fixes 0003410: 0.17 Regression: recompute will make parts lose color and take a longer delay compared to FC0.16
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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())
|
||||
|
||||
@@ -51,6 +51,7 @@ enum ObjectStatus {
|
||||
Remove = 5,
|
||||
PythonCall = 6,
|
||||
Destroy = 7,
|
||||
Enforce = 8,
|
||||
Expand = 16
|
||||
};
|
||||
|
||||
@@ -105,13 +106,18 @@ public:
|
||||
/** 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
|
||||
@@ -187,7 +193,10 @@ public:
|
||||
* 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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -121,6 +121,14 @@ FeatureTest::~FeatureTest()
|
||||
|
||||
}
|
||||
|
||||
short FeatureTest::mustExecute(void) const
|
||||
{
|
||||
if (isTouched())
|
||||
return 1;
|
||||
|
||||
return DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn *FeatureTest::execute(void)
|
||||
{
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
|
||||
/** @name methods override Feature */
|
||||
//@{
|
||||
virtual short mustExecute(void) const;
|
||||
/// recalculate the Feature
|
||||
virtual DocumentObjectExecReturn *execute(void);
|
||||
/// returns the type name of the ViewProvider
|
||||
|
||||
@@ -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 {
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user