Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group fixes #803

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a91784e
Fix drag&drop of geofeature groups. fixes #0002835 fixes #0002796
ickby Jan 19, 2017
d2420b6
Introduce global placement calculations
ickby Jan 29, 2017
b035add
Sketcher: Use correct global placements
ickby Jan 29, 2017
4beb26e
Consistently name origins
ickby Jan 29, 2017
d0eaa8d
DependencyGraph: Show GeoFeatureGroups as subgraph. fixes #0002142
ickby Jan 29, 2017
9ac2595
DependencyGraph: Show origins correctly
ickby Jan 29, 2017
d047405
DependencyGraph: Add unflatten step
ickby Jan 30, 2017
c04d571
DependencyGraph: Subgraphs are identified by label
ickby Jan 30, 2017
43868dd
DependencyGraph: Add colors to coordinate systems
ickby Jan 30, 2017
5c8585f
DependencyGraph: Fix colors and unflatten
ickby Jan 31, 2017
afd3495
DependencyGraph: grouping & unflatten is optional
ickby Jan 31, 2017
c4e8836
Unify and fix group handling in geofeaturegroups
ickby Feb 8, 2017
264134f
GeoFeatureGroup: add object adds relevant links
ickby Feb 9, 2017
cd4619c
Groups: Handle add and remove object correctly
ickby Feb 9, 2017
b723a54
GeoFeatureGroup: Handle drag into document
ickby Feb 9, 2017
56806e9
Fix collecting of cs relevant links
ickby Feb 9, 2017
6854d87
Drag&Drop: Tree is responsible for undo/redo
ickby Feb 9, 2017
9ddc42e
Parent groups are irelevant, not only parent geofeaturegroups
ickby Feb 9, 2017
2e650cf
Group: ensure single group only
ickby Feb 9, 2017
50ae054
Links ensure uncyclic graph and correct groups
ickby Feb 10, 2017
7d17b90
Group tests and fixes
ickby Feb 11, 2017
9e8a030
Fix undo/redo while checking link integrity
ickby Feb 11, 2017
d559355
Extend python interface for groups and fix test cases
ickby Feb 12, 2017
f2d1302
Allow add/remove multiple objects in a group
ickby Feb 17, 2017
7ce514b
Partially fix PartDesign move test
ickby Feb 18, 2017
699abe9
GeoFeatureGroup: Make link collection non-DAG save
ickby Jun 3, 2017
c9b1b83
Revert link integrity checks in properties
ickby Jun 3, 2017
4163282
DependencyGraph: Ensure OriginFeatures get in the correct subgraph
ickby Jun 3, 2017
3687f01
Add missing header for random numbers
ickby Jun 3, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
189 changes: 161 additions & 28 deletions src/App/Document.cpp

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/App/Document.h
Expand Up @@ -230,7 +230,8 @@ class AppExport Document : public App::PropertyContainer
/// Returns a list of all Objects
std::vector<DocumentObject*> getObjects() const;
std::vector<DocumentObject*> getObjectsOfType(const Base::Type& typeId) const;
std::vector<DocumentObject*> getObjectsWithExtension(const Base::Type& typeId) const;
/// Returns all object with given extensions. If derived=true also all objects with extenions derived from the given one
std::vector<DocumentObject*> getObjectsWithExtension(const Base::Type& typeId, bool derived = true) const;
std::vector<DocumentObject*> findObjects(const Base::Type& typeId, const char* objname) const;
/// Returns an array with the correct types already.
template<typename T> inline std::vector<T*> getObjectsOfType() const;
Expand Down Expand Up @@ -305,6 +306,8 @@ class AppExport Document : public App::PropertyContainer
std::vector<std::string> getAvailableRedoNames() const;
/// Will REDO one step, returns False if no redo was done (Redos == 0).
bool redo() ;
/// returns true if the document is in an Transaction phase, e.g. currently performing a redo/undo or rollback
bool performsTransactionOperation();
//@}

/** @name dependency stuff */
Expand Down
10 changes: 6 additions & 4 deletions src/App/DocumentObject.cpp
Expand Up @@ -422,10 +422,12 @@ void DocumentObject::onChanged(const Property* prop)
if (prop == &Label && _pDoc && oldLabel != Label.getStrValue())
_pDoc->signalRelabelObject(*this);

if (prop->getType() & Prop_Output)
return;
// set object touched
StatusBits.set(ObjectStatus::Touch);
// set object touched if it is a input ptoperty
if (!(prop->getType() & Prop_Output))
StatusBits.set(0);

//call the parent for appropriate handling
TransactionalObject::onChanged(prop);
}

PyObject *DocumentObject::getPyObject(void)
Expand Down
14 changes: 14 additions & 0 deletions src/App/DocumentObjectPy.xml
Expand Up @@ -55,6 +55,20 @@
<UserDocu>Recomputes this object</UserDocu>
</Documentation>
</Methode>
<Methode Name="getParentGroup">
<Documentation>
<UserDocu>Returns the group the object is in or None if it is not part of a group.
Note that an object can only be in a single group, hence only a single return
value.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getParentGeoFeatureGroup">
<Documentation>
<UserDocu>Returns the GeoFeatureGroup, and hence the local coorinate system, the object
is in or None if it is not part of a group. Note that an object can only be
in a single group, hence only a single return value.</UserDocu>
</Documentation>
</Methode>
<Attribute Name="OutList" ReadOnly="true">
<Documentation>
<UserDocu>A list of all objects this object links to.</UserDocu>
Expand Down
38 changes: 38 additions & 0 deletions src/App/DocumentObjectPyImp.cpp
Expand Up @@ -25,6 +25,8 @@
#include "DocumentObject.h"
#include "Document.h"
#include "Expression.h"
#include "GroupExtension.h"
#include "GeoFeatureGroupExtension.h"

// inclusion of the generated files (generated out of DocumentObjectPy.xml)
#include <App/DocumentObjectPy.h>
Expand Down Expand Up @@ -315,6 +317,42 @@ PyObject* DocumentObjectPy::recompute(PyObject *args)
}
}

PyObject* DocumentObjectPy::getParentGroup(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;

try {
auto grp = GroupExtension::getGroupOfObject(getDocumentObjectPtr());
if(!grp) {
Py_INCREF(Py_None);
return Py_None;
}
return grp->getPyObject();
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
}
}

PyObject* DocumentObjectPy::getParentGeoFeatureGroup(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;

try {
auto grp = GeoFeatureGroupExtension::getGroupOfObject(getDocumentObjectPtr());
if(!grp) {
Py_INCREF(Py_None);
return Py_None;
}
return grp->getPyObject();
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
}
}

PyObject *DocumentObjectPy::getCustomAttributes(const char* attr) const
{
// search for dynamic property
Expand Down
12 changes: 6 additions & 6 deletions src/App/ExtensionContainer.cpp
Expand Up @@ -68,19 +68,19 @@ void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext)
_extensions[extension] = ext;
}

bool ExtensionContainer::hasExtension(Base::Type t) const {
bool ExtensionContainer::hasExtension(Base::Type t, bool derived) const {

//check for the exact type
bool found = _extensions.find(t) != _extensions.end();
if(!found) {
if(!found && derived) {
//and for types derived from it, as they can be cast to the extension
for(auto entry : _extensions) {
if(entry.first.isDerivedFrom(t))
return true;
}
return false;
}
return true;
return found;
}

bool ExtensionContainer::hasExtension(const std::string& name) const {
Expand All @@ -94,10 +94,10 @@ bool ExtensionContainer::hasExtension(const std::string& name) const {
}


Extension* ExtensionContainer::getExtension(Base::Type t) {
Extension* ExtensionContainer::getExtension(Base::Type t, bool derived) const {

auto result = _extensions.find(t);
if(result == _extensions.end()) {
if((result == _extensions.end()) && derived) {
//we need to check for derived types
for(auto entry : _extensions) {
if(entry.first.isDerivedFrom(t))
Expand All @@ -115,7 +115,7 @@ bool ExtensionContainer::hasExtensions() const {
return !_extensions.empty();
}

Extension* ExtensionContainer::getExtension(const std::string& name) {
Extension* ExtensionContainer::getExtension(const std::string& name) const {

//and for types derived from it, as they can be cast to the extension
for(auto entry : _extensions) {
Expand Down
8 changes: 4 additions & 4 deletions src/App/ExtensionContainer.h
Expand Up @@ -124,15 +124,15 @@ class AppExport ExtensionContainer : public App::PropertyContainer
virtual ~ExtensionContainer();

void registerExtension(Base::Type extension, App::Extension* ext);
bool hasExtension(Base::Type) const; //returns first of type (or derived from) and throws otherwise
bool hasExtension(Base::Type, bool derived=true) const; //returns first of type (or derived from if set to true) and throws otherwise
bool hasExtension(const std::string& name) const; //this version does not check derived classes
bool hasExtensions() const;
App::Extension* getExtension(Base::Type); //returns first of type (or derived from) and throws otherwise
App::Extension* getExtension(const std::string& name); //this version does not check derived classes
App::Extension* getExtension(Base::Type, bool derived = true) const;
App::Extension* getExtension(const std::string& name) const; //this version does not check derived classes

//returns first of type (or derived from) and throws otherwise
template<typename ExtensionT>
ExtensionT* getExtensionByType() {
ExtensionT* getExtensionByType() const {
return dynamic_cast<ExtensionT*>(getExtension(ExtensionT::getExtensionClassTypeId()));
};

Expand Down
11 changes: 11 additions & 0 deletions src/App/GeoFeature.cpp
Expand Up @@ -27,6 +27,7 @@
#endif

#include "GeoFeature.h"
#include "GeoFeatureGroupExtension.h"
#include <App/GeoFeaturePy.h>

using namespace App;
Expand Down Expand Up @@ -55,6 +56,16 @@ void GeoFeature::transformPlacement(const Base::Placement &transform)
this->Placement.setValue(plm);
}

Base::Placement GeoFeature::globalPlacement()
{
auto* group = GeoFeatureGroupExtension::getGroupOfObject(this);
if(group) {
auto ext = group->getExtensionByType<GeoFeatureGroupExtension>();
return ext->globalGroupPlacement() * Placement.getValue();
}
return Placement.getValue();
}

const PropertyComplexGeoData* GeoFeature::getPropertyOfGeometry() const
{
return nullptr;
Expand Down
14 changes: 14 additions & 0 deletions src/App/GeoFeature.h
Expand Up @@ -66,6 +66,20 @@ class AppExport GeoFeature : public App::DocumentObject
* @return the Python binding object
*/
virtual PyObject* getPyObject(void);

/**
* @brief Calculates the placement in the global reference coordinate system
*
* In FreeCAD the GeoFeature placement describes the local placement of the object in its parent
* coordinate system. This is however not always the same as the global reference system. If the
* object is in a GeoFeatureGroup, hence in annother local coordinate system, the Placement
* property does only give the local transformation. This function can be used to calculate the
* placement of the object in the global reference coordinate system taking all stacked local
* system into account.
*
* @return Base::Placement The transformation from the global reference coordinate system
*/
Base::Placement globalPlacement();
};

} //namespace App
Expand Down