@@ -116,6 +116,49 @@ bool IsNullPose(const T pos[3], const T quat[4]) {
116
116
}
117
117
118
118
119
+ // set ids, check for repeated names
120
+ template <class T >
121
+ static void processlist (mjListKeyMap& ids, vector<T*>& list,
122
+ mjtObj type, bool checkrepeat = true ) {
123
+ // assign ids for regular elements
124
+ if (type < mjNOBJECT) {
125
+ for (size_t i=0 ; i < list.size (); i++) {
126
+ // check for incompatible id setting; SHOULD NOT OCCUR
127
+ if (list[i]->id != -1 && list[i]->id != i) {
128
+ throw mjCError (list[i], " incompatible id in %s array, position %d" , mju_type2Str (type), i);
129
+ }
130
+
131
+ // id equals position in array
132
+ list[i]->id = i;
133
+
134
+ // add to ids map
135
+ ids[type][list[i]->name ] = i;
136
+ }
137
+ }
138
+
139
+ // check for repeated names
140
+ if (checkrepeat) {
141
+ // created vectors with all names
142
+ vector<string> allnames;
143
+ for (size_t i=0 ; i < list.size (); i++) {
144
+ if (!list[i]->name .empty ()) {
145
+ allnames.push_back (list[i]->name );
146
+ }
147
+ }
148
+
149
+ // sort and check for duplicates
150
+ if (allnames.size () > 1 ) {
151
+ std::sort (allnames.begin (), allnames.end ());
152
+ auto adjacent = std::adjacent_find (allnames.begin (), allnames.end ());
153
+ if (adjacent != allnames.end ()) {
154
+ string msg = " repeated name '" + *adjacent + " ' in " + mju_type2Str (type);
155
+ throw mjCError (nullptr , " %s" , msg.c_str ());
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+
119
162
} // namespace
120
163
121
164
// ---------------------------------- CONSTRUCTOR AND DESTRUCTOR ------------------------------------
@@ -490,7 +533,7 @@ void mjCModel::RemoveFromList(std::vector<T*>& list, const mjCModel& other) {
490
533
element->ResolveReferences (this );
491
534
} catch (mjCError err) {
492
535
ids[element->elemtype ].erase (element->name );
493
- delete element;
536
+ element-> Release () ;
494
537
list.erase (list.begin () + i);
495
538
nlist--;
496
539
i--;
@@ -515,6 +558,52 @@ void mjCModel::DeleteAll<mjCKey>(std::vector<mjCKey*>& elements) {
515
558
516
559
517
560
561
+ template <class T >
562
+ void mjCModel::MarkPluginInstance (std::unordered_map<std::string, bool >& instances,
563
+ const std::vector<T*>& list) {
564
+ for (const auto & element : list) {
565
+ if (!element->plugin_instance_name .empty ()) {
566
+ instances[element->plugin_instance_name ] = true ;
567
+ }
568
+ }
569
+ }
570
+
571
+
572
+
573
+ void mjCModel::RemovePlugins () {
574
+ // store elements that reference a plugin instance
575
+ std::unordered_map<std::string, bool > instances;
576
+ MarkPluginInstance (instances, bodies_);
577
+ MarkPluginInstance (instances, geoms_);
578
+ MarkPluginInstance (instances, meshes_);
579
+ MarkPluginInstance (instances, actuators_);
580
+ MarkPluginInstance (instances, sensors_);
581
+
582
+ // remove plugins that are not referenced
583
+ int nlist = (int )plugins_.size ();
584
+ int removed = 0 ;
585
+ for (int i = 0 ; i < nlist; i++) {
586
+ if (plugins_[i]->name .empty ()) {
587
+ continue ;
588
+ }
589
+ if (instances.find (plugins_[i]->name ) == instances.end ()) {
590
+ ids[plugins_[i]->elemtype ].erase (plugins_[i]->name );
591
+ plugins_[i]->Release ();
592
+ plugins_.erase (plugins_.begin () + i);
593
+ nlist--;
594
+ i--;
595
+ removed++;
596
+ }
597
+ }
598
+
599
+ // if any elements were removed, update ids using processlist
600
+ if (removed > 0 && !plugins_.empty ()) {
601
+ processlist (ids, plugins_, plugins_[0 ]->elemtype , /* checkrepeat=*/ false );
602
+ }
603
+ }
604
+
605
+
606
+
518
607
mjCModel& mjCModel::operator -=(const mjCBody& subtree) {
519
608
mjCModel oldmodel (*this );
520
609
@@ -550,6 +639,7 @@ mjCModel& mjCModel::operator-=(const mjCBody& subtree) {
550
639
RemoveFromList (equalities_, oldmodel);
551
640
RemoveFromList (actuators_, oldmodel);
552
641
RemoveFromList (sensors_, oldmodel);
642
+ RemovePlugins ();
553
643
554
644
// restore to the original state
555
645
if (!compiled) {
@@ -3923,49 +4013,6 @@ static void reassignid(vector<T*>& list) {
3923
4013
}
3924
4014
3925
4015
3926
- // set ids, check for repeated names
3927
- template <class T >
3928
- static void processlist (mjListKeyMap& ids, vector<T*>& list,
3929
- mjtObj type, bool checkrepeat = true ) {
3930
- // assign ids for regular elements
3931
- if (type < mjNOBJECT) {
3932
- for (size_t i=0 ; i < list.size (); i++) {
3933
- // check for incompatible id setting; SHOULD NOT OCCUR
3934
- if (list[i]->id != -1 && list[i]->id != i) {
3935
- throw mjCError (list[i], " incompatible id in %s array, position %d" , mju_type2Str (type), i);
3936
- }
3937
-
3938
- // id equals position in array
3939
- list[i]->id = i;
3940
-
3941
- // add to ids map
3942
- ids[type][list[i]->name ] = i;
3943
- }
3944
- }
3945
-
3946
- // check for repeated names
3947
- if (checkrepeat) {
3948
- // created vectors with all names
3949
- vector<string> allnames;
3950
- for (size_t i=0 ; i < list.size (); i++) {
3951
- if (!list[i]->name .empty ()) {
3952
- allnames.push_back (list[i]->name );
3953
- }
3954
- }
3955
-
3956
- // sort and check for duplicates
3957
- if (allnames.size () > 1 ) {
3958
- std::sort (allnames.begin (), allnames.end ());
3959
- auto adjacent = std::adjacent_find (allnames.begin (), allnames.end ());
3960
- if (adjacent != allnames.end ()) {
3961
- string msg = " repeated name '" + *adjacent + " ' in " + mju_type2Str (type);
3962
- throw mjCError (nullptr , " %s" , msg.c_str ());
3963
- }
3964
- }
3965
- }
3966
- }
3967
-
3968
-
3969
4016
3970
4017
// set object ids, check for repeated names
3971
4018
void mjCModel::ProcessLists (bool checkrepeat) {
0 commit comments