From 32d45ac97d6af96c18cec3646554ccff1cd141fb Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Fri, 16 Apr 2021 16:56:25 +0800 Subject: [PATCH] App/Part: fix App::Link visibility detection in PartFeature::getTopoShape() --- src/App/Link.cpp | 65 ++++++++++++++++++++++++++++++-- src/App/Link.h | 5 +++ src/Mod/Part/App/PartFeature.cpp | 53 ++++++++++++++++++++++---- 3 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/App/Link.cpp b/src/App/Link.cpp index e9d9d1c6a1..8f4eb62303 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -2177,10 +2177,12 @@ void LinkBaseExtension::expandSubname(std::string &subname) const { } static bool isExcludedProperties(const char *name) { -#define CHECK_EXCLUDE_PROP(_name) if(strcmp(name,#_name)==0) return true; - CHECK_EXCLUDE_PROP(Shape); - CHECK_EXCLUDE_PROP(Proxy); - CHECK_EXCLUDE_PROP(Placement); + if (boost::equals(name, "Shape")) + return true; + if (boost::equals(name, "Proxy")) + return true; + if (boost::equals(name, "Placement")) + return true; return false; } @@ -2204,6 +2206,61 @@ Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const return nullptr; } +std::vector LinkBaseExtension::getHiddenSubnames( + const App::DocumentObject *obj, const char *prefix) +{ + std::vector res; + if(!obj || !obj->getNameInDocument()) + return res; + PropertyLinkSubHidden *prop; + int depth=0; + while((prop=Base::freecad_dynamic_cast( + obj->getPropertyByName("ColoredElements")))) + { + for(auto &v : prop->getShadowSubs()) { + if(prefix && !boost::starts_with(v.first,prefix) && !boost::starts_with(v.second,prefix)) + continue; + auto &s = v.second; + if(boost::ends_with(s,DocumentObject::hiddenMarker())) + res.push_back(s.substr(0,s.size()-DocumentObject::hiddenMarker().size())); + } + auto o = Base::freecad_dynamic_cast(prop->getContainer()); + if(!o) + break; + o = o->getLinkedObject(false); + if(o==obj || !GetApplication().checkLinkDepth(++depth,true)) + break; + obj = o; + } + return res; +} + +bool LinkBaseExtension::isSubnameHidden(const App::DocumentObject *obj, const char *subname) +{ + if(!obj || !obj->getNameInDocument() || !subname || !subname[0]) + return false; + PropertyLinkSubHidden *prop; + int depth=0; + while((prop=Base::freecad_dynamic_cast( + obj->getPropertyByName("ColoredElements")))) + { + for(auto &v : prop->getShadowSubs()) { + if((boost::starts_with(v.first,subname) || boost::starts_with(v.second,subname)) + && boost::ends_with(v.second, DocumentObject::hiddenMarker())) + return true; + } + auto o = Base::freecad_dynamic_cast(prop->getContainer()); + if(!o) + break; + o = o->getLinkedObject(false); + if(o==obj || !GetApplication().checkLinkDepth(++depth,true)) + break; + obj = o; + } + return false; +} + + bool LinkBaseExtension::isLinkMutated() const { return getLinkCopyOnChangeValue() != CopyOnChangeDisabled diff --git a/src/App/Link.h b/src/App/Link.h index f0aa368a74..b4ab85ccfa 100644 --- a/src/App/Link.h +++ b/src/App/Link.h @@ -304,6 +304,11 @@ public: int getElementIndex(const char *subname, const char **psubname=nullptr) const; void elementNameFromIndex(int idx, std::ostream &ss) const; + static std::vector getHiddenSubnames( + const App::DocumentObject *obj, const char *prefix=0); + + static bool isSubnameHidden(const App::DocumentObject *obj, const char *subname); + DocumentObject *getContainer(); const DocumentObject *getContainer() const; diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index a51dc8316b..d1b9190fde 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -524,23 +524,60 @@ TopoDS_Shape Feature::getShape(const App::DocumentObject *obj, const char *subna return getTopoShape(obj,subname,needSubElement,pmat,powner,resolveLink,transform,true).getShape(); } -#if 0 // remove the function as it's not used static inline bool checkLink(const App::DocumentObject *obj) { return obj->getExtensionByType(obj) || obj->getExtensionByType(obj); } -#endif static bool checkLinkVisibility(std::set &hiddens, bool check, const App::DocumentObject *&lastLink, const App::DocumentObject *obj, const char *subname) { - (void)hiddens; - (void)check; - (void)lastLink; - (void)obj; - (void)subname; - //Stub to be filled in subsequent patches; + if(!obj || !obj->getNameInDocument()) + return false; + + if(checkLink(obj)) { + lastLink = obj; + for(auto &s : App::LinkBaseExtension::getHiddenSubnames(obj)) + hiddens.emplace(std::move(s)); + } + + if(!subname || !subname[0]) + return true; + + auto element = Data::ComplexGeoData::findElementName(subname); + std::string sub(subname,element-subname); + + for(auto pos=sub.find('.');pos!=std::string::npos;pos=sub.find('.',pos+1)) { + char c = sub[pos+1]; + sub[pos+1] = 0; + + for(auto it=hiddens.begin();it!=hiddens.end();) { + if(!boost::starts_with(*it,CharRange(sub.c_str(),sub.c_str()+pos+1))) + it = hiddens.erase(it); + else { + if(check && it->size()==pos+1) + return false; + ++it; + } + } + auto sobj = obj->getSubObject(sub.c_str()); + if(!sobj || !sobj->getNameInDocument()) + return false; + if(checkLink(sobj)) { + for(auto &s : App::LinkBaseExtension::getHiddenSubnames(sobj)) + hiddens.insert(std::string(sub)+s); + lastLink = sobj; + } + sub[pos+1] = c; + } + + std::set res; + for(auto &s : hiddens) { + if(s.size()>sub.size()) + res.insert(s.c_str()+sub.size()); + } + hiddens = std::move(res); return true; }