From 3d35e6956fa6cbf7da6d04a6bffacc09e8484d38 Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 29 Nov 2017 10:26:33 +0300 Subject: [PATCH] Speed up undo-redo and document loading: do not recompute persistence-based features . --- src/Model/Model_Document.cpp | 12 ++++++++++++ src/Model/Model_Document.h | 5 ++++- src/Model/Model_Objects.cpp | 10 +++++----- src/Model/Model_Update.cpp | 33 +++++++++++++++++++++++++-------- src/Model/Model_Update.h | 8 +++++--- 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index bb82a340e..e11f26faa 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1817,3 +1817,15 @@ void Model_Document::eraseAllFeatures() if (myObjs) myObjs->eraseAllFeatures(); } + +void Model_Document::setExecuteFeatures(const bool theFlag) +{ + myExecuteFeatures = theFlag; + const std::set aSubs = subDocuments(); + std::set::iterator aSubIter = aSubs.begin(); + for (; aSubIter != aSubs.end(); aSubIter++) { + if (!subDoc(*aSubIter)->myObjs) + continue; + subDoc(*aSubIter)->setExecuteFeatures(theFlag); + } +} diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 4b33be6af..b6358eb4f 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -201,7 +201,10 @@ class Model_Document : public ModelAPI_Document ///! Returns true if parametric updater need to execute feature on recomputartion ///! On abort, undo or redo it is not necessary: results in document are updated automatically - bool& executeFeatures() {return myExecuteFeatures;} + bool executeFeatures() {return myExecuteFeatures;} + + ///! On abort, undo or redo it is not necessary: results in document are updated automatically + void setExecuteFeatures(const bool theFlag); //! Registers the name of the shape for the topological naming needs void addNamingName(const TDF_Label theLabel, std::string theName); diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 85460450c..17c623357 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -69,7 +69,7 @@ void Model_Objects::setOwner(DocumentPtr theDoc) myDoc = theDoc; // update all fields and recreate features and result objects if needed TDF_LabelList aNoUpdated; - synchronizeFeatures(aNoUpdated, true, true, true, true); + synchronizeFeatures(aNoUpdated, true, false, true, true); myHistory.clear(); } @@ -783,8 +783,8 @@ void Model_Objects::synchronizeFeatures( myHistory.clear(); } - if (theExecuteFeatures) - anOwner->executeFeatures() = false; + if (!theExecuteFeatures) + anOwner->setExecuteFeatures(false); aLoop->activateFlushes(isActive); if (theFlush) { @@ -797,8 +797,8 @@ void Model_Objects::synchronizeFeatures( aLoop->flush(aRedispEvent); aLoop->flush(aToHideEvent); } - if (theExecuteFeatures) - anOwner->executeFeatures() = true; + if (!theExecuteFeatures) + anOwner->setExecuteFeatures(true); } /// synchronises back references for the given object basing on the collected data diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 4274d9c5e..8e2ac8137 100755 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -90,6 +90,7 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { bool isNotExecuted = theFeature->isPersistentResult() && !std::dynamic_pointer_cast((theFeature)->document())->executeFeatures(); if (isNotExecuted) { + redisplayWithResults(theFeature, ModelAPI_StateNothing, false); // redisplay even not executed if (!theReason.get()) // no reason => no construction reason return false; if (myNotPersistentRefs.find(theFeature) == myNotPersistentRefs.end()) { @@ -104,7 +105,10 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) { // update arguments for "apply button" state change if ((!theFeature->isPreviewNeeded() && !myIsFinish) || myIsPreviewBlocked) { - myProcessOnFinish.insert(theFeature); + if (theReason.get()) + myProcessOnFinish[theFeature].insert(theReason); + else if (myProcessOnFinish.find(theFeature) == myProcessOnFinish.end()) + myProcessOnFinish[theFeature] = std::set >(); #ifdef DEB_UPDATE std::cout<<"*** Add process on finish "<name()<& theMessag if (theMessage->eventID() == kOpFinishEvent) { myIsFinish = true; // add features that wait for finish as modified - std::set >::iterator aFeature = myProcessOnFinish.begin(); - for(; aFeature != myProcessOnFinish.end(); aFeature++) - if ((*aFeature)->data()->isValid()) // there may be already removed wait for features - addModified(*aFeature, FeaturePtr()); + std::map, std::set > >:: + iterator aFeature = myProcessOnFinish.begin(); + for(; aFeature != myProcessOnFinish.end(); aFeature++) { + if (aFeature->first->data()->isValid()) {// there may be already removed while wait + if (aFeature->second.empty()) { + addModified(aFeature->first, FeaturePtr()); + continue; + } + std::set >::iterator aReasons; + for(aReasons = aFeature->second.begin(); aReasons != aFeature->second.end(); aReasons++) { + addModified(aFeature->first, *aReasons); + } + } + } myIsFinish = false; } // processed features must be only on finish, so clear anyway (to avoid reimport on load) @@ -628,7 +642,8 @@ bool Model_Update::processFeature(FeaturePtr theFeature) return true; } -void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_ExecState theState) +void Model_Update::redisplayWithResults( + FeaturePtr theFeature, const ModelAPI_ExecState theState, bool theUpdateState) { // make updated and redisplay all results static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); @@ -641,7 +656,8 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex if (!aRes->isDisabled()) { // update state only for enabled results // (Placement Result Part may make the original Part Result as invalid) - aRes->data()->execState(theState); + if (theUpdateState) + aRes->data()->execState(theState); } if (theFeature->data()->updateID() > aRes->data()->updateID()) { aRes->data()->setUpdateID(theFeature->data()->updateID()); @@ -650,7 +666,8 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex } // to redisplay "presentable" feature (for ex. distance constraint) ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP); - theFeature->data()->execState(theState); + if (theUpdateState) + theFeature->data()->execState(theState); } /// Updates the state by the referenced object: if something bad with it, set state for this one diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h index cef7c0b49..9a6ecc711 100644 --- a/src/Model/Model_Update.h +++ b/src/Model/Model_Update.h @@ -56,8 +56,10 @@ class Model_Update : public Events_Listener bool myIsFinish; /// try if processing is currently performed bool myIsProcessed; - /// set that contains features that must be executed only on finish of the operation - std::set > myProcessOnFinish; + /// map that contains features that must be executed only on finish of the operation + /// the value in map is the set of reasons + std::map, std::set > > + myProcessOnFinish; /// to avoid infinitive cycling: feature -> count of the processing periods during this update std::map, int > myProcessed; /// if preview in hte property panel is blocked and @@ -89,7 +91,7 @@ protected: /// Sends the redisplay events for feature and results, updates the updated status void redisplayWithResults(std::shared_ptr theFeature, - const ModelAPI_ExecState theState); + const ModelAPI_ExecState theState, bool theUpdateState = true); /// On operation start/end/abort the "Just" fileds must be cleared and processed in the right way //! \param theFlushRedisplay a boolean value if the redisplay signal should be flushed -- 2.39.2