@@ -180,3 +180,94 @@ int WrapObject::wrapPathSegment(const SimTK::State& s,
180180
181181 return return_code;
182182}
183+
184+ void WrapObject::updateFromXMLNode (SimTK::Xml::Element& node,
185+ int versionNumber) {
186+ int documentVersion = versionNumber;
187+ if (documentVersion < XMLDocument::getLatestVersion ()) {
188+ if (documentVersion < 30515 ) {
189+ // Replace 3.3 display_preference, color, and VisibleObject with
190+ // Appearance's visible and color.
191+ // We ignore most of VisibleObject's other properties (e.g.,
192+ // transform), since it would be misleading to draw the wrap object
193+ // in the wrong place.
194+ SimTK::Xml::Element appearanceNode (" Appearance" );
195+ // Use the correct defaults for WrapObject's appearance, which
196+ // are different from the default Appearance.
197+ SimTK::Xml::Element color (" color" );
198+ color.setValue (" 0 1 1" ); // SimTK::Cyan
199+ appearanceNode.insertNodeAfter (appearanceNode.element_end (),
200+ color);
201+ SimTK::Xml::Element defaultOpacity (" opacity" );
202+ defaultOpacity.setValue (" 0.5" );
203+ appearanceNode.insertNodeAfter (appearanceNode.element_end (),
204+ defaultOpacity);
205+ SimTK::Xml::Element defaultSurfProp (" SurfaceProperties" );
206+ appearanceNode.insertNodeAfter (appearanceNode.element_end (),
207+ defaultSurfProp);
208+ SimTK::Xml::Element rep (" representation" );
209+ rep.setValue (" 3" ); // VisualRepresentation::DrawSurface
210+ defaultSurfProp.insertNodeAfter (defaultSurfProp.element_end (), rep);
211+ bool appearanceModified = false ;
212+
213+ // color.
214+ SimTK::Xml::element_iterator colorIter =
215+ node.element_begin (" color" );
216+ if (colorIter != node.element_end ()) {
217+ color.setValue (colorIter->getValue ());
218+ node.removeNode (colorIter);
219+ appearanceModified = true ;
220+ }
221+
222+ // display_preference -> visible, representation
223+ SimTK::Xml::Element visibleNode (" visible" );
224+ SimTK::Xml::element_iterator dispPrefIter =
225+ node.element_begin (" display_preference" );
226+ if (dispPrefIter != node.element_end ()) {
227+ if (dispPrefIter->getValueAs <int >() == 0 ) {
228+ visibleNode.setValue (" false" );
229+ appearanceModified = true ;
230+ } else if (dispPrefIter->getValueAs <int >() < 4 ) {
231+ // Set `representation`.
232+ // If the value is 4, we use 3 instead, which is the
233+ // default (above).
234+ rep.setValue (dispPrefIter->getValue ());
235+ appearanceModified = true ;
236+ }
237+ node.removeNode (dispPrefIter);
238+ }
239+ SimTK::Xml::element_iterator visObjIter =
240+ node.element_begin (" VisibleObject" );
241+ if (visObjIter != node.element_end ()) {
242+ SimTK::Xml::element_iterator voDispPrefIter =
243+ visObjIter->element_begin (" display_preference" );
244+ if (voDispPrefIter != visObjIter->element_end ()) {
245+ if (voDispPrefIter->getValueAs <int >() == 0 ) {
246+ visibleNode.setValue (" false" );
247+ appearanceModified = true ;
248+ } else if (rep.getValue () == " 3" &&
249+ voDispPrefIter->getValueAs <int >() < 4 ) {
250+ // Set `representation`.
251+ // The representation still has its default value,
252+ // meaning the user only specified the inner display
253+ // preference, therefore we should use this one.
254+ rep.setValue (voDispPrefIter->getValue ());
255+ appearanceModified = true ;
256+ }
257+ }
258+ node.removeNode (visObjIter);
259+ }
260+ if (visibleNode.getValue () != " " ) {
261+ appearanceNode.insertNodeAfter (appearanceNode.element_end (),
262+ visibleNode);
263+ appearanceModified = true ;
264+ }
265+
266+ // Add Appearance to the WrapObject.
267+ if (appearanceModified) {
268+ node.insertNodeAfter (node.element_end (), appearanceNode);
269+ }
270+ }
271+ }
272+ Super::updateFromXMLNode (node, versionNumber);
273+ }
0 commit comments