PartDesign: Make Base Feature compatible with GeoFeatureGroup. fixes #0003080
The Original BaseFeature implementation had some serious issues with scoped links. It failed completely for e.g. sketches on the BaseFeature as it made a local link to refere to a out of body object. The only solution to make this work correctly is to add a proxy object into the body which is alloed to exactly that, to link outside oof the body. Something like shapebinder.
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include "ShapeBinder.h"
|
||||
|
||||
#include "Body.h"
|
||||
#include "FeatureBase.h"
|
||||
#include "BodyPy.h"
|
||||
|
||||
using namespace PartDesign;
|
||||
@@ -109,8 +110,7 @@ void Body::onChanged(const App::Property *prop)
|
||||
|
||||
short Body::mustExecute() const
|
||||
{
|
||||
if ( Tip.isTouched() ||
|
||||
BaseFeature.isTouched() ) {
|
||||
if ( Tip.isTouched() ) {
|
||||
return 1;
|
||||
}
|
||||
return Part::BodyBase::mustExecute();
|
||||
@@ -133,18 +133,13 @@ App::DocumentObject* Body::getPrevFeature(App::DocumentObject *start) const
|
||||
|
||||
App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start)
|
||||
{
|
||||
App::DocumentObject* baseFeature = BaseFeature.getValue();
|
||||
|
||||
if ( !start ) { // default to tip
|
||||
start = Tip.getValue();
|
||||
}
|
||||
|
||||
if ( !start ) { // No Tip
|
||||
return nullptr;
|
||||
} else if ( start == baseFeature ) { // The base feature always considered as the first solid
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!hasObject(start))
|
||||
return nullptr;
|
||||
|
||||
@@ -156,15 +151,13 @@ App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start)
|
||||
|
||||
if (rvIt != features.rend()) { // the solid found in model list
|
||||
return *rvIt;
|
||||
} else { // if solid is not present in the list the previous one is baseFeature
|
||||
return baseFeature; // return it either it's set or nullptr
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
|
||||
{
|
||||
App::DocumentObject* baseFeature = BaseFeature.getValue();
|
||||
|
||||
if ( !start ) { // default to tip
|
||||
start = Tip.getValue();
|
||||
}
|
||||
@@ -178,14 +171,9 @@ App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
|
||||
const std::vector<App::DocumentObject*> & features = Group.getValues();
|
||||
std::vector<App::DocumentObject*>::const_iterator startIt;
|
||||
|
||||
if ( start == baseFeature ) {
|
||||
// Handle the base feature, it's always considered to be solid
|
||||
startIt = features.begin();
|
||||
} else {
|
||||
startIt = std::find ( features.begin(), features.end(), start );
|
||||
assert ( startIt != features.end() );
|
||||
startIt++;
|
||||
}
|
||||
startIt = std::find ( features.begin(), features.end(), start );
|
||||
assert ( startIt != features.end() );
|
||||
startIt++;
|
||||
|
||||
if (startIt == features.end() ) { // features list is empty
|
||||
return nullptr;
|
||||
@@ -195,9 +183,9 @@ App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
|
||||
|
||||
if (rvIt != features.end()) { // the solid found in model list
|
||||
return *rvIt;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Body::isAfterInsertPoint(App::DocumentObject* feature) {
|
||||
@@ -299,18 +287,8 @@ std::vector< App::DocumentObject* > Body::addObjects(std::vector< App::DocumentO
|
||||
|
||||
void Body::insertObject(App::DocumentObject* feature, App::DocumentObject* target, bool after)
|
||||
{
|
||||
if (target) {
|
||||
if (target == BaseFeature.getValue()) {
|
||||
// Handle the insertion relative to the base feature in a special way
|
||||
if (after) {
|
||||
target = nullptr;
|
||||
} else {
|
||||
throw Base::Exception("Body: impossible to insert before the base object");
|
||||
}
|
||||
} else if (!hasObject (target)) {
|
||||
// Check if the target feature belongs to the body
|
||||
throw Base::Exception("Body: the feature we should insert relative to is not part of that body");
|
||||
}
|
||||
if (target && !hasObject (target)) {
|
||||
throw Base::Exception("Body: the feature we should insert relative to is not part of that body");
|
||||
}
|
||||
|
||||
//ensure that all origin links are ok
|
||||
@@ -420,8 +398,7 @@ App::DocumentObjectExecReturn *Body::execute(void)
|
||||
|
||||
Part::TopoShape tipShape;
|
||||
if ( tip ) {
|
||||
if ( !tip->getTypeId().isDerivedFrom ( PartDesign::Feature::getClassTypeId() )
|
||||
&& tip != BaseFeature.getValue () ) {
|
||||
if ( !tip->getTypeId().isDerivedFrom ( PartDesign::Feature::getClassTypeId() ) ) {
|
||||
return new App::DocumentObjectExecReturn ( "Linked object is not a PartDesign feature" );
|
||||
}
|
||||
|
||||
@@ -454,11 +431,32 @@ void Body::onSettingDocument() {
|
||||
|
||||
void Body::onChanged (const App::Property* prop) {
|
||||
if ( prop == &BaseFeature ) {
|
||||
App::DocumentObject *baseFeature = BaseFeature.getValue();
|
||||
App::DocumentObject *nextSolid = getNextSolidFeature ( baseFeature );
|
||||
if ( nextSolid ) {
|
||||
assert ( nextSolid->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) );
|
||||
static_cast<PartDesign::Feature*>(nextSolid)->BaseFeature.setValue( baseFeature );
|
||||
FeatureBase* bf = nullptr;
|
||||
auto first = Group.getValues().empty() ? nullptr : Group.getValues().front();
|
||||
|
||||
if(BaseFeature.getValue()) {
|
||||
|
||||
//setup the FeatureBase if needed
|
||||
if(!first || !first->isDerivedFrom(FeatureBase::getClassTypeId())) {
|
||||
bf = static_cast<FeatureBase*>(getDocument()->addObject("PartDesign::FeatureBase", "BaseFeature"));
|
||||
insertObject(bf, first, false);
|
||||
if(!Tip.getValue())
|
||||
Tip.setValue(bf);
|
||||
}
|
||||
else
|
||||
bf = static_cast<FeatureBase*>(first);
|
||||
}
|
||||
|
||||
if(bf && (bf->BaseFeature.getValue() != BaseFeature.getValue()))
|
||||
bf->BaseFeature.setValue(BaseFeature.getValue());
|
||||
}
|
||||
else if( prop == &Group ) {
|
||||
|
||||
//if the FeatureBase was deleted we set the BaseFeature link to nullptr
|
||||
if(BaseFeature.getValue() &&
|
||||
(Group.getValues().empty() || !Group.getValues().front()->isDerivedFrom(FeatureBase::getClassTypeId()))) {
|
||||
|
||||
BaseFeature.setValue(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user