diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index 6674c42faa..0262cec270 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -33,6 +33,7 @@ #include "OriginFeature.h" #include "Origin.h" #include "OriginGroupExtension.h" +#include //#include "GeoFeatureGroupPy.h" //#include "FeaturePythonPyImp.h" @@ -49,6 +50,7 @@ EXTENSION_PROPERTY_SOURCE(App::GeoFeatureGroupExtension, App::GroupExtension) GeoFeatureGroupExtension::GeoFeatureGroupExtension(void) { initExtensionType(GeoFeatureGroupExtension::getExtensionClassTypeId()); + Group.setScope(LinkScope::Child); } GeoFeatureGroupExtension::~GeoFeatureGroupExtension(void) @@ -367,11 +369,14 @@ void GeoFeatureGroupExtension::getCSRelevantLinks(const DocumentObject* obj, std bool GeoFeatureGroupExtension::areLinksValid(const DocumentObject* obj) { //no cross CS link for local links. + //Base::Console().Message("Check object links: %s\n", obj->getNameInDocument()); std::vector list; obj->getPropertyList(list); for(App::Property* prop : list) { - if(!isLinkValid(prop)) + if(!isLinkValid(prop)) { + //Base::Console().Message("Invalid link: %s\n", prop->getName()); return false; + } } return true; @@ -386,16 +391,16 @@ bool GeoFeatureGroupExtension::isLinkValid(App::Property* prop) { //no cross CS link for local links. auto result = getScopedObjectsFromLink(prop, LinkScope::Local); - auto group = obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId()) ? obj : getGroupOfObject(obj); + auto group = getGroupOfObject(obj); for(auto link : result) { if(getGroupOfObject(link) != group) return false; } //for links with scope SubGroup we need to check if all features are part of subgroups - if(group) { + if(obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) { result = getScopedObjectsFromLink(prop, LinkScope::Child); - auto groupExt = group->getExtensionByType(); + auto groupExt = obj->getExtensionByType(); for(auto link : result) { if(!groupExt->hasObject(link, true)) return false; diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index 8b99a2e574..7c403ab6de 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -104,6 +104,12 @@ std::vector< DocumentObject* > GroupExtension::addObjects(std::vector< DocumentO return added; } +std::vector< DocumentObject* > GroupExtension::setObjects(std::vector< DocumentObject* > obj) { + + Group.setValues(std::vector< DocumentObject* > ()); + return addObjects(obj); +} + std::vector GroupExtension::removeObject(DocumentObject* obj) { std::vector vec = {obj}; diff --git a/src/App/GroupExtension.h b/src/App/GroupExtension.h index 0e1d27d0b8..a12ac5ce63 100644 --- a/src/App/GroupExtension.h +++ b/src/App/GroupExtension.h @@ -56,6 +56,11 @@ public: /* Adds the objects \a objs to this group. Returns all objects that have been added. */ virtual std::vector addObjects(std::vector obj); + + /* Sets the objects in this group. Everything contained already will be removed first + */ + virtual std::vector< DocumentObject* > setObjects(std::vector< DocumentObject* > obj); + /*override this function if you want only special objects */ virtual bool allowObject(DocumentObject* ) {return true;} diff --git a/src/App/GroupExtensionPy.xml b/src/App/GroupExtensionPy.xml index 252ce45ccf..9b0950bbb0 100644 --- a/src/App/GroupExtensionPy.xml +++ b/src/App/GroupExtensionPy.xml @@ -20,22 +20,27 @@ - Add an object to the group + Add an object to the group. Returns all objects that have been added. - Adds multiple objects to the group. Expects a list. + Adds multiple objects to the group. Expects a list and returns all objects that have been added. + + + + + Sets the objects of the group. Expects a list and returns all objects that are now in the group. - Remove an object from the group + Remove an object from the group and returns all objects that have been removed. - Remove multiple objects from the group. Expects a list. + Remove multiple objects from the group. Expects a list and returns all objects that have been removed. diff --git a/src/App/GroupExtensionPyImp.cpp b/src/App/GroupExtensionPyImp.cpp index c9cb181150..dc04eb930f 100644 --- a/src/App/GroupExtensionPyImp.cpp +++ b/src/App/GroupExtensionPyImp.cpp @@ -131,6 +131,44 @@ PyObject* GroupExtensionPy::addObjects(PyObject *args) { throw Base::TypeError(error); }; + +PyObject* GroupExtensionPy::setObjects(PyObject *args) { + + PyObject *object; + if (!PyArg_ParseTuple(args, "O", &object)) // convert args: Python->C + return NULL; // NULL triggers exception + + if (PyTuple_Check(object) || PyList_Check(object)) { + Py::Sequence list(object); + Py::Sequence::size_type size = list.size(); + std::vector values; + values.resize(size); + + for (Py::Sequence::size_type i = 0; i < size; i++) { + Py::Object item = list[i]; + if (!PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { + std::string error = std::string("type in list must be 'DocumentObject', not "); + error += (*item)->ob_type->tp_name; + throw Base::TypeError(error); + } + + values[i] = static_cast(*item)->getDocumentObjectPtr(); + } + + GroupExtension* grp = getGroupExtensionPtr(); + auto vec = grp->setObjects(values); + Py::List result; + for (App::DocumentObject* obj : vec) + result.append(Py::asObject(obj->getPyObject())); + + return Py::new_reference_to(result); + } + + std::string error = std::string("type must be list of 'DocumentObject', not "); + error += object->ob_type->tp_name; + throw Base::TypeError(error); +}; + PyObject* GroupExtensionPy::removeObject(PyObject *args) { PyObject *object; diff --git a/src/App/OriginGroupExtension.cpp b/src/App/OriginGroupExtension.cpp index ca4b694bea..453f6d9e85 100644 --- a/src/App/OriginGroupExtension.cpp +++ b/src/App/OriginGroupExtension.cpp @@ -42,6 +42,7 @@ OriginGroupExtension::OriginGroupExtension () { initExtensionType(OriginGroupExtension::getExtensionClassTypeId()); EXTENSION_ADD_PROPERTY_TYPE ( Origin, (0), 0, App::Prop_Hidden, "Origin linked to the group" ); + Origin.setScope(LinkScope::Global); } OriginGroupExtension::~OriginGroupExtension () diff --git a/src/Mod/Part/App/BodyBase.cpp b/src/Mod/Part/App/BodyBase.cpp index 462f3588fb..a04b82dbd5 100644 --- a/src/Mod/Part/App/BodyBase.cpp +++ b/src/Mod/Part/App/BodyBase.cpp @@ -41,6 +41,8 @@ PROPERTY_SOURCE_WITH_EXTENSIONS(Part::BodyBase, Part::Feature) BodyBase::BodyBase() { ADD_PROPERTY(Tip , (0) ); + Tip.setScope(App::LinkScope::Child); + ADD_PROPERTY(BaseFeature , (0) ); App::OriginGroupExtension::initExtension(this); diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index 7e4f67b644..3646b78bb9 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -55,7 +55,6 @@ using namespace PartDesign; PROPERTY_SOURCE(PartDesign::Body, Part::BodyBase) Body::Body() { - ADD_PROPERTY_TYPE (Origin, (0), 0, App::Prop_Hidden, "Origin linked to the body" ); } /* diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index 29b37d973f..4ad361912b 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -46,7 +46,7 @@ using namespace PartDesign; namespace PartDesign { -PROPERTY_SOURCE(PartDesign::Boolean, PartDesign::Feature) +PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::Boolean, PartDesign::Feature) const char* Boolean::TypeEnums[]= {"Fuse","Cut","Common","Section",NULL}; @@ -54,13 +54,13 @@ Boolean::Boolean() { ADD_PROPERTY(Type,((long)0)); Type.setEnums(TypeEnums); - ADD_PROPERTY(Bodies,(0)); - Bodies.setSize(0); + + initExtension(this); } short Boolean::mustExecute() const { - if (Bodies.isTouched()) + if (Group.isTouched()) return 1; return PartDesign::Feature::mustExecute(); } @@ -74,8 +74,8 @@ App::DocumentObjectExecReturn *Boolean::execute(void) return new App::DocumentObjectExecReturn("Cannot do boolean operation with invalid BaseFeature"); } - std::vector bodies = Bodies.getValues(); - if (bodies.empty()) + std::vector tools = Group.getValues(); + if (tools.empty()) return App::DocumentObject::StdReturn; // Get the base shape to operate on @@ -89,84 +89,66 @@ App::DocumentObjectExecReturn *Boolean::execute(void) if(!baseBody) return new App::DocumentObjectExecReturn("Cannot do boolean on feature which is not in a body"); - // TODO: Why is Feature::getLocation() protected? - Base::Placement place = baseBody->Placement.getValue(); - Base::Rotation rot(place.getRotation()); - Base::Vector3d axis; - double angle; - rot.getValue(axis, angle); - gp_Trsf trf; - trf.SetRotation(gp_Ax1(gp_Pnt(), gp_Dir(axis.x, axis.y, axis.z)), angle); - trf.SetTranslationPart(gp_Vec(place.getPosition().x,place.getPosition().y,place.getPosition().z)); - TopLoc_Location objLoc(trf); - TopoDS_Shape result = baseTopShape.getShape(); - result.Move(objLoc); // Get the operation type std::string type = Type.getValueAsString(); - for (std::vector::const_iterator b = bodies.begin(); b != bodies.end(); b++) + for (auto tool : tools) { // Extract the body shape. Its important to get the actual feature that provides the last solid in the body // so that the placement will be right - PartDesign::Body* body = static_cast(*b); + if(!tool->isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Cannot do boolean with anything but Part::Feature and its derivatives"); - TopoDS_Shape shape = body->Shape.getValue(); - - // Move the shape to the location of the base shape in the other body - Base::Placement pl = body->Placement.getValue(); - // TODO: Why is Feature::getLocation() protected? - Base::Rotation rot(pl.getRotation()); - Base::Vector3d axis; - double angle; - rot.getValue(axis, angle); - gp_Trsf trf; - trf.SetRotation(gp_Ax1(gp_Pnt(), gp_Dir(axis.x, axis.y, axis.z)), angle); - trf.SetTranslationPart(gp_Vec(pl.getPosition().x,pl.getPosition().y,pl.getPosition().z)); - TopLoc_Location bLoc(trf); - shape.Move(bLoc); - + TopoDS_Shape shape = static_cast(tool)->Shape.getValue(); TopoDS_Shape boolOp; if (type == "Fuse") { BRepAlgoAPI_Fuse mkFuse(result, shape); if (!mkFuse.IsDone()) - return new App::DocumentObjectExecReturn("Fusion of bodies failed", *b); + return new App::DocumentObjectExecReturn("Fusion of tools failed"); // we have to get the solids (fuse sometimes creates compounds) boolOp = this->getSolid(mkFuse.Shape()); // lets check if the result is a solid if (boolOp.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *b); + return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); } else if (type == "Cut") { BRepAlgoAPI_Cut mkCut(result, shape); if (!mkCut.IsDone()) - return new App::DocumentObjectExecReturn("Cut out of first body failed", *b); + return new App::DocumentObjectExecReturn("Cut out failed"); boolOp = mkCut.Shape(); } else if (type == "Common") { BRepAlgoAPI_Common mkCommon(result, shape); if (!mkCommon.IsDone()) - return new App::DocumentObjectExecReturn("Common operation with first body failed", *b); + return new App::DocumentObjectExecReturn("Common operation failed"); boolOp = mkCommon.Shape(); } else if (type == "Section") { BRepAlgoAPI_Section mkSection(result, shape); if (!mkSection.IsDone()) - return new App::DocumentObjectExecReturn("Section out of first body failed", *b); + return new App::DocumentObjectExecReturn("Section failed"); // we have to get the solids boolOp = this->getSolid(mkSection.Shape()); // lets check if the result is a solid if (boolOp.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *b); + return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); } result = boolOp; // Use result of this operation for fuse/cut of next body - //bring the result geometry into the correct coordinance of the body the boolean belongs to - BRepBuilderAPI_GTransform mkTrf(result, objLoc.Inverted().Transformation()); - result = mkTrf.Shape(); } this->Shape.setValue(getSolid(result)); return App::DocumentObject::StdReturn; } +void Boolean::onChanged(const App::Property* prop) { + + if(strcmp(prop->getName(), "Group") == 0) + touch(); + + PartDesign::Feature::onChanged(prop); +} + + + } diff --git a/src/Mod/PartDesign/App/FeatureBoolean.h b/src/Mod/PartDesign/App/FeatureBoolean.h index f6b937cfad..61e2a21a6e 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.h +++ b/src/Mod/PartDesign/App/FeatureBoolean.h @@ -25,6 +25,7 @@ #define PARTDESIGN_FeatureBoolean_H #include +#include #include "Feature.h" @@ -35,17 +36,15 @@ namespace PartDesign * Abstract superclass of all features that are created by transformation of another feature * Transformations are translation, rotation and mirroring */ -class PartDesignExport Boolean : public PartDesign::Feature +class PartDesignExport Boolean : public PartDesign::Feature, public App::GeoFeatureGroupExtension { - PROPERTY_HEADER(PartDesign::Boolean); + PROPERTY_HEADER_WITH_EXTENSIONS(PartDesign::Boolean); public: Boolean(); /// The type of the boolean operation App::PropertyEnumeration Type; - /// The bodies for the operation - App::PropertyLinkList Bodies; /** @name methods override feature */ //@{ @@ -56,6 +55,7 @@ public: const char* getViewProviderName(void) const { return "PartDesignGui::ViewProviderBoolean"; } + virtual void onChanged(const App::Property* prop); //@} private: diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 4617dfe3e7..c614aa227c 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -2136,13 +2136,13 @@ void CmdPartDesignBoolean::activated(int iMsg) PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); if (!pcActiveBody) return; - Gui::SelectionFilter BodyFilter("SELECT PartDesign::Body COUNT 1.."); + Gui::SelectionFilter BodyFilter("SELECT Part::Feature COUNT 1.."); openCommand("Create Boolean"); std::string FeatName = getUniqueObjectName("Boolean"); doCommand(Doc,"App.activeDocument().addObject('PartDesign::Boolean','%s')",FeatName.c_str()); - if (BodyFilter.match()) { + if (BodyFilter.match() && !BodyFilter.Result.empty()) { std::vector bodies; std::vector >::iterator i = BodyFilter.Result.begin(); for (; i != BodyFilter.Result.end(); i++) { @@ -2152,7 +2152,7 @@ void CmdPartDesignBoolean::activated(int iMsg) } } std::string bodyString = PartDesignGui::buildLinkListPythonStr(bodies); - doCommand(Doc,"App.activeDocument().%s.Bodies = %s",FeatName.c_str(),bodyString.c_str()); + doCommand(Doc,"App.activeDocument().%s.addObjects(%s)",FeatName.c_str(),bodyString.c_str()); } finishFeature(this, FeatName, nullptr, false); diff --git a/src/Mod/PartDesign/Gui/TaskBooleanParameters.cpp b/src/Mod/PartDesign/Gui/TaskBooleanParameters.cpp index c20db46af9..9bba9cc992 100644 --- a/src/Mod/PartDesign/Gui/TaskBooleanParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskBooleanParameters.cpp @@ -71,7 +71,7 @@ TaskBooleanParameters::TaskBooleanParameters(ViewProviderBoolean *BooleanView,QW this->groupLayout()->addWidget(proxy); PartDesign::Boolean* pcBoolean = static_cast(BooleanView->getObject()); - std::vector bodies = pcBoolean->Bodies.getValues(); + std::vector bodies = pcBoolean->Group.getValues(); for (std::vector::const_iterator b = bodies.begin(); b != bodies.end(); b++) { ui->listWidgetBodies->insertItem(0, QString::fromLatin1((*b)->getNameInDocument())); @@ -108,12 +108,13 @@ void TaskBooleanParameters::onSelectionChanged(const Gui::SelectionChanges& msg) return; } - std::vector bodies = pcBoolean->Bodies.getValues(); + std::vector bodies = pcBoolean->Group.getValues(); if (selectionMode == bodyAdd) { if (std::find(bodies.begin(), bodies.end(), pcBody) == bodies.end()) { bodies.push_back(pcBody); - pcBoolean->Bodies.setValues(bodies); + pcBoolean->Group.setValues(std::vector()); + pcBoolean->addObjects(bodies); ui->listWidgetBodies->insertItem(ui->listWidgetBodies->count(), QString::fromStdString(pcBody->getNameInDocument())); @@ -145,7 +146,7 @@ void TaskBooleanParameters::onSelectionChanged(const Gui::SelectionChanges& msg) std::vector::iterator b = std::find(bodies.begin(), bodies.end(), pcBody); if (b != bodies.end()) { bodies.erase(b); - pcBoolean->Bodies.setValues(bodies); + pcBoolean->setObjects(bodies); QList items = ui->listWidgetBodies->findItems(QString::fromStdString(body), Qt::MatchExactly); if (!items.empty()) { for (QList::const_iterator i = items.begin(); i != items.end(); i++) { @@ -180,7 +181,7 @@ void TaskBooleanParameters::onButtonBodyAdd(bool checked) PartDesign::Boolean* pcBoolean = static_cast(BooleanView->getObject()); Gui::Document* doc = BooleanView->getDocument(); BooleanView->hide(); - if (pcBoolean->Bodies.getValues().empty() && pcBoolean->BaseFeature.getValue()) + if (pcBoolean->Group.getValues().empty() && pcBoolean->BaseFeature.getValue()) doc->setHide(pcBoolean->BaseFeature.getValue()->getNameInDocument()); selectionMode = bodyAdd; Gui::Selection().clearSelection(); @@ -233,13 +234,13 @@ int TaskBooleanParameters::getType(void) const void TaskBooleanParameters::onBodyDeleted(void) { PartDesign::Boolean* pcBoolean = static_cast(BooleanView->getObject()); - std::vector bodies = pcBoolean->Bodies.getValues(); + std::vector bodies = pcBoolean->Group.getValues(); int index = ui->listWidgetBodies->currentRow(); if (index < 0 && (size_t) index > bodies.size()) return; App::DocumentObject* body = bodies[index]; bodies.erase(bodies.begin() + ui->listWidgetBodies->currentRow()); - pcBoolean->Bodies.setValues(bodies); + pcBoolean->setObjects(bodies); ui->listWidgetBodies->model()->removeRow(ui->listWidgetBodies->currentRow()); pcBoolean->getDocument()->recomputeFeature(pcBoolean); @@ -323,10 +324,10 @@ bool TaskDlgBooleanParameters::accept() try { std::vector bodies = parameter->getBodies(); std::stringstream str; - str << "App.ActiveDocument." << name.c_str() << ".Bodies = ["; + str << "App.ActiveDocument." << name.c_str() << ".setObjects( ["; for (std::vector::const_iterator it = bodies.begin(); it != bodies.end(); ++it) str << "App.ActiveDocument." << *it << ","; - str << "]"; + str << "])"; Gui::Command::runCommand(Gui::Command::Doc,str.str().c_str()); } catch (const Base::Exception& e) { @@ -350,7 +351,7 @@ bool TaskDlgBooleanParameters::reject() if (doc != NULL) { if (obj->BaseFeature.getValue() != NULL) { doc->setShow(obj->BaseFeature.getValue()->getNameInDocument()); - std::vector bodies = obj->Bodies.getValues(); + std::vector bodies = obj->Group.getValues(); for (std::vector::const_iterator b = bodies.begin(); b != bodies.end(); b++) doc->setShow((*b)->getNameInDocument()); } diff --git a/src/Mod/PartDesign/Gui/ViewProviderBoolean.cpp b/src/Mod/PartDesign/Gui/ViewProviderBoolean.cpp index fe19263dc6..48ec58ce83 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBoolean.cpp @@ -40,11 +40,12 @@ using namespace PartDesignGui; -PROPERTY_SOURCE(PartDesignGui::ViewProviderBoolean,PartDesignGui::ViewProvider) +PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesignGui::ViewProviderBoolean,PartDesignGui::ViewProvider) ViewProviderBoolean::ViewProviderBoolean() { sPixmap = "PartDesign_Boolean.svg"; + initExtension(this); } ViewProviderBoolean::~ViewProviderBoolean() @@ -101,17 +102,12 @@ bool ViewProviderBoolean::setEdit(int ModNum) } } -std::vector ViewProviderBoolean::claimChildren(void)const -{ - return static_cast(getObject())->Bodies.getValues(); -} - bool ViewProviderBoolean::onDelete(const std::vector &s) { PartDesign::Boolean* pcBoolean = static_cast(getObject()); // if abort command deleted the object the bodies are visible again - std::vector bodies = pcBoolean->Bodies.getValues(); + std::vector bodies = pcBoolean->Group.getValues(); for (std::vector::const_iterator b = bodies.begin(); b != bodies.end(); b++) { if (*b && Gui::Application::Instance->getViewProvider(*b)) Gui::Application::Instance->getViewProvider(*b)->show(); diff --git a/src/Mod/PartDesign/Gui/ViewProviderBoolean.h b/src/Mod/PartDesign/Gui/ViewProviderBoolean.h index 90de970002..726ad0c80c 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBoolean.h +++ b/src/Mod/PartDesign/Gui/ViewProviderBoolean.h @@ -25,13 +25,15 @@ #define PARTGUI_ViewProviderBoolean_H #include "ViewProvider.h" +#include namespace PartDesignGui { -class PartDesignGuiExport ViewProviderBoolean : public ViewProvider +class PartDesignGuiExport ViewProviderBoolean : public ViewProvider, + public Gui::ViewProviderGeoFeatureGroupExtension { - PROPERTY_HEADER(PartDesignGui::ViewProviderBoolean); + PROPERTY_HEADER_WITH_EXTENSIONS(PartDesignGui::ViewProviderBoolean); public: /// constructor @@ -41,7 +43,6 @@ public: /// grouping handling void setupContextMenu(QMenu*, QObject*, const char*); - std::vector claimChildren(void)const; virtual bool onDelete(const std::vector &); diff --git a/src/Mod/PartDesign/PartDesignTests/TestBoolean.py b/src/Mod/PartDesign/PartDesignTests/TestBoolean.py index 314e962d4b..7fb3d8d9b2 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestBoolean.py +++ b/src/Mod/PartDesign/PartDesignTests/TestBoolean.py @@ -47,7 +47,7 @@ class TestBoolean(unittest.TestCase): self.BooleanFuse = self.Doc.addObject('PartDesign::Boolean','BooleanFuse') self.Body001.addObject(self.BooleanFuse) self.Doc.recompute() - self.BooleanFuse.Bodies = [self.Body,] + self.BooleanFuse.setObjects([self.Body,]) self.BooleanFuse.Type = 0 self.Doc.recompute() self.assertAlmostEqual(self.BooleanFuse.Shape.Volume, 1500) @@ -71,7 +71,7 @@ class TestBoolean(unittest.TestCase): self.BooleanCut = self.Doc.addObject('PartDesign::Boolean','BooleanCut') self.Body001.addObject(self.BooleanCut) self.Doc.recompute() - self.BooleanCut.Bodies = [self.Body,] + self.BooleanCut.setObjects([self.Body,]) self.BooleanCut.Type = 1 self.Doc.recompute() self.assertAlmostEqual(self.BooleanCut.Shape.Volume, 500) @@ -95,7 +95,7 @@ class TestBoolean(unittest.TestCase): self.BooleanCommon = self.Doc.addObject('PartDesign::Boolean','BooleanCommon') self.Body001.addObject(self.BooleanCommon) self.Doc.recompute() - self.BooleanCommon.Bodies = [self.Body,] + self.BooleanCommon.setObjects([self.Body,]) self.BooleanCommon.Type = 2 self.Doc.recompute() self.assertAlmostEqual(self.BooleanCommon.Shape.Volume, 500)