PartDesign: Body rework - add BaseFeature property and make Tip always point to solid

This commit is contained in:
Alexander Golubev 2015-08-06 20:46:26 +03:00 committed by Stefan Tröger
parent 37320a0bfa
commit 8c5d514b18
17 changed files with 470 additions and 416 deletions

View File

@ -41,26 +41,13 @@ BodyBase::BodyBase()
{ {
ADD_PROPERTY(Model , (0) ); ADD_PROPERTY(Model , (0) );
ADD_PROPERTY(Tip , (0) ); ADD_PROPERTY(Tip , (0) );
} ADD_PROPERTY(BaseFeature , (0) );
short BodyBase::mustExecute() const
{
//if (Sketch.isTouched() ||
// Length.isTouched())
// return 1;
return 0;
}
App::DocumentObjectExecReturn *BodyBase::execute(void)
{
return App::DocumentObject::StdReturn;
} }
const bool BodyBase::hasFeature(const App::DocumentObject* f) const const bool BodyBase::hasFeature(const App::DocumentObject* f) const
{ {
const std::vector<App::DocumentObject*> features = Model.getValues(); const std::vector<App::DocumentObject*> &features = Model.getValues();
return std::find(features.begin(), features.end(), f) != features.end(); return f == BaseFeature.getValue() || std::find(features.begin(), features.end(), f) != features.end();
} }
BodyBase* BodyBase::findBodyOf(const App::DocumentObject* f) BodyBase* BodyBase::findBodyOf(const App::DocumentObject* f)
@ -78,15 +65,42 @@ BodyBase* BodyBase::findBodyOf(const App::DocumentObject* f)
return NULL; return NULL;
} }
const bool BodyBase::isAfterTip(const App::DocumentObject *f) const { const bool BodyBase::isAfter(const App::DocumentObject *feature, const App::DocumentObject* target) const {
App::DocumentObject* tipFeature = Tip.getValue(); assert (feature);
if (tipFeature == NULL)
return true;
std::vector<App::DocumentObject*> features = Model.getValues(); if (feature == target) {
std::vector<App::DocumentObject*>::const_iterator it = std::find(features.begin(), features.end(), f); return false;
std::vector<App::DocumentObject*>::const_iterator tip = std::find(features.begin(), features.end(), tipFeature);
return (it > tip);
} }
if (!target || target == BaseFeature.getValue() ) {
return hasFeature (feature);
} }
const std::vector<App::DocumentObject *> & features = Model.getValues();
auto featureIt = std::find(features.begin(), features.end(), feature);
auto targetIt = std::find(features.begin(), features.end(), target);
if (featureIt == features.end()) {
return false;
} else {
return featureIt > targetIt;
}
}
void BodyBase::onBeforeChange (const App::Property* prop) {
// If we are changing the base feature and tip point to it reset it
if ( prop == &BaseFeature && BaseFeature.getValue() == Tip.getValue() && BaseFeature.getValue() ) {
Tip.setValue( nullptr );
}
Part::Feature::onBeforeChange ( prop );
}
void BodyBase::onChanged (const App::Property* prop) {
// If the tip is zero and we are adding a base feature to the body set it to be the tip
if ( prop == &BaseFeature && !Tip.getValue() && BaseFeature.getValue() ) {
Tip.setValue( BaseFeature.getValue () );
}
Part::Feature::onChanged ( prop );
}
} /* Part */

View File

@ -43,41 +43,47 @@ class PartExport BodyBase : public Part::Feature
public: public:
BodyBase(); BodyBase();
/// The list of features
App::PropertyLinkList Model; App::PropertyLinkList Model;
/**
* The final feature of the body it is associated with.
* Note: tip may either point to the BaseFeature or to some feature inside the Model list.
* in case it points to the model the PartDesign::Body guaranties that it is a solid.
*/
App::PropertyLink Tip; App::PropertyLink Tip;
/** @name methods override feature */ /**
//@{ * A base object of the body, serves as a base object for the first feature of the body.
/// recalculate the feature * A Part::Feature link to make bodies be able based upon non-PartDesign Features.
App::DocumentObjectExecReturn *execute(void); */
short mustExecute() const; App::PropertyLink BaseFeature;
/// returns the type name of the view provider
//const char* getViewProviderName(void) const {
// return "PartDesignGui::ViewProviderBodyBase";
//}
//@}
// These methods are located here to avoid a dependency of ViewProviderSketchObject on PartDesign // These methods are located here to avoid a dependency of ViewProviderSketchObject on PartDesign
/// Remove the feature from the body /// Remove the feature from the body
virtual void removeFeature(App::DocumentObject* feature){} virtual void removeFeature(App::DocumentObject* feature){}
/// Return true if the feature belongs to this body /// Return true if the feature belongs to this body or either the body is based on the feature
const bool hasFeature(const App::DocumentObject *f) const; const bool hasFeature(const App::DocumentObject *f) const;
/// Return true if the feature belongs to the body and is located after the target
const bool isAfter(const App::DocumentObject *feature, const App::DocumentObject *target) const;
/** /**
* Return the solid feature before the given feature, or before the Tip feature * Return the body which this feature belongs too, or NULL.
* That is, sketches and datum features are skipped * Note: Normally each PartDesign feature belongs to a single body,
* If inclusive is true, start or the Tip is returned if it is a solid feature * But if a body is based on the feature it also will be return...
* But there are could be more features based on the same body.
* TODO introduce a findBodiesOf() if needed (2015-08-04, Fat-Zer)
*/ */
virtual App::DocumentObject *getPrevSolidFeature(App::DocumentObject *start = NULL, const bool inclusive = true)
{ return NULL; }
/// Return true if the feature is located after the current Tip feature
const bool isAfterTip(const App::DocumentObject *f) const;
/// Return the body which this feature belongs too, or NULL
static BodyBase* findBodyOf(const App::DocumentObject* f); static BodyBase* findBodyOf(const App::DocumentObject* f);
protected:
/// If BaseFeature is getting changed and Tip points to it resets the Tip
virtual void onBeforeChange (const App::Property* prop);
/// If BaseFeature is setted and Tip is null sets the Tip to it
virtual void onChanged (const App::Property* prop);
}; };
} //namespace Part } //namespace Part

View File

@ -71,7 +71,7 @@ public:
TopLoc_Location getLocation() const; TopLoc_Location getLocation() const;
protected: protected:
void onChanged(const App::Property* prop); virtual void onChanged(const App::Property* prop);
/** /**
* Build a history of changes * Build a history of changes
* MakeShape: The operation that created the changes, e.g. BRepAlgoAPI_Common * MakeShape: The operation that created the changes, e.g. BRepAlgoAPI_Common

View File

@ -127,17 +127,15 @@ bool ViewProviderPart::doubleClicked(void)
bool ViewProviderPart::onDelete(const std::vector<std::string> &) bool ViewProviderPart::onDelete(const std::vector<std::string> &)
{ {
// TODO Why the heck it's here? (2015-08-05, Fat-Zer)
// Body feature housekeeping // Body feature housekeeping
Part::BodyBase* body = Part::BodyBase::findBodyOf(getObject()); Part::BodyBase* body = Part::BodyBase::findBodyOf(getObject());
if (body != NULL) { if (body != NULL) {
body->removeFeature(getObject()); body->removeFeature(getObject());
// Make the new Tip and the previous solid feature visible again // Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = body->Tip.getValue(); App::DocumentObject* tip = body->Tip.getValue();
App::DocumentObject* prev = body->getPrevSolidFeature();
if (tip != NULL) { if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show(); Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
} }
} }

View File

@ -110,23 +110,10 @@ void Body::onChanged(const App::Property *prop)
short Body::mustExecute() const short Body::mustExecute() const
{ {
if (Tip.isTouched() ) if ( Tip.isTouched() ||
BaseFeature.isTouched() )
return 1; return 1;
return 0; return Part::BodyBase::mustExecute();
}
const Part::TopoShape Body::getTipShape()
{
// TODO right selection for Body
App::DocumentObject* link = Tip.getValue();
if (!link)
return Part::TopoShape();
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
//return new App::DocumentObjectExecReturn("Linked object is not a PartDesign object");
return Part::TopoShape();
// get the shape of the tip
return static_cast<Part::Feature*>(link)->Shape.getShape();
} }
App::DocumentObject* Body::getPrevFeature(App::DocumentObject *start) const App::DocumentObject* Body::getPrevFeature(App::DocumentObject *start) const
@ -144,54 +131,85 @@ App::DocumentObject* Body::getPrevFeature(App::DocumentObject *start) const
return *it; return *it;
} }
App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start, const bool inclusive) App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start)
{ {
std::vector<App::DocumentObject*> features = Model.getValues(); App::DocumentObject* baseFeature = BaseFeature.getValue();
if (features.empty()) return NULL;
App::DocumentObject* st = (start == NULL ? Tip.getValue() : start);
if (st == NULL)
return st; // Tip is NULL
if (inclusive && isSolidFeature(st)) if ( !start ) { // default to tip
return st; start = Tip.getValue();
std::vector<App::DocumentObject*>::iterator it = std::find(features.begin(), features.end(), st);
if (it == features.end()) return NULL; // Invalid start object
// Skip sketches and datum features
do {
if (it == features.begin())
return NULL;
it--;
} while (!isSolidFeature(*it));
return *it;
} }
App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start, const bool inclusive) if ( !start ) { // No Tip
return nullptr;
} else if ( start == baseFeature ) { // The base feature always considered as the first solid
return nullptr;
}
assert ( hasFeature ( start ) );
const std::vector<App::DocumentObject*> & features = Model.getValues();
auto startIt = std::find ( features.rbegin(), features.rend(), start );
assert ( startIt != features.rend() );
auto rvIt = std::find_if ( startIt + 1, features.rend(), isSolidFeature );
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
}
}
App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
{ {
std::vector<App::DocumentObject*> features = Model.getValues(); App::DocumentObject* baseFeature = BaseFeature.getValue();
if (features.empty()) return NULL;
App::DocumentObject* st = (start == NULL ? Tip.getValue() : start);
if (inclusive && isSolidFeature(st)) if ( !start ) { // default to tip
return st; start = Tip.getValue();
}
std::vector<App::DocumentObject*>::iterator it; if ( !start ) { // no tip
if (st == NULL) return nullptr;
it = features.begin(); // Tip is NULL }
else
it = std::find(features.begin(), features.end(), st);
if (it == features.end()) return NULL; // Invalid start object
// Skip sketches and datum features assert ( hasFeature ( start ) );
do {
it++;
if (it == features.end())
return NULL;
} while (!isSolidFeature(*it));
return *it; const std::vector<App::DocumentObject*> & features = Model.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++;
}
if (startIt == features.end() ) { // features list is empty
return nullptr;
}
auto rvIt = std::find_if ( startIt, features.end(), isSolidFeature );
if (rvIt != features.end()) { // the solid found in model list
return *rvIt;
} else {
return nullptr;
}
}
bool Body::isAfterInsertPoint(App::DocumentObject* feature) {
App::DocumentObject *nextSolid = getNextSolidFeature ();
assert (feature);
if (feature == nextSolid) {
return true;
} else if (!nextSolid) { // the tip is last solid, we can't be plased after it
return false;
} else {
return isAfter ( feature, nextSolid );
}
} }
const bool Body::isMemberOfMultiTransform(const App::DocumentObject* f) const bool Body::isMemberOfMultiTransform(const App::DocumentObject* f)
@ -240,19 +258,29 @@ Body* Body::findBodyOf(const App::DocumentObject* feature)
void Body::addFeature(App::DocumentObject *feature) void Body::addFeature(App::DocumentObject *feature)
{ {
insertFeature (feature, Tip.getValue(), /*after = */ true); insertFeature (feature, getNextSolidFeature (), /*after = */ false);
// Move the Tip if we added a solid
// Move the Tip if (isSolidFeature(feature)) {
Tip.setValue (feature); Tip.setValue (feature);
} }
}
void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after) void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after)
{ {
// Check if the after feature belongs to the body if (target) {
if (target && !hasFeature (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 (!hasFeature (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"); throw Base::Exception("Body: the feature we should insert relative to is not part of that body");
} }
}
std::vector<App::DocumentObject*> model = Model.getValues(); std::vector<App::DocumentObject*> model = Model.getValues();
std::vector<App::DocumentObject*>::iterator insertInto; std::vector<App::DocumentObject*>::iterator insertInto;
@ -282,29 +310,31 @@ void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* targ
// Set the BaseFeature property // Set the BaseFeature property
if (Body::isSolidFeature(feature)) { if (Body::isSolidFeature(feature)) {
// Set BaseFeature property to previous feature (this might be the Tip feature) // Set BaseFeature property to previous feature (this might be the Tip feature)
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature, false); App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature);
// NULL is ok here, it just means we made the current one fiature the base solid // NULL is ok here, it just means we made the current one fiature the base solid
static_cast<PartDesign::Feature*>(feature)->BaseFeature.setValue(prevSolidFeature); static_cast<PartDesign::Feature*>(feature)->BaseFeature.setValue(prevSolidFeature);
// Reroute the next solid feature's BaseFeature property to this feature // Reroute the next solid feature's BaseFeature property to this feature
App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature, false); App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature);
if (nextSolidFeature) if (nextSolidFeature) {
assert ( nextSolidFeature->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) );
static_cast<PartDesign::Feature*>(nextSolidFeature)->BaseFeature.setValue(feature); static_cast<PartDesign::Feature*>(nextSolidFeature)->BaseFeature.setValue(feature);
} }
}
} }
void Body::removeFeature(App::DocumentObject* feature) void Body::removeFeature(App::DocumentObject* feature)
{ {
App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature);
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature);
// This method must be called BEFORE the feature is removed from the Document! // This method must be called BEFORE the feature is removed from the Document!
if (isSolidFeature(feature)) { if (isSolidFeature(feature)) {
// This is a solid feature // This is a solid feature
// If the next feature is solid, reroute its BaseFeature property to the previous solid feature // If the next feature is solid, reroute its BaseFeature property to the previous solid feature
App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature, false);
if (nextSolidFeature) { if (nextSolidFeature) {
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature, false); assert ( nextSolidFeature->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) );
// Note: It's ok to remove the first solid feature, that just mean the next feature become the base one // Note: It's ok to remove the first solid feature, that just mean the next feature become the base one
static_cast<PartDesign::Feature*>(nextSolidFeature)->BaseFeature.setValue(prevSolidFeature); static_cast<PartDesign::Feature*>(nextSolidFeature)->BaseFeature.setValue(prevSolidFeature);
} }
@ -314,28 +344,11 @@ void Body::removeFeature(App::DocumentObject* feature)
std::vector<App::DocumentObject*>::iterator it = std::find(model.begin(), model.end(), feature); std::vector<App::DocumentObject*>::iterator it = std::find(model.begin(), model.end(), feature);
// Adjust Tip feature if it is pointing to the deleted object // Adjust Tip feature if it is pointing to the deleted object
App::DocumentObject* tipFeature = Tip.getValue(); if (Tip.getValue()== feature) {
if (tipFeature == feature) { if (prevSolidFeature) {
// Set the Tip to the previous feature if possible, otherwise to the next feature Tip.setValue(prevSolidFeature);
std::vector<App::DocumentObject*>::const_iterator prev = it, next = it;
if (it != model.begin()) {
prev--;
next++;
if (prev != model.end()) {
Tip.setValue(*prev);
} else { } else {
if (next != model.end()) Tip.setValue(nextSolidFeature);
Tip.setValue(*next);
else
Tip.setValue(NULL);
}
} else {
next++;
if (next != model.end())
Tip.setValue(*next);
else
Tip.setValue(NULL);
} }
} }
@ -365,36 +378,51 @@ App::DocumentObjectExecReturn *Body::execute(void)
} }
*/ */
const Part::TopoShape& TipShape = getTipShape(); App::DocumentObject* tip = Tip.getValue();
if (TipShape._Shape.IsNull()) Part::TopoShape tipShape;
//return new App::DocumentObjectExecReturn("empty shape"); if ( tip ) {
if ( !tip->getTypeId().isDerivedFrom ( PartDesign::Feature::getClassTypeId() )
&& tip != BaseFeature.getValue () ) {
return new App::DocumentObjectExecReturn ( "Linked object is not a PartDesign feature" );
}
App::DocumentObject* link = Tip.getValue();
// get the shape of the tip
tipShape = static_cast<Part::Feature *>(tip)->Shape.getShape();
if ( tipShape._Shape.IsNull () ) {
return new App::DocumentObjectExecReturn ( "Tip shape is empty" );
}
// We should hide here the transformation of the baseFeature
tipShape.transformShape (tipShape.getTransform(), true );
} else {
tipShape = Part::TopoShape();
}
Shape.setValue ( tipShape );
return App::DocumentObject::StdReturn; return App::DocumentObject::StdReturn;
Shape.setValue(TipShape);
return App::DocumentObject::StdReturn;
} }
Base::BoundBox3d Body::getBoundBox() Base::BoundBox3d Body::getBoundBox()
{ {
Base::BoundBox3d result; Base::BoundBox3d result;
Part::Feature* tipSolid = static_cast<Part::Feature*>(getPrevSolidFeature()); Part::Feature* tipSolid = static_cast<Part::Feature*>(Tip.getValue());
if (tipSolid != NULL) { if (tipSolid && tipSolid->Shape.getValue().IsNull()) {
if (tipSolid->Shape.getValue().IsNull())
// This can happen when a new feature is added without having its Shape property set yet // This can happen when a new feature is added without having its Shape property set yet
tipSolid = static_cast<Part::Feature*>(getPrevSolidFeature(NULL, false)); tipSolid = static_cast<Part::Feature*>(getPrevSolidFeature());
}
if (tipSolid != NULL) { if (!tipSolid || tipSolid->Shape.getValue().IsNull()) {
if (tipSolid->Shape.getValue().IsNull()) result = App::Plane::getBoundBox();
tipSolid = NULL; } else {
else
result = tipSolid->Shape.getShape().getBoundBox(); result = tipSolid->Shape.getShape().getBoundBox();
} }
}
if (tipSolid == NULL)
result = App::Plane::getBoundBox();
std::vector<App::DocumentObject*> model = Model.getValues(); std::vector<App::DocumentObject*> model = Model.getValues();
// TODO: In DatumLine and DatumPlane, recalculate the Base point to be as near as possible to the origin (0,0,0) // TODO: In DatumLine and DatumPlane, recalculate the Base point to be as near as possible to the origin (0,0,0)
@ -432,11 +460,12 @@ void Body::onSettingDocument() {
connection.disconnect(); connection.disconnect();
getDocument()->signalDeletedObject.connect(boost::bind(&Body::onDelete, this, _1)); getDocument()->signalDeletedObject.connect(boost::bind(&Body::onDelete, this, _1));
App::DocumentObject::onSettingDocument();
Part::BodyBase::onSettingDocument();
} }
void Body::onDelete(const App::DocumentObject& obj) { void Body::onDelete(const App::DocumentObject& obj) {
// TODO Handle this in view provider rather here (2015-08-06, Fat-Zer)
if(&obj == this) { if(&obj == this) {
//delete all child objects if needed //delete all child objects if needed
std::vector<DocumentObject*> grp = Model.getValues(); std::vector<DocumentObject*> grp = Model.getValues();
@ -445,4 +474,19 @@ void Body::onDelete(const App::DocumentObject& obj) {
} }
} }
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 );
} }
}
Part::BodyBase::onChanged ( prop );
}
} /* PartDesign */

View File

@ -56,30 +56,16 @@ public:
} }
//@} //@}
/// Get the tip shape
const Part::TopoShape getTipShape();
/// Return the previous feature /// Return the previous feature
App::DocumentObject* getPrevFeature(App::DocumentObject *start = NULL) const; App::DocumentObject* getPrevFeature(App::DocumentObject *start = NULL) const;
/**
* Return the solid feature before the given feature, or before the Tip feature
* That is, sketches and datum features are skipped
* If inclusive is true, start or the Tip is returned if it is a solid feature
*/
App::DocumentObject *getPrevSolidFeature(App::DocumentObject *start = NULL, const bool inclusive = true);
/**
* Return the next solid feature after the given feature, or after the Tip feature
* That is, sketches and datum features are skipped
* If inclusive is true, start or the Tip is returned if it is a solid feature
*/
App::DocumentObject *getNextSolidFeature(App::DocumentObject* start = NULL, const bool inclusive = true);
// Return the shape of the feature preceding this feature // Return the shape of the feature preceding this feature
//const Part::TopoShape getPreviousSolid(const PartDesign::Feature* f); //const Part::TopoShape getPreviousSolid(const PartDesign::Feature* f);
/// Add the feature into the body at the current insert point (Tip feature) /**
* Add the feature into the body at the current insert point.
* The insertion poin is the before next solid after the Tip feature
*/
void addFeature(App::DocumentObject* feature); void addFeature(App::DocumentObject* feature);
/** /**
@ -98,8 +84,11 @@ public:
/// Remove the feature from the body /// Remove the feature from the body
void removeFeature(App::DocumentObject* feature); void removeFeature(App::DocumentObject* feature);
/// Checks if the given document object is a feaure of this body /**
bool isFeature(App::DocumentObject* feature); * Checks if the given document object lays after the current insert point
* (place before next solid after the Tip)
*/
bool isAfterInsertPoint(App::DocumentObject* feature);
/// Return true if the given feature is member of a MultiTransform feature /// Return true if the given feature is member of a MultiTransform feature
static const bool isMemberOfMultiTransform(const App::DocumentObject* f); static const bool isMemberOfMultiTransform(const App::DocumentObject* f);
@ -131,6 +120,21 @@ public:
protected: protected:
virtual void onSettingDocument(); virtual void onSettingDocument();
/// Adjusts the first solid's feature's base on on BaseFeature getting setted
virtual void onChanged (const App::Property* prop);
/**
* Return the solid feature before the given feature, or before the Tip feature
* That is, sketches and datum features are skipped
*/
App::DocumentObject *getPrevSolidFeature(App::DocumentObject *start = NULL);
/**
* Return the next solid feature after the given feature, or after the Tip feature
* That is, sketches and datum features are skipped
*/
App::DocumentObject *getNextSolidFeature(App::DocumentObject* start = NULL);
private: private:
App::DocumentObject* rememberTip; App::DocumentObject* rememberTip;
boost::signals::scoped_connection connection; boost::signals::scoped_connection connection;

View File

@ -128,7 +128,7 @@ App::DocumentObjectExecReturn *Boolean::execute(void)
if(!part->hasObject(body)) if(!part->hasObject(body))
return new App::DocumentObjectExecReturn("Cannot do boolean on bodies of different parts"); return new App::DocumentObjectExecReturn("Cannot do boolean on bodies of different parts");
TopoDS_Shape shape = body->getTipShape()._Shape; TopoDS_Shape shape = body->Shape.getValue();
// Move the shape to the location of the base shape in the other body // Move the shape to the location of the base shape in the other body
Base::Placement pl = body->Placement.getValue(); Base::Placement pl = body->Placement.getValue();

View File

@ -60,7 +60,7 @@ public:
void getContiniusEdges(Part::TopoShape, std::vector< std::string >&); void getContiniusEdges(Part::TopoShape, std::vector< std::string >&);
protected: protected:
void onChanged(const App::Property* prop); virtual void onChanged(const App::Property* prop);
}; };
} //namespace PartDesign } //namespace PartDesign

View File

@ -139,28 +139,41 @@ CmdPartDesignBody::CmdPartDesignBody()
void CmdPartDesignBody::activated(int iMsg) void CmdPartDesignBody::activated(int iMsg)
{ {
openCommand("Add a body"); std::vector<App::DocumentObject*> features =
std::string FeatName = getUniqueObjectName("Body"); getSelection().getObjectsOfType(Part::Feature::getClassTypeId());
App::DocumentObject* baseFeature = nullptr;
if (!features.empty()) {
if (features.size() == 1) {
baseFeature = features[0];
// TODO Check if the feature belongs to another body and may be some other sanity checks (2015-08-04, Fat-Zer)
} else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Body may be based no more than on one feature."));
return;
}
}
// first check if Part is already created: // first check if Part is already created:
App::Part *actPart = getDocument()->Tip.getValue<App::Part *>(); App::Part *actPart = getDocument()->Tip.getValue<App::Part *>();
std::string PartName; std::string PartName;
if(!actPart){ if(!actPart){
// if not, creating a part and set it up by calling the appropiated function in Workbench Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
//if we create a new part we automaticly get a new body, there is no need to create a second one rcCmdMgr.runCommandByName("PartDesign_Part");
PartName = getUniqueObjectName("Part"); actPart = getDocument()->Tip.getValue<App::Part *>();
doCommand(Doc,"App.activeDocument().Tip = App.activeDocument().addObject('App::Part','%s')",PartName.c_str()); }
doCommand(Doc,"App.activeDocument().ActiveObject.Label = '%s'", QObject::tr(PartName.c_str()).toStdString().c_str());
PartDesignGui::Workbench::setUpPart(dynamic_cast<App::Part *>(getDocument()->getObject(PartName.c_str()))); openCommand("Add a body");
doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PARTKEY, PartName.c_str()); std::string FeatName = getUniqueObjectName("Body");
} else {
PartName = actPart->getNameInDocument(); PartName = actPart->getNameInDocument();
// add the Body feature itself, and make it active // add the Body feature itself, and make it active
doCommand(Doc,"App.activeDocument().addObject('PartDesign::Body','%s')", FeatName.c_str()); doCommand(Doc,"App.activeDocument().addObject('PartDesign::Body','%s')", FeatName.c_str());
//doCommand(Doc,"App.activeDocument().%s.Model = []",FeatName.c_str()); if (baseFeature) {
//doCommand(Doc,"App.activeDocument().%s.Tip = None",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.BaseFeature = App.activeDocument().%s",
FeatName.c_str(), baseFeature->getNameInDocument());
}
addModule(Gui,"PartDesignGui"); // import the Gui module only once a session addModule(Gui,"PartDesignGui"); // import the Gui module only once a session
doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PDBODYKEY, FeatName.c_str()); doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PDBODYKEY, FeatName.c_str());
@ -168,7 +181,6 @@ void CmdPartDesignBody::activated(int iMsg)
doCommand(Gui,"Gui.Selection.clearSelection()"); doCommand(Gui,"Gui.Selection.clearSelection()");
doCommand(Gui,"Gui.Selection.addSelection(App.ActiveDocument.%s)", FeatName.c_str()); doCommand(Gui,"Gui.Selection.addSelection(App.ActiveDocument.%s)", FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.addObject(App.ActiveDocument.%s)",PartName.c_str(),FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.addObject(App.ActiveDocument.%s)",PartName.c_str(),FeatName.c_str());
}
updateActive(); updateActive();
} }
@ -188,8 +200,8 @@ CmdPartDesignMoveTip::CmdPartDesignMoveTip()
{ {
sAppModule = "PartDesign"; sAppModule = "PartDesign";
sGroup = QT_TR_NOOP("PartDesign"); sGroup = QT_TR_NOOP("PartDesign");
sMenuText = QT_TR_NOOP("Insert here"); sMenuText = QT_TR_NOOP("Set tip");
sToolTipText = QT_TR_NOOP("Move insert point to selected feature"); sToolTipText = QT_TR_NOOP("Move the tip of the body");
sWhatsThis = sToolTipText; sWhatsThis = sToolTipText;
sStatusTip = sToolTipText; sStatusTip = sToolTipText;
sPixmap = "PartDesign_MoveTip"; sPixmap = "PartDesign_MoveTip";
@ -197,51 +209,47 @@ CmdPartDesignMoveTip::CmdPartDesignMoveTip()
void CmdPartDesignMoveTip::activated(int iMsg) void CmdPartDesignMoveTip::activated(int iMsg)
{ {
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(
if(!pcActiveBody) return; Part::Feature::getClassTypeId() );
std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId());
App::DocumentObject* selFeature; App::DocumentObject* selFeature;
PartDesign::Body* body= nullptr;
if (features.empty()) { if ( features.size() == 1 ) {
// Insert at the beginning of this body
selFeature = NULL;
} else {
selFeature = features.front(); selFeature = features.front();
if ( selFeature->getTypeId().isDerivedFrom ( PartDesign::Body::getClassTypeId() ) ) { if ( selFeature->getTypeId().isDerivedFrom ( PartDesign::Body::getClassTypeId() ) ) {
// Insert at the beginning of this body body = static_cast<PartDesign::Body *> ( selFeature );
selFeature = NULL; } else {
} else if (!pcActiveBody->hasFeature(selFeature)) { body = PartDesignGui::getBodyFor ( selFeature, /* messageIfNot =*/ false );
// Switch to other body
pcActiveBody = static_cast<PartDesign::Body*>(Part::BodyBase::findBodyOf(selFeature));
if (pcActiveBody != NULL)
Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s',App.activeDocument().%s)",
PDBODYKEY, pcActiveBody->getNameInDocument());
else
return;
} }
} else {
selFeature = nullptr;
}
// TODO Refuse to set tip to nonsolid features (2015-08-05, Fat-Zer)
if (!selFeature || !body ) {
QMessageBox::warning (0, QObject::tr( "Selection error" ),
QObject::tr( "Select exactly one PartDesign feature or a body." ) );
return;
} else if (!body) {
QMessageBox::warning (0, QObject::tr( "Selection error" ),
QObject::tr( "Couldn't determin a body for selected feature." ) );
return;
} }
openCommand("Move insert point to selected feature"); openCommand("Move insert point to selected feature");
App::DocumentObject* oldTip = pcActiveBody->Tip.getValue(); App::DocumentObject* oldTip = body->Tip.getValue();
if (oldTip != NULL) { if (oldTip) {
if (!oldTip->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()))
doCommand(Gui, "Gui.activeDocument().hide(\"%s\")", oldTip->getNameInDocument() ); doCommand(Gui, "Gui.activeDocument().hide(\"%s\")", oldTip->getNameInDocument() );
App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature();
if (prevSolidFeature != NULL)
doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prevSolidFeature->getNameInDocument());
} }
if (selFeature == NULL) { if (selFeature == body) {
doCommand(Doc,"App.activeDocument().%s.Tip = None", pcActiveBody->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Tip = None", body->getNameInDocument());
} else { } else {
doCommand(Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",pcActiveBody->getNameInDocument(), selFeature->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",body->getNameInDocument(),
selFeature->getNameInDocument());
// Adjust visibility to show only the Tip feature and (if the Tip feature is not solid) the solid feature prior to the Tip // Adjust visibility to show only the Tip feature
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", selFeature->getNameInDocument()); doCommand(Gui,"Gui.activeDocument().show(\"%s\")", selFeature->getNameInDocument());
App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature();
if ((prevSolidFeature != NULL) && !PartDesign::Body::isSolidFeature(selFeature))
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", prevSolidFeature->getNameInDocument());
} }
// TOOD: Hide all datum features after the Tip feature? But the user might have already hidden some and wants to see // TOOD: Hide all datum features after the Tip feature? But the user might have already hidden some and wants to see
@ -271,8 +279,8 @@ CmdPartDesignDuplicateSelection::CmdPartDesignDuplicateSelection()
sPixmap = ""; sPixmap = "";
} }
void CmdPartDesignDuplicateSelection::activated(int iMsg) void CmdPartDesignDuplicateSelection::activated(int iMsg) {
{ // TODO Review the function (2015-08-05, Fat-Zer)
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true);
if(!pcActiveBody) return; if(!pcActiveBody) return;
@ -314,9 +322,6 @@ void CmdPartDesignDuplicateSelection::activated(int iMsg)
// Adjust visibility of features // Adjust visibility of features
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", newFeatures.back()->getNameInDocument()); doCommand(Gui,"Gui.activeDocument().show(\"%s\")", newFeatures.back()->getNameInDocument());
App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature();
if ((prevSolidFeature != NULL) && !PartDesign::Body::isSolidFeature(selFeature))
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", prevSolidFeature->getNameInDocument());
} }
bool CmdPartDesignDuplicateSelection::isActive(void) bool CmdPartDesignDuplicateSelection::isActive(void)
@ -375,17 +380,19 @@ void CmdPartDesignMoveFeature::activated(int iMsg)
for (std::vector<App::DocumentObject*>::const_iterator f = features.begin(); f != features.end(); f++) { for (std::vector<App::DocumentObject*>::const_iterator f = features.begin(); f != features.end(); f++) {
// Find body of this feature // Find body of this feature
Part::BodyBase* source = PartDesign::Body::findBodyOf(*f); Part::BodyBase* source = PartDesign::Body::findBodyOf(*f);
bool featureIsTip = false; bool featureWasTip = false;
if (source == target) continue; if (source == target) continue;
// Remove from the source body if the feature belonged to a body // Remove from the source body if the feature belonged to a body
if (source) { if (source) {
featureIsTip = (source->Tip.getValue() == *f); featureWasTip = (source->Tip.getValue() == *f);
doCommand(Doc,"App.activeDocument().%s.removeFeature(App.activeDocument().%s)", doCommand(Doc,"App.activeDocument().%s.removeFeature(App.activeDocument().%s)",
source->getNameInDocument(), (*f)->getNameInDocument()); source->getNameInDocument(), (*f)->getNameInDocument());
} }
App::DocumentObject* targetOldTip = target->Tip.getValue();
// Add to target body (always at the Tip) // Add to target body (always at the Tip)
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
target->getNameInDocument(), (*f)->getNameInDocument()); target->getNameInDocument(), (*f)->getNameInDocument());
@ -393,20 +400,26 @@ void CmdPartDesignMoveFeature::activated(int iMsg)
doCommand(Gui,"App.activeDocument().recompute()"); doCommand(Gui,"App.activeDocument().recompute()");
// Adjust visibility of features // Adjust visibility of features
if (PartDesign::Body::isSolidFeature(*f)) { // TODO: May be something can be done in view provider (2015-08-05, Fat-Zer)
// If we removed the tip of the source body, make the new tip visible // If we removed the tip of the source body, make the new tip visible
if (featureIsTip) { if (featureWasTip ) {
App::DocumentObject* prevSolidFeature = source->getPrevSolidFeature(); App::DocumentObject * sourceNewTip = source->Tip.getValue();
if (prevSolidFeature) { doCommand(Gui,"Gui.activeDocument().show(\"%s\")", sourceNewTip->getNameInDocument());
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", prevSolidFeature->getNameInDocument());
}
} }
// Hide old tip and show new tip (the moved feature) of the target body // Hide old tip and show new tip (the moved feature) of the target body
App::DocumentObject* prevSolidFeature = target->getPrevSolidFeature(); App::DocumentObject* targetNewTip = target->Tip.getValue();
doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prevSolidFeature->getNameInDocument()); if ( targetOldTip != targetNewTip ) {
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", (*f)->getNameInDocument()); if ( targetOldTip ) {
} else if ((*f)->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) { doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", targetOldTip->getNameInDocument());
}
if (targetNewTip) {
doCommand(Gui,"Gui.activeDocument().show(\"%s\")", targetNewTip->getNameInDocument());
}
}
// Fix sketch support
if ((*f)->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(*f); Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(*f);
try { try {
PartDesignGui::Workbench::fixSketchSupport(sketch); PartDesignGui::Workbench::fixSketchSupport(sketch);
@ -421,10 +434,7 @@ void CmdPartDesignMoveFeature::activated(int iMsg)
bool CmdPartDesignMoveFeature::isActive(void) bool CmdPartDesignMoveFeature::isActive(void)
{ {
if (getActiveGuiDocument()) return hasActiveDocument ();
return true;
else
return false;
} }
DEF_STD_CMD_A(CmdPartDesignMoveFeatureInTree); DEF_STD_CMD_A(CmdPartDesignMoveFeatureInTree);
@ -747,10 +757,10 @@ void CmdPartDesignNewSketch::activated(int iMsg)
return; return;
} }
} else if (!obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()) } else if (!obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())
&& pcActiveBody->getNextSolidFeature() != obj) { && pcActiveBody->Tip.getValue () != obj) {
// TOOD: checkme why it's forbidden!? // TODO checkme why it's forbidden!? (2015-08-05, Fat-Zer)
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Selection from inactive feature"), QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Selection from inactive feature"),
QObject::tr("You can only use the last solid feature as sketch support")); QObject::tr("You can only use the Tip as sketch support"));
return; return;
} }
@ -809,7 +819,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
continue; continue;
} else { } else {
if (pcActiveBody->isAfterTip(*p)){ if (pcActiveBody->isAfterInsertPoint(*p)) {
status.push_back(PartDesignGui::TaskFeaturePick::afterTip); status.push_back(PartDesignGui::TaskFeaturePick::afterTip);
continue; continue;
} }
@ -908,7 +918,7 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName,
} }
if (pcActiveBody) { if (pcActiveBody) {
App::DocumentObject* lastSolidFeature = pcActiveBody->getPrevSolidFeature(NULL, true); App::DocumentObject* lastSolidFeature = pcActiveBody->Tip.getValue();
if (!prevSolidFeature || prevSolidFeature == lastSolidFeature) { if (!prevSolidFeature || prevSolidFeature == lastSolidFeature) {
// If the previous feature not given or is the Tip add Feature after it. // If the previous feature not given or is the Tip add Feature after it.
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
@ -999,7 +1009,7 @@ const unsigned validateSketches(std::vector<App::DocumentObject*>& sketches,
continue; continue;
} }
if (pcActiveBody && pcActiveBody->isAfterTip(*s)){ if (pcActiveBody && pcActiveBody->isAfterInsertPoint(*s)){
status.push_back(PartDesignGui::TaskFeaturePick::afterTip); status.push_back(PartDesignGui::TaskFeaturePick::afterTip);
continue; continue;
} }
@ -1749,7 +1759,7 @@ void prepareTransformed(Gui::Command* cmd, const std::string& which,
// Exception (Thu Sep 6 11:52:01 2012): 'App.Document' object has no attribute 'Mirrored' // Exception (Thu Sep 6 11:52:01 2012): 'App.Document' object has no attribute 'Mirrored'
Gui::Command::updateActive(); // Helps to ensure that the object already exists when the next command comes up Gui::Command::updateActive(); // Helps to ensure that the object already exists when the next command comes up
Gui::Command::doCommand(Gui::Command::Doc, str.str().c_str()); Gui::Command::doCommand(Gui::Command::Doc, str.str().c_str());
// TODO Wjat that function supposed to do? (2015-08-05, Fat-Zer)
func(FeatName, features); func(FeatName, features);
}; };
@ -2069,9 +2079,7 @@ void CmdPartDesignMultiTransform::activated(int iMsg)
return; return;
// Make sure the user isn't presented with an empty screen because no transformations are defined yet... // Make sure the user isn't presented with an empty screen because no transformations are defined yet...
App::DocumentObject* prevSolid = 0; App::DocumentObject* prevSolid = pcActiveBody->Tip.getValue();
if (pcActiveBody)
pcActiveBody->getPrevSolidFeature(NULL, true);
if (prevSolid != NULL) { if (prevSolid != NULL) {
Part::Feature* feat = static_cast<Part::Feature*>(prevSolid); Part::Feature* feat = static_cast<Part::Feature*>(prevSolid);
doCommand(Doc,"App.activeDocument().%s.Shape = App.activeDocument().%s.Shape", doCommand(Doc,"App.activeDocument().%s.Shape = App.activeDocument().%s.Shape",

View File

@ -251,7 +251,8 @@ void CmdPrimtiveCompSubtractive::activated(int iMsg)
//check if we already have a feature as subtractive ones work only if we have //check if we already have a feature as subtractive ones work only if we have
//something to subtract from. //something to subtract from.
if(!pcActiveBody->getPrevSolidFeature()) { App::DocumentObject *prevSolid = pcActiveBody->Tip.getValue();
if(!prevSolid) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No previous feature found"), QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No previous feature found"),
QObject::tr("It is not possible to create a subtractive feature without a base feature available")); QObject::tr("It is not possible to create a subtractive feature without a base feature available"));
return; return;
@ -335,9 +336,10 @@ void CmdPrimtiveCompSubtractive::activated(int iMsg)
Gui::Command::updateActive(); Gui::Command::updateActive();
if (isActiveObjectValid() && (pcActiveBody != NULL)) { if (isActiveObjectValid() && (pcActiveBody != NULL)) {
App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature(NULL, false); // TODO (2015-08-05, Fat-Zer)
if (prevSolidFeature != NULL && strcmp(prevSolidFeature->getNameInDocument(), FeatName.c_str())!=0) if (prevSolid) {
doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prevSolidFeature->getNameInDocument()); doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prevSolid->getNameInDocument());
}
} }
Gui::Command::doCommand(Gui, "Gui.activeDocument().hide(\'%s\')", CSName.c_str()); Gui::Command::doCommand(Gui, "Gui.activeDocument().hide(\'%s\')", CSName.c_str());

View File

@ -917,17 +917,6 @@ bool TaskDlgDatumParameters::reject()
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY); PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
// Body housekeeping
if (activeBody != NULL) {
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = activeBody->Tip.getValue();
App::DocumentObject* prev = activeBody->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
return true; return true;
} }

View File

@ -97,24 +97,14 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject()); PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY); PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
App::DocumentObject* curSolid = 0;//the last solid of the body, the one that is likely visible, but can't be used for up-to-face // The solid this feature will be fused to
if (activeBody) App::DocumentObject* prevSolid = pcSketchBased->getBaseObject( /* silent =*/ true );
curSolid = activeBody->getPrevSolidFeature();
else
curSolid = pcSketchBased;
App::DocumentObject* prevSolid = 0;//the solid this feature will be fused to
try {
prevSolid = pcSketchBased->getBaseObject();
} catch (Base::Exception) {
//this feature is a starting feature
}
if (pressed) { if (pressed) {
Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) { if (doc) {
if (curSolid) if (pcSketchBased)
doc->setHide(curSolid->getNameInDocument()); doc->setHide(pcSketchBased->getNameInDocument());
if (prevSolid) if (prevSolid)
doc->setShow(prevSolid->getNameInDocument()); doc->setShow(prevSolid->getNameInDocument());
} }
@ -125,8 +115,8 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool
Gui::Selection().rmvSelectionGate(); Gui::Selection().rmvSelectionGate();
Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) { if (doc) {
if (curSolid) if (pcSketchBased)
doc->setShow(curSolid->getNameInDocument()); doc->setShow(pcSketchBased->getNameInDocument());
if (prevSolid) if (prevSolid)
doc->setHide(prevSolid->getNameInDocument()); doc->setHide(prevSolid->getNameInDocument());
} }

View File

@ -70,7 +70,7 @@ void ViewProviderBody::attach(App::DocumentObject *pcFeat)
// call parent attach method // call parent attach method
ViewProviderPart::attach(pcFeat); ViewProviderPart::attach(pcFeat);
// TODO fixup the "Body" display mode (2015-08-07, Fat-Zer)
// putting all together with the switch // putting all together with the switch
addDisplayMaskMode(pcBodyTip, "Body"); addDisplayMaskMode(pcBodyTip, "Body");
addDisplayMaskMode(pcBodyChildren, "Through"); addDisplayMaskMode(pcBodyChildren, "Through");
@ -119,7 +119,8 @@ bool ViewProviderBody::doubleClicked(void)
std::vector<App::DocumentObject*> ViewProviderBody::claimChildren(void)const std::vector<App::DocumentObject*> ViewProviderBody::claimChildren(void)const
{ {
std::vector<App::DocumentObject*> Model = static_cast<PartDesign::Body*>(getObject())->Model.getValues(); PartDesign::Body* bodyObj = static_cast<PartDesign::Body*>(getObject());
const std::vector<App::DocumentObject*> &Model = bodyObj->Model.getValues();
std::set<App::DocumentObject*> OutSet; std::set<App::DocumentObject*> OutSet;
// search for objects handled (claimed) by the features // search for objects handled (claimed) by the features
@ -136,23 +137,34 @@ std::vector<App::DocumentObject*> ViewProviderBody::claimChildren(void)const
// remove the otherwise handled objects, preserving their order so the order in the TreeWidget is correct // remove the otherwise handled objects, preserving their order so the order in the TreeWidget is correct
std::vector<App::DocumentObject*> Result; std::vector<App::DocumentObject*> Result;
// Clame for the base feature first
if (bodyObj->BaseFeature.getValue()) {
Result.push_back (bodyObj->BaseFeature.getValue());
}
// return the rest as claim set of the Body
for (std::vector<App::DocumentObject*>::const_iterator it = Model.begin();it!=Model.end();++it) { for (std::vector<App::DocumentObject*>::const_iterator it = Model.begin();it!=Model.end();++it) {
if (OutSet.find(*it) == OutSet.end()) if (OutSet.find(*it) == OutSet.end())
Result.push_back(*it); Result.push_back(*it);
} }
// return the rest as claim set of the Body
return Result; return Result;
} }
std::vector<App::DocumentObject*> ViewProviderBody::claimChildren3D(void)const std::vector<App::DocumentObject*> ViewProviderBody::claimChildren3D(void)const
{ {
//std::vector<App::DocumentObject*> children = static_cast<PartDesign::Body*>(getObject())->Model.getValues(); PartDesign::Body* body = static_cast<PartDesign::Body*>(getObject());
//Base::Console().Error("Body 3D claimed children:\n");
//for (std::vector<App::DocumentObject*>::const_iterator o = children.begin(); o != children.end(); o++) const std::vector<App::DocumentObject*> & features = body->Model.getValues();
// Base::Console().Error("%s\n", (*o)->getNameInDocument());
return static_cast<PartDesign::Body*>(getObject())->Model.getValues(); std::vector<App::DocumentObject*> rv;
rv.push_back( body->BaseFeature.getValue() );
rv.insert( rv.end(), features.begin(), features.end());
// TODO Check what will happen if BaseFature will be shared by severral bodies (2015-08-04, Fat-Zer)
return rv;
} }

View File

@ -51,11 +51,11 @@ public:
virtual std::vector<std::string> getDisplayModes(void) const; virtual std::vector<std::string> getDisplayModes(void) const;
virtual bool doubleClicked(void); virtual bool doubleClicked(void);
std::vector<App::DocumentObject*> claimChildren(void)const; virtual std::vector<App::DocumentObject*> claimChildren(void)const;
// returns the root node where the children gets collected(3D) // returns the root node where the children gets collected(3D)
virtual SoGroup* getChildRoot(void) const {return pcBodyChildren;} virtual SoGroup* getChildRoot(void) const {return pcBodyChildren;}
std::vector<App::DocumentObject*> claimChildren3D(void)const; virtual std::vector<App::DocumentObject*> claimChildren3D(void)const;
/// Update the children's highlighting when triggered /// Update the children's highlighting when triggered
void updateData(const App::Property* prop); void updateData(const App::Property* prop);

View File

@ -120,20 +120,6 @@ void ViewProviderDatum::attach(App::DocumentObject *obj)
bool ViewProviderDatum::onDelete(const std::vector<std::string> &) bool ViewProviderDatum::onDelete(const std::vector<std::string> &)
{ {
// Body feature housekeeping
Part::BodyBase* body = Part::BodyBase::findBodyOf(getObject());
if (body != NULL) {
body->removeFeature(getObject());
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = body->Tip.getValue();
App::DocumentObject* prev = body->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
// TODO: Ask user what to do about dependent objects, e.g. Sketches that have this feature as their support // TODO: Ask user what to do about dependent objects, e.g. Sketches that have this feature as their support
// 1. Delete // 1. Delete
// 2. Suppress // 2. Suppress

View File

@ -172,16 +172,16 @@ PartDesign::Body *Workbench::setUpPart(const App::Part *part)
Gui::ViewProviderPart::setUpPart(part); Gui::ViewProviderPart::setUpPart(part);
// check for Bodies // check for Bodies
std::vector<App::DocumentObject*> bodies = part->getObjectsOfType(PartDesign::Body::getClassTypeId()); // std::vector<App::DocumentObject*> bodies = part->getObjectsOfType(PartDesign::Body::getClassTypeId());
assert(bodies.size() == 0); // assert(bodies.size() == 0);
std::string PartName = part->getNameInDocument(); // std::string PartName = part->getNameInDocument();
std::string BodyName = part->getDocument()->getUniqueObjectName("MainBody"); // std::string BodyName = part->getDocument()->getUniqueObjectName("MainBody");
Gui::Command::addModule(Gui::Command::Doc, "PartDesign"); Gui::Command::addModule(Gui::Command::Doc, "PartDesign");
Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().addObject('PartDesign::Body','%s')", BodyName.c_str()); // Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().addObject('PartDesign::Body','%s')", BodyName.c_str());
Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.addObject(App.activeDocument().ActiveObject)", part->getNameInDocument()); // Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.addObject(App.activeDocument().ActiveObject)", part->getNameInDocument());
Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PDBODYKEY, BodyName.c_str()); // Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PDBODYKEY, BodyName.c_str());
Gui::Command::updateActive(); Gui::Command::updateActive();
return NULL; return NULL;

View File

@ -4480,9 +4480,10 @@ namespace SketcherGui {
// Note: its better to search the support of the sketch in case the sketch support is a base plane // Note: its better to search the support of the sketch in case the sketch support is a base plane
Part::BodyBase* body = Part::BodyBase::findBodyOf(sketch); Part::BodyBase* body = Part::BodyBase::findBodyOf(sketch);
if ((body != NULL) && (Part::BodyBase::findBodyOf(pObj) == body) && body->isAfterTip(pObj)) if ((body != NULL) && (Part::BodyBase::findBodyOf(pObj) == body) && body->isAfter(pObj, sketch)) {
// Don't allow selection after the Tip feature in the same body // Don't allow selection after the sketch in the same body
return false; return false;
}
if (!sSubName || sSubName[0] == '\0') if (!sSubName || sSubName[0] == '\0')
return false; return false;