diff --git a/src/Mod/PartDesign/App/ShapeBinder.cpp b/src/Mod/PartDesign/App/ShapeBinder.cpp index 25720172a6..a79c4317e6 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.cpp +++ b/src/Mod/PartDesign/App/ShapeBinder.cpp @@ -23,11 +23,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include +#include #include #endif #include "ShapeBinder.h" +#include #include #ifndef M_PI @@ -44,15 +46,19 @@ ShapeBinder::ShapeBinder() { ADD_PROPERTY_TYPE(Support, (0,0), "",(App::PropertyType)(App::Prop_None),"Support of the geometry"); Placement.setStatus(App::Property::Hidden, true); + ADD_PROPERTY_TYPE(TraceSupport, (false), "", App::Prop_None, "Trace support shape"); } ShapeBinder::~ShapeBinder() { + this->connectDocumentChangedObject.disconnect(); } short int ShapeBinder::mustExecute(void) const { - if(Support.isTouched()) + if (Support.isTouched()) + return 1; + if (TraceSupport.isTouched()) return 1; return Part::Feature::mustExecute(); @@ -60,16 +66,29 @@ short int ShapeBinder::mustExecute(void) const { App::DocumentObjectExecReturn* ShapeBinder::execute(void) { - if(! this->isRestoring()){ + if (!this->isRestoring()) { Part::Feature* obj = nullptr; std::vector subs; ShapeBinder::getFilteredReferences(&Support, obj, subs); //if we have a link we rebuild the shape, but we change nothing if we are a simple copy - if(obj) { + if (obj) { Part::TopoShape shape = ShapeBinder::buildShapeFromReferences(obj, subs); Base::Placement placement(shape.getTransform()); Shape.setValue(shape); + + if (TraceSupport.getValue()) { + chain.clear(); + std::vector list = getInListRecursive(); + chain.insert(chain.end(), list.begin(), list.end()); + list = obj->getInListRecursive(); + chain.insert(chain.end(), list.begin(), list.end()); + + // this is the inverted global placement of the parent group ... + placement = this->globalPlacement() * Placement.getValue().inverse(); + // multiplied with the global placement of the support shape + placement = placement.inverse() * obj->globalPlacement(); + } Placement.setValue(placement); } } @@ -77,76 +96,75 @@ App::DocumentObjectExecReturn* ShapeBinder::execute(void) { return Part::Feature::execute(); } -void ShapeBinder::getFilteredReferences(App::PropertyLinkSubList* prop, Part::Feature*& obj, std::vector< std::string >& subobjects) { - +void ShapeBinder::getFilteredReferences(App::PropertyLinkSubList* prop, Part::Feature*& obj, + std::vector< std::string >& subobjects) +{ obj = nullptr; subobjects.clear(); auto objs = prop->getValues(); auto subs = prop->getSubValues(); - if(objs.empty()) { + if (objs.empty()) { return; } //we only allow one part feature, so get the first one we find size_t index = 0; - while(index < objs.size() && !objs[index]->isDerivedFrom(Part::Feature::getClassTypeId())) + while (index < objs.size() && !objs[index]->isDerivedFrom(Part::Feature::getClassTypeId())) index++; //do we have any part feature? - if(index >= objs.size()) + if (index >= objs.size()) return; obj = static_cast(objs[index]); //if we have no subshpape we use the whole shape - if(subs[index].empty()) { - return; + if (subs[index].empty()) { + return; } //collect all subshapes for the object index = 0; - for(std::string sub : subs) { + for (std::string sub : subs) { //we only allow subshapes from a single Part::Feature - if(objs[index] != obj) + if (objs[index] != obj) continue; //in this mode the full shape is not allowed, as we already started the subshape //processing - if(sub.empty()) + if (sub.empty()) continue; subobjects.push_back(sub); } } - Part::TopoShape ShapeBinder::buildShapeFromReferences( Part::Feature* obj, std::vector< std::string > subs) { - if(!obj) + if (!obj) return TopoDS_Shape(); - if(subs.empty()) + if (subs.empty()) return obj->Shape.getShape(); //if we use multiple subshapes we build a shape from them by fusing them together Part::TopoShape base; std::vector operators; - for(std::string sub : subs) { - - if(base.isNull()) + for (std::string sub : subs) { + if (base.isNull()) base = obj->Shape.getShape().getSubShape(sub.c_str()); else operators.push_back(obj->Shape.getShape().getSubShape(sub.c_str())); } try { - if(!operators.empty() && !base.isNull()) + if (!operators.empty() && !base.isNull()) return base.fuse(operators); } - catch(...) { + catch (...) { return base; } return base; @@ -159,3 +177,26 @@ void ShapeBinder::handleChangedPropertyType(Base::XMLReader &reader, const char Support.Restore(reader); } } + +void ShapeBinder::onSettingDocument() +{ + App::Document* document = getDocument(); + if (document) { + this->connectDocumentChangedObject = document->signalChangedObject.connect(boost::bind + (&ShapeBinder::slotChangedObject, this, _1, _2)); + } +} + +void ShapeBinder::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop) +{ + if (this == &Obj) + return; + if (!TraceSupport.getValue()) + return; + if (!Prop.getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())) + return; + auto it = std::find(chain.begin(), chain.end(), &Obj); + if (it != chain.end()) { + touch(); + } +} diff --git a/src/Mod/PartDesign/App/ShapeBinder.h b/src/Mod/PartDesign/App/ShapeBinder.h index 36afb524cb..1f72cc5aad 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.h +++ b/src/Mod/PartDesign/App/ShapeBinder.h @@ -25,6 +25,7 @@ #define PARTDESIGN_DATUMSHAPE_H #include +#include #include #include @@ -48,6 +49,7 @@ public: virtual ~ShapeBinder(); App::PropertyLinkSubListGlobal Support; + App::PropertyBool TraceSupport; static void getFilteredReferences(App::PropertyLinkSubList* prop, Part::Feature*& object, std::vector< std::string >& subobjects); static Part::TopoShape buildShapeFromReferences(Feature* obj, std::vector< std::string > subs); @@ -60,6 +62,14 @@ protected: virtual void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, App::Property * prop); virtual short int mustExecute(void) const; virtual App::DocumentObjectExecReturn* execute(void); + +private: + void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop); + virtual void onSettingDocument(); + + std::vector chain; + typedef boost::signals::connection Connection; + Connection connectDocumentChangedObject; }; } //namespace PartDesign