Skip to content

Commit

Permalink
PartDesign: Port body to be a origin group
Browse files Browse the repository at this point in the history
  • Loading branch information
ickby authored and wwmayer committed Jan 4, 2017
1 parent 47ed29f commit 9a3b952
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 128 deletions.
8 changes: 4 additions & 4 deletions src/App/GroupExtension.h
Expand Up @@ -49,20 +49,20 @@ class AppExport GroupExtension : public DocumentObjectExtension
/** Adds an object of \a sType with \a pObjectName to the document this group belongs to and
* append it to this group as well.
*/
DocumentObject *addObject(const char* sType, const char* pObjectName);
virtual DocumentObject *addObject(const char* sType, const char* pObjectName);
/* Adds the object \a obj to this group.
*/
void addObject(DocumentObject* obj);
virtual void addObject(DocumentObject* obj);
/*override this function if you want only special objects
*/
virtual bool allowObject(DocumentObject* ) {return true;};

/** Removes an object from this group.
*/
void removeObject(DocumentObject* obj);
virtual void removeObject(DocumentObject* obj);
/** Removes all children objects from this group and the document.
*/
void removeObjectsFromDocument();
virtual void removeObjectsFromDocument();
/** Returns the object of this group with \a Name. If the group doesn't have such an object 0 is returned.
* @note This method might return 0 even if the document this group belongs to contains an object with this name.
*/
Expand Down
15 changes: 4 additions & 11 deletions src/Mod/Part/App/BodyBase.cpp
Expand Up @@ -35,29 +35,22 @@
namespace Part {


PROPERTY_SOURCE(Part::BodyBase, Part::Feature)
PROPERTY_SOURCE_WITH_EXTENSIONS(Part::BodyBase, Part::Feature)

BodyBase::BodyBase()
{
ADD_PROPERTY(Model , (0) );
ADD_PROPERTY(Tip , (0) );
ADD_PROPERTY(BaseFeature , (0) );
}

bool BodyBase::hasFeature(const App::DocumentObject* f) const
{
const std::vector<App::DocumentObject*> &features = Model.getValues();
return f == BaseFeature.getValue() || std::find(features.begin(), features.end(), f) != features.end();
}

BodyBase* BodyBase::findBodyOf(const App::DocumentObject* f)
{
App::Document* doc = f->getDocument();
if (doc != NULL) {
std::vector<App::DocumentObject*> bodies = doc->getObjectsOfType(BodyBase::getClassTypeId());
for (std::vector<App::DocumentObject*>::const_iterator b = bodies.begin(); b != bodies.end(); b++) {
BodyBase* body = static_cast<BodyBase*>(*b);
if (body->hasFeature(f))
if (body->hasObject(f))
return body;
}
}
Expand All @@ -73,10 +66,10 @@ bool BodyBase::isAfter(const App::DocumentObject *feature, const App::DocumentOb
}

if (!target || target == BaseFeature.getValue() ) {
return hasFeature (feature);
return hasObject (feature);
}

const std::vector<App::DocumentObject *> & features = Model.getValues();
const std::vector<App::DocumentObject *> & features = Group.getValues();
auto featureIt = std::find(features.begin(), features.end(), feature);
auto targetIt = std::find(features.begin(), features.end(), target);

Expand Down
21 changes: 6 additions & 15 deletions src/Mod/Part/App/BodyBase.h
Expand Up @@ -25,6 +25,7 @@
#define PART_BodyBase_H

#include <App/PropertyStandard.h>
#include <App/OriginGroupExtension.h>
#include <Mod/Part/App/PartFeature.h>


Expand All @@ -36,19 +37,16 @@ namespace Part
* in edit or active on a workbench, the body shows only the
* resulting shape to the outside (Tip link).
*/
class PartExport BodyBase : public Part::Feature
class PartExport BodyBase : public Part::Feature, public App::OriginGroupExtension
{
PROPERTY_HEADER(Part::BodyBase);
PROPERTY_HEADER_WITH_EXTENSIONS(Part::BodyBase);

public:
BodyBase();

/// The list of features
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.
* Note: tip may either point to the BaseFeature or to some feature inside the Group list.
* in case it points to the model the PartDesign::Body guaranties that it is a solid.
*/
App::PropertyLink Tip;
Expand All @@ -59,23 +57,16 @@ class PartExport BodyBase : public Part::Feature
*/
App::PropertyLink BaseFeature;

/// Returns all Model objects prepanded by BaseFeature (if any)
/// Returns all Group objects prepanded by BaseFeature (if any)
std::vector<App::DocumentObject *> getFullModel () {
std::vector<App::DocumentObject *> rv;
if ( BaseFeature.getValue () ) {
rv.push_back ( BaseFeature.getValue () );
}
std::copy ( Model.getValues ().begin (), Model.getValues ().end (), std::back_inserter (rv) );
std::copy ( Group.getValues ().begin (), Group.getValues ().end (), std::back_inserter (rv) );
return rv;
}

// These methods are located here to avoid a dependency of ViewProviderSketchObject on PartDesign
/// Remove the feature from the body
virtual void removeFeature(App::DocumentObject*){}

/// Return true if the feature belongs to this body or either the body is based on the feature
bool hasFeature(const App::DocumentObject *f) const;

/// Return true if the feature belongs to the body and is located after the target
bool isAfter(const App::DocumentObject *feature, const App::DocumentObject *target) const;

Expand Down
73 changes: 25 additions & 48 deletions src/Mod/PartDesign/App/Body.cpp
Expand Up @@ -60,15 +60,15 @@ Body::Body() {

/*
// Note: The following code will catch Python Document::removeObject() modifications. If the object removed is
// a member of the Body::Model, then it will be automatically removed from the Model property which triggers the
// a member of the Body::Group, then it will be automatically removed from the Group property which triggers the
// following two methods
// But since we require the Python user to call both Document::addObject() and Body::addFeature(), we should
// also require calling both Document::removeObject and Body::removeFeature() in order to be consistent
void Body::onBeforeChange(const App::Property *prop)
{
// Remember the feature before the current Tip. If the Tip is already at the first feature, remember the next feature
if (prop == &Model) {
std::vector<App::DocumentObject*> features = Model.getValues();
if (prop == &Group) {
std::vector<App::DocumentObject*> features = Group.getValues();
if (features.empty()) {
rememberTip = NULL;
} else {
Expand All @@ -91,8 +91,8 @@ void Body::onBeforeChange(const App::Property *prop)
void Body::onChanged(const App::Property *prop)
{
if (prop == &Model) {
std::vector<App::DocumentObject*> features = Model.getValues();
if (prop == &Group) {
std::vector<App::DocumentObject*> features = Group.getValues();
if (features.empty()) {
Tip.setValue(NULL);
} else {
Expand All @@ -119,7 +119,7 @@ short Body::mustExecute() const

App::DocumentObject* Body::getPrevFeature(App::DocumentObject *start) const
{
std::vector<App::DocumentObject*> features = Model.getValues();
std::vector<App::DocumentObject*> features = Group.getValues();
if (features.empty()) return NULL;
App::DocumentObject* st = (start == NULL ? Tip.getValue() : start);
if (st == NULL)
Expand All @@ -146,9 +146,9 @@ App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start)
return nullptr;
}

assert ( hasFeature ( start ) );
assert ( hasObject ( start ) );

const std::vector<App::DocumentObject*> & features = Model.getValues();
const std::vector<App::DocumentObject*> & features = Group.getValues();

auto startIt = std::find ( features.rbegin(), features.rend(), start );
assert ( startIt != features.rend() );
Expand All @@ -173,9 +173,9 @@ App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
return nullptr;
}

assert ( hasFeature ( start ) );
assert ( hasObject ( start ) );

const std::vector<App::DocumentObject*> & features = Model.getValues();
const std::vector<App::DocumentObject*> & features = Group.getValues();
std::vector<App::DocumentObject*>::const_iterator startIt;

if ( start == baseFeature ) {
Expand Down Expand Up @@ -264,17 +264,20 @@ Body* Body::findBodyOf(const App::DocumentObject* feature)
}


void Body::addFeature(App::DocumentObject *feature)
void Body::addObject(App::DocumentObject *feature)
{
insertFeature (feature, getNextSolidFeature (), /*after = */ false);
if(!isAllowed(feature))
throw Base::Exception("Body: object is not allowed");

insertObject (feature, getNextSolidFeature (), /*after = */ false);
// Move the Tip if we added a solid
if (isSolidFeature(feature)) {
Tip.setValue (feature);
}
}


void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after)
void Body::insertObject(App::DocumentObject* feature, App::DocumentObject* target, bool after)
{
if (target) {
if (target == BaseFeature.getValue()) {
Expand All @@ -284,13 +287,13 @@ void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* targ
} else {
throw Base::Exception("Body: impossible to insert before the base object");
}
} else if (!hasFeature (target)) {
} 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");
}
}

std::vector<App::DocumentObject*> model = Model.getValues();
std::vector<App::DocumentObject*> model = Group.getValues();
std::vector<App::DocumentObject*>::iterator insertInto;

// Find out the position there to insert the feature
Expand All @@ -313,7 +316,7 @@ void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* targ
// Insert the new feature after the given
model.insert (insertInto, feature);

Model.setValues (model);
Group.setValues (model);

// Set the BaseFeature property
if (Body::isSolidFeature(feature)) {
Expand All @@ -333,7 +336,7 @@ void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* targ
}


void Body::removeFeature(App::DocumentObject* feature)
void Body::removeObject(App::DocumentObject* feature)
{
App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature);
App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature);
Expand All @@ -348,7 +351,7 @@ void Body::removeFeature(App::DocumentObject* feature)
}
}

std::vector<App::DocumentObject*> model = Model.getValues();
std::vector<App::DocumentObject*> model = Group.getValues();
std::vector<App::DocumentObject*>::iterator it = std::find(model.begin(), model.end(), feature);

// Adjust Tip feature if it is pointing to the deleted object
Expand All @@ -360,9 +363,9 @@ void Body::removeFeature(App::DocumentObject* feature)
}
}

// Erase feature from Model
// Erase feature from Group
model.erase(it);
Model.setValues(model);
Group.setValues(model);
}


Expand All @@ -372,8 +375,8 @@ App::DocumentObjectExecReturn *Body::execute(void)
Base::Console().Error("Body '%s':\n", getNameInDocument());
App::DocumentObject* tip = Tip.getValue();
Base::Console().Error(" Tip: %s\n", (tip == NULL) ? "None" : tip->getNameInDocument());
std::vector<App::DocumentObject*> model = Model.getValues();
Base::Console().Error(" Model:\n");
std::vector<App::DocumentObject*> model = Group.getValues();
Base::Console().Error(" Group:\n");
for (std::vector<App::DocumentObject*>::const_iterator m = model.begin(); m != model.end(); m++) {
if (*m == NULL) continue;
Base::Console().Error(" %s", (*m)->getNameInDocument());
Expand Down Expand Up @@ -422,14 +425,6 @@ void Body::onSettingDocument() {
Part::BodyBase::onSettingDocument();
}

void Body::removeModelFromDocument() {
//delete all child objects if needed
std::set<DocumentObject*> grp ( Model.getValues().begin (), Model.getValues().end() );
for (auto obj : grp) {
this->getDocument()->remObject(obj->getNameInDocument());
}
}

void Body::onChanged (const App::Property* prop) {
if ( prop == &BaseFeature ) {
App::DocumentObject *baseFeature = BaseFeature.getValue();
Expand All @@ -443,24 +438,6 @@ void Body::onChanged (const App::Property* prop) {
Part::BodyBase::onChanged ( prop );
}

App::Origin *Body::getOrigin () const {
App::DocumentObject *originObj = Origin.getValue ();

if ( !originObj ) {
std::stringstream err;
err << "Can't find Origin for \"" << getNameInDocument () << "\"";
throw Base::Exception ( err.str().c_str () );

} else if (! originObj->isDerivedFrom ( App::Origin::getClassTypeId() ) ) {
std::stringstream err;
err << "Bad object \"" << originObj->getNameInDocument () << "\"(" << originObj->getTypeId().getName()
<< ") linked to the Origin of \"" << getNameInDocument () << "\"";
throw Base::Exception ( err.str().c_str () );
} else {
return static_cast<App::Origin *> ( originObj );
}
}

void Body::setupObject () {
// NOTE: the code shared with App::OriginGroup
App::Document *doc = getDocument ();
Expand Down
15 changes: 4 additions & 11 deletions src/Mod/PartDesign/App/Body.h
Expand Up @@ -68,7 +68,7 @@ class PartDesignExport Body : public Part::BodyBase
* 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);
virtual void addObject(App::DocumentObject*) override;

/**
* Insert the feature into the body after the given feature.
Expand All @@ -81,13 +81,10 @@ class PartDesignExport Body : public Part::BodyBase
*
* @note the methode doesn't modifies the Tip unlike addFeature()
*/
void insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after=false);
void insertObject(App::DocumentObject* feature, App::DocumentObject* target, bool after=false);

/// Remove the feature from the body
void removeFeature(App::DocumentObject* feature);

/// Delets all the objects linked to the model.
void removeModelFromDocument();
virtual void removeObject(DocumentObject* obj) override;

/**
* Checks if the given document object lays after the current insert point
Expand All @@ -110,20 +107,16 @@ class PartDesignExport Body : public Part::BodyBase
* all features derived from PartDesign::Feature and Part::Datum and sketches
*/
static bool isAllowed(const App::DocumentObject* f);
virtual bool allowObject(DocumentObject* f) {return isAllowed(f);};

/**
* Return the body which this feature belongs too, or NULL
* The only difference to BodyBase::findBodyOf() is that this one casts value to Body*
*/
static Body *findBodyOf(const App::DocumentObject* feature);

/// Returns the origin link or throws an exception
App::Origin *getOrigin () const;

PyObject *getPyObject(void);

/// Origin linked to the property, please use getOrigin () to access it
App::PropertyLink Origin;

protected:
virtual void onSettingDocument();
Expand Down

0 comments on commit 9a3b952

Please sign in to comment.