Skip to content

Commit

Permalink
fixes 0003410: 0.17 Regression: recompute will make parts lose color …
Browse files Browse the repository at this point in the history
…and take a longer delay compared to FC0.16
  • Loading branch information
wwmayer committed Oct 2, 2018
1 parent 4cab61c commit 93f06f8
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 35 deletions.
19 changes: 11 additions & 8 deletions src/App/Document.cpp
Expand Up @@ -2232,22 +2232,25 @@ int Document::recompute()

for (auto objIt = topoSortedObjects.rbegin(); objIt != topoSortedObjects.rend(); ++objIt){
// ask the object if it should be recomputed
if ((*objIt)->isTouched() || (*objIt)->mustExecute() == 1){
bool doRecompute = false;
if ((*objIt)->mustRecompute()) {
doRecompute = true;
objectCount++;
if (_recomputeFeature(*objIt)) {
// if something happened break execution of recompute
return -1;
}
else{
(*objIt)->purgeTouched();
// set all dependent object touched to force recompute
for (auto inObjIt : (*objIt)->getInList())
inObjIt->touch();
}
}

if ((*objIt)->isTouched() || doRecompute) {
(*objIt)->purgeTouched();
// force recompute of all dependent objects
for (auto inObjIt : (*objIt)->getInList())
inObjIt->enforceRecompute();
}
}
#ifdef FC_DEBUG
// check if all objects are recalculated which were thouched
// check if all objects are recalculated which were touched
for (auto objectIt : d->objectArray) {
if (objectIt->isTouched())
cerr << "Document::recompute(): " << objectIt->getNameInDocument() << " still touched after recompute" << endl;
Expand Down
67 changes: 49 additions & 18 deletions src/App/DocumentObject.cpp
Expand Up @@ -110,19 +110,65 @@ bool DocumentObject::recomputeFeature()
return isValid();
}

/**
* @brief Set this document object touched.
* Touching a document object does not mean to recompute it, it only means that
* other document objects that link it (i.e. its InList) will be recomputed.
* If it should be forced to recompute a document object then use
* \ref enforceRecompute() instead.
*/
void DocumentObject::touch(void)
{
StatusBits.set(ObjectStatus::Touch);
}

/**
* @brief Check whether the document object is touched or not.
* @return true if document object is touched, false if not.
*/
bool DocumentObject::isTouched() const
{
return ExpressionEngine.isTouched() || StatusBits.test(ObjectStatus::Touch);
}

/**
* @brief Enforces this document object to be recomputed.
* This can be useful to recompute the feature without
* having to change one of its input properties.
*/
void DocumentObject::enforceRecompute(void)
{
StatusBits.set(ObjectStatus::Enforce);
StatusBits.set(ObjectStatus::Touch);
}

/**
* @brief Check whether the document object must be recomputed or not.
* This means that the 'Enforce' flag is set or that \ref mustExecute()
* returns a value > 0.
* @return true if document object must be recomputed, false if not.
*/
bool DocumentObject::mustRecompute(void) const
{
if (StatusBits.test(ObjectStatus::Enforce))
return true;

return mustExecute() > 0;
}

short DocumentObject::mustExecute(void) const
{
if(isTouched())
if (ExpressionEngine.isTouched())
return 1;

//ask all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
for(auto ext : vector) {
if(ext->extensionMustExecute())
if (ext->extensionMustExecute())
return 1;
}

return 0;

}

const char* DocumentObject::getStatusString(void) const
Expand Down Expand Up @@ -503,21 +549,6 @@ std::vector<PyObject *> DocumentObject::getPySubObjects(const std::vector<std::s
return std::vector<PyObject *>();
}

void DocumentObject::touch(void)
{
StatusBits.set(ObjectStatus::Touch);
}

/**
* @brief Check whether the document object is touched or not.
* @return true if document object is touched, false if not.
*/

bool DocumentObject::isTouched() const
{
return ExpressionEngine.isTouched() || StatusBits.test(ObjectStatus::Touch);
}

void DocumentObject::Save (Base::Writer &writer) const
{
if (this->getNameInDocument())
Expand Down
17 changes: 13 additions & 4 deletions src/App/DocumentObject.h
Expand Up @@ -51,6 +51,7 @@ enum ObjectStatus {
Remove = 5,
PythonCall = 6,
Destroy = 7,
Enforce = 8,
Expand = 16
};

Expand Down Expand Up @@ -105,13 +106,18 @@ class AppExport DocumentObject: public App::TransactionalObject
/** Set the property touched -> changed, cause recomputation in Update()
*/
//@{
/// set this feature touched (cause recomputation on depndend features)
/// set this document object touched (cause recomputation on dependent features)
void touch(void);
/// test if this feature is touched
/// test if this document object is touched
bool isTouched(void) const;
/// reset this feature touched
/// Enforce this document object to be recomputed
void enforceRecompute();
/// Test if this document object must be recomputed
bool mustRecompute(void) const;
/// reset this document object touched
void purgeTouched(void) {
StatusBits.reset(ObjectStatus::Touch);
StatusBits.reset(ObjectStatus::Enforce);
setPropertyStatus(0,false);
}
/// set this feature to error
Expand Down Expand Up @@ -187,7 +193,10 @@ class AppExport DocumentObject: public App::TransactionalObject
* If we must recompute the object - to call the method execute().
* 0: no recompution is needed
* 1: recompution needed
* -1: the document examine all links of this object and if one is touched -> recompute
*
* @remark If an object is marked as 'touched' then this does not
* necessarily mean that it will be recomputed. It only means that all
* objects that link it (i.e. its InList) will be recomputed.
*/
virtual short mustExecute(void) const;

Expand Down
5 changes: 5 additions & 0 deletions src/App/DocumentObjectPy.xml
Expand Up @@ -45,6 +45,11 @@
<UserDocu>Mark the object as unchanged</UserDocu>
</Documentation>
</Methode>
<Methode Name="enforceRecompute">
<Documentation>
<UserDocu>Mark the object for recompute</UserDocu>
</Documentation>
</Methode>
<Methode Name="setExpression">
<Documentation>
<UserDocu>Register an expression for a property</UserDocu>
Expand Down
8 changes: 8 additions & 0 deletions src/App/DocumentObjectPyImp.cpp
Expand Up @@ -146,6 +146,14 @@ PyObject* DocumentObjectPy::purgeTouched(PyObject * args)
Py_Return;
}

PyObject* DocumentObjectPy::enforceRecompute(PyObject * args)
{
if (!PyArg_ParseTuple(args, "")) // convert args: Python->C
return NULL; // NULL triggers exception
getDocumentObjectPtr()->enforceRecompute();
Py_Return;
}

Py::List DocumentObjectPy::getState(void) const
{
DocumentObject* object = this->getDocumentObjectPtr();
Expand Down
8 changes: 8 additions & 0 deletions src/App/FeatureTest.cpp
Expand Up @@ -121,6 +121,14 @@ FeatureTest::~FeatureTest()

}

short FeatureTest::mustExecute(void) const
{
if (isTouched())
return 1;

return DocumentObject::mustExecute();
}

DocumentObjectExecReturn *FeatureTest::execute(void)
{

Expand Down
1 change: 1 addition & 0 deletions src/App/FeatureTest.h
Expand Up @@ -104,6 +104,7 @@ class FeatureTest : public DocumentObject

/** @name methods override Feature */
//@{
virtual short mustExecute(void) const;
/// recalculate the Feature
virtual DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
Expand Down
10 changes: 5 additions & 5 deletions src/Gui/Tree.cpp
Expand Up @@ -348,7 +348,7 @@ void TreeWidget::onMarkRecompute()
App::Document* doc = docitem->document()->getDocument();
std::vector<App::DocumentObject*> obj = doc->getObjects();
for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it)
(*it)->touch();
(*it)->enforceRecompute();
}
// mark all selected objects
else {
Expand All @@ -357,7 +357,7 @@ void TreeWidget::onMarkRecompute()
if ((*it)->type() == ObjectType) {
DocumentObjectItem* objitem = static_cast<DocumentObjectItem*>(*it);
App::DocumentObject* obj = objitem->object()->getObject();
obj->touch();
obj->enforceRecompute();
}
}
}
Expand Down Expand Up @@ -1574,9 +1574,9 @@ void DocumentObjectItem::testStatus()

// if status has changed then continue
int currentStatus =
((pObject->isError() ? 1 : 0) << 2) |
((pObject->mustExecute() == 1 ? 1 : 0) << 1) |
(viewObject->isShow() ? 1 : 0);
((pObject->isError() ? 1 : 0) << 2) |
((pObject->mustRecompute() == 1 ? 1 : 0) << 1) |
(viewObject->isShow() ? 1 : 0);
if (previousStatus == currentStatus)
return;
previousStatus = currentStatus;
Expand Down
11 changes: 11 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.cpp
Expand Up @@ -142,6 +142,17 @@ SketchObject::~SketchObject()
delete analyser;
}

short SketchObject::mustExecute() const
{
if (Geometry.isTouched())
return 1;
if (Constraints.isTouched())
return 1;
if (ExternalGeometry.isTouched())
return 1;
return Part2DObject::mustExecute();
}

App::DocumentObjectExecReturn *SketchObject::execute(void)
{
try {
Expand Down
1 change: 1 addition & 0 deletions src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -66,6 +66,7 @@ class SketcherExport SketchObject : public Part::Part2DObject
App ::PropertyLinkSubList ExternalGeometry;
/** @name methods override Feature */
//@{
short mustExecute() const;
/// recalculate the Feature (if no recompute is needed see also solve() and solverNeedsUpdate boolean)
App::DocumentObjectExecReturn *execute(void);

Expand Down

0 comments on commit 93f06f8

Please sign in to comment.