src/Screens/ModelEditorScreen.cpp
// try to delete an undoable-model's current selection
//
// "try", because some things are difficult to delete from OpenSim models
try to delete an undoable-model's current selection
"try", because some things are difficult to delete from OpenSim models
try to delete an undoable - model ' s current selection " try " because some things are difficult to delete from OpenSim models
void actionTryDeleteSelectionFromEditedModel(UndoableUiModel& uim) {
        OpenSim::Component* selected = uim.updSelected();
        if (!selected) {
            return;  
        }
        if (!selected->hasOwner()) {
            return;
        }
        OpenSim::Component* owner = const_cast<OpenSim::Component*>(&selected->getOwner());
         this is uglier than it should be because OpenSim doesn't have a uniform approach for
         storing Components in the model hierarchy. Some Components might be in specialized sets,
         some Components might be in std::vectors, some might be solo children, etc.
         the challenge is knowing what component is selected, what kind of parent it's contained
         within, and how that particular component type can be safely deleted from that particular
         parent type without leaving the overall Model in an invalid state
        if (auto* js = dynamic_cast<OpenSim::JointSet*>(owner); js) {
             delete an OpenSim::Joint from its owning OpenSim::JointSet
            deleteItemFromSet(*js, static_cast<OpenSim::Joint*>(selected));
            uim.setDirty(true);
            uim.declareDeathOf(selected);
        } else if (auto* bs = dynamic_cast<OpenSim::BodySet*>(owner); bs) {
             delete an OpenSim::Body from its owning OpenSim::BodySet
            log::error(
                "cannot delete %s: deleting OpenSim::Body is not supported: it segfaults in the OpenSim API",
                selected->getName().c_str());
             segfaults:
             uim.before_modifying_model();
             delete_item_from_set_in_model(*bs, static_cast<OpenSim::Body*>(selected));
             uim.model().clearConnections();
             uim.declare_death_of(selected);
             uim.after_modifying_model();
        } else if (auto* wos = dynamic_cast<OpenSim::WrapObjectSet*>(owner); wos) {
             delete an OpenSim::WrapObject from its owning OpenSim::WrapObjectSet
            log::error(
                "cannot delete %s: deleting an OpenSim::WrapObject is not supported: faults in the OpenSim API until after AK's connection checking addition",
                selected->getName().c_str());
             also, this implementation needs to iterate over all pathwraps in the model
             and disconnect them from the GeometryPath that uses them; otherwise, the model
             will explode
        } else if (auto* cs = dynamic_cast<OpenSim::ControllerSet*>(owner); cs) {
             delete an OpenSim::Controller from its owning OpenSim::ControllerSet
            uim.setDirty(true);
            deleteItemFromSet(*cs, static_cast<OpenSim::Controller*>(selected));            
            uim.declareDeathOf(selected);
        } else if (auto* conss = dynamic_cast<OpenSim::ConstraintSet*>(owner); cs) {
             delete an OpenSim::Constraint from its owning OpenSim::ConstraintSet
            uim.setDirty(true);
            deleteItemFromSet(*conss, static_cast<OpenSim::Constraint*>(selected));
            uim.declareDeathOf(selected);
        } else if (auto* fs = dynamic_cast<OpenSim::ForceSet*>(owner); fs) {
             delete an OpenSim::Force from its owning OpenSim::ForceSet
            uim.setDirty(true);
            deleteItemFromSet(*fs, static_cast<OpenSim::Force*>(selected));
            uim.declareDeathOf(selected);
        } else if (auto* ms = dynamic_cast<OpenSim::MarkerSet*>(owner); ms) {
             delete an OpenSim::Marker from its owning OpenSim::MarkerSet
            uim.setDirty(true);
            deleteItemFromSet(*ms, static_cast<OpenSim::Marker*>(selected));
            uim.declareDeathOf(selected);
        } else if (auto* cgs = dynamic_cast<OpenSim::ContactGeometrySet*>(owner); cgs) {
             delete an OpenSim::ContactGeometry from its owning OpenSim::ContactGeometrySet
            uim.setDirty(true);
            deleteItemFromSet(*cgs, static_cast<OpenSim::ContactGeometry*>(selected));
            uim.declareDeathOf(selected);
        } else if (auto* ps = dynamic_cast<OpenSim::ProbeSet*>(owner); ps) {
             delete an OpenSim::Probe from its owning OpenSim::ProbeSet
            uim.setDirty(true);
            deleteItemFromSet(*ps, static_cast<OpenSim::Probe*>(selected));
            uim.declareDeathOf(selected);
        } else if (auto const* geom = findAncestorWithType<OpenSim::Geometry>(selected); geom) {
             delete an OpenSim::Geometry from its owning OpenSim::Frame
            if (auto const* frame = findAncestorWithType<OpenSim::Frame>(geom); frame) {
                 its owner is a frame, which holds the geometry in a list property
                 make a copy of the property containing the geometry and
                 only copy over the not-deleted geometry into the copy
                 this is necessary because OpenSim::Property doesn't seem
                 to support list element deletion, but does support full
                 assignment
                uim.setDirty(true);
                auto& mframe = const_cast<OpenSim::Frame&>(*frame);
                OpenSim::ObjectProperty<OpenSim::Geometry>& prop =
                    static_cast<OpenSim::ObjectProperty<OpenSim::Geometry>&>(mframe.updProperty_attached_geometry());
                std::unique_ptr<OpenSim::ObjectProperty<OpenSim::Geometry>> copy{prop.clone()};
                copy->clear();
                for (int i = 0; i < prop.size(); ++i) {
                    OpenSim::Geometry& g = prop[i];
                    if (&g != geom) {
                        copy->adoptAndAppendValue(g.clone());
                    }
                }
                prop.assign(*copy);
                uim.declareDeathOf(selected);
            }
        } else if (auto* pp = dynamic_cast<OpenSim::PathPoint*>(selected); pp) {
            if (auto* gp = dynamic_cast<OpenSim::GeometryPath*>(owner); gp) {
                OpenSim::PathPointSet const& pps = gp->getPathPointSet();
                int idx = -1;
                for (int i = 0; i < pps.getSize(); ++i) {
                    if (&pps.get(i) == pp) {
                        idx = i;
                    }
                }
                if (idx != -1) {
                    uim.setDirty(true);
                    gp->deletePathPoint(uim.getState(), idx);
                    uim.declareDeathOf(selected);
                }
            }
        }
        uim.updateIfDirty();
    }
void actionTryDeleteSelectionFromEditedModel ( UndoableUiModel & uim ) { OpenSim :: Component * selected = uim . updSelected ( ) ; if ( ! selected ) { return ; } if ( ! selected -> hasOwner ( ) ) { return ; } OpenSim :: Component * owner = const_cast < OpenSim :: Component * > ( & selected -> getOwner ( ) ) ; if ( auto * js = dynamic_cast < OpenSim :: JointSet * > ( owner ) ; js ) { deleteItemFromSet ( * js , static_cast < OpenSim :: Joint * > ( selected ) ) ; uim . setDirty ( true ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * bs = dynamic_cast < OpenSim :: BodySet * > ( owner ) ; bs ) { log :: error ( " " , selected -> getName ( ) . c_str ( ) ) ; } else if ( auto * wos = dynamic_cast < OpenSim :: WrapObjectSet * > ( owner ) ; wos ) { log :: error ( " " , selected -> getName ( ) . c_str ( ) ) ; } else if ( auto * cs = dynamic_cast < OpenSim :: ControllerSet * > ( owner ) ; cs ) { uim . setDirty ( true ) ; deleteItemFromSet ( * cs , static_cast < OpenSim :: Controller * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * conss = dynamic_cast < OpenSim :: ConstraintSet * > ( owner ) ; cs ) { uim . setDirty ( true ) ; deleteItemFromSet ( * conss , static_cast < OpenSim :: Constraint * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * fs = dynamic_cast < OpenSim :: ForceSet * > ( owner ) ; fs ) { uim . setDirty ( true ) ; deleteItemFromSet ( * fs , static_cast < OpenSim :: Force * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * ms = dynamic_cast < OpenSim :: MarkerSet * > ( owner ) ; ms ) { uim . setDirty ( true ) ; deleteItemFromSet ( * ms , static_cast < OpenSim :: Marker * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * cgs = dynamic_cast < OpenSim :: ContactGeometrySet * > ( owner ) ; cgs ) { uim . setDirty ( true ) ; deleteItemFromSet ( * cgs , static_cast < OpenSim :: ContactGeometry * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto * ps = dynamic_cast < OpenSim :: ProbeSet * > ( owner ) ; ps ) { uim . setDirty ( true ) ; deleteItemFromSet ( * ps , static_cast < OpenSim :: Probe * > ( selected ) ) ; uim . declareDeathOf ( selected ) ; } else if ( auto const * geom = findAncestorWithType < OpenSim :: Geometry > ( selected ) ; geom ) { if ( auto const * frame = findAncestorWithType < OpenSim :: Frame > ( geom ) ; frame ) { uim . setDirty ( true ) ; auto & mframe = const_cast < OpenSim :: Frame & > ( * frame ) ; OpenSim :: ObjectProperty < OpenSim :: Geometry > & prop = static_cast < OpenSim :: ObjectProperty < OpenSim :: Geometry > & > ( mframe . updProperty_attached_geometry ( ) ) ; std :: unique_ptr < OpenSim :: ObjectProperty < OpenSim :: Geometry > > copy { prop . clone ( ) } ; copy -> clear ( ) ; for ( int i = 0 ; i < prop . size ( ) ; ++ i ) { OpenSim :: Geometry & g = prop [ i ] ; if ( & g != geom ) { copy -> adoptAndAppendValue ( g . clone ( ) ) ; } } prop . assign ( * copy ) ; uim . declareDeathOf ( selected ) ; } } else if ( auto * pp = dynamic_cast < OpenSim :: PathPoint * > ( selected ) ; pp ) { if ( auto * gp = dynamic_cast < OpenSim :: GeometryPath * > ( owner ) ; gp ) { OpenSim :: PathPointSet const & pps = gp -> getPathPointSet ( ) ; int idx = -1 ; for ( int i = 0 ; i < pps . getSize ( ) ; ++ i ) { if ( & pps . get ( i ) == pp ) { idx = i ; } } if ( idx != -1 ) { uim . setDirty ( true ) ; gp -> deletePathPoint ( uim . getState ( ) , idx ) ; uim . declareDeathOf ( selected ) ; } } } uim . updateIfDirty ( ) ; }
try to delete an undoable-model's current selection
"try", because some things are difficult to delete from OpenSim models
try to delete an undoable - model ' s current selection " try " because some things are difficult to delete from OpenSim models
// nothing selected, so nothing can be deleted // the selected item isn't owned by anything, so it can't be deleted from its // owner's hierarchy // else: an OpenSim::Component is selected and we need to figure out how to remove it // from its parent // // this is uglier than it should be because OpenSim doesn't have a uniform approach for // storing Components in the model hierarchy. Some Components might be in specialized sets, // some Components might be in std::vectors, some might be solo children, etc. // // the challenge is knowing what component is selected, what kind of parent it's contained // within, and how that particular component type can be safely deleted from that particular // parent type without leaving the overall Model in an invalid state // delete an OpenSim::Joint from its owning OpenSim::JointSet // delete an OpenSim::Body from its owning OpenSim::BodySet // segfaults: // uim.before_modifying_model(); // delete_item_from_set_in_model(*bs, static_cast<OpenSim::Body*>(selected)); // uim.model().clearConnections(); // uim.declare_death_of(selected); // uim.after_modifying_model(); // delete an OpenSim::WrapObject from its owning OpenSim::WrapObjectSet // also, this implementation needs to iterate over all pathwraps in the model // and disconnect them from the GeometryPath that uses them; otherwise, the model // will explode // delete an OpenSim::Controller from its owning OpenSim::ControllerSet // delete an OpenSim::Constraint from its owning OpenSim::ConstraintSet // delete an OpenSim::Force from its owning OpenSim::ForceSet // delete an OpenSim::Marker from its owning OpenSim::MarkerSet // delete an OpenSim::ContactGeometry from its owning OpenSim::ContactGeometrySet // delete an OpenSim::Probe from its owning OpenSim::ProbeSet // delete an OpenSim::Geometry from its owning OpenSim::Frame // its owner is a frame, which holds the geometry in a list property // make a copy of the property containing the geometry and // only copy over the not-deleted geometry into the copy // // this is necessary because OpenSim::Property doesn't seem // to support list element deletion, but does support full // assignment