using namespace std;
Model_Update MY_UPDATER_INSTANCE; /// the only one instance initialized on load of the library
+//#define DEB_UPDATE
Model_Update::Model_Update()
{
// created objects are always must be up to date (python box feature)
// and updated not in internal uptation chain
myJustUpdated.insert(*anObjIter);
+ #ifdef DEB_UPDATE
+ if ((*anObjIter)->data() && (*anObjIter)->data()->isValid()) {
+ std::cout<<"Add updated "<<(*anObjIter)->groupName()<<" "
+ <<(*anObjIter)->data()->name()<<std::endl;
+ }
+ #endif
}
- // this event is for solver update, not here, do not react immideately
+ // this event is for solver update, not here, do not react immediately
if (!isOnlyResults && !(theMessage->eventID() == kMovedEvent))
processOperation(false);
} else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent ||
theMessage->eventID() == kOpStartEvent) {
- myIsParamUpdated = false;
if (!(theMessage->eventID() == kOpStartEvent)) {
myIsFinish = true;
}
// in the end of transaction everything is updated, so clear the old objects (the only one
// place where results are cleared)
+ myIsParamUpdated = false;
myJustUpdated.clear();
myWaitForFinish.clear();
}
}
// perform update of everything if needed
if (!myIsExecuted) {
+ #ifdef DEB_UPDATE
+ std::cout<<"****** Start processing"<<std::endl;
+ #endif
myIsExecuted = true;
bool isAutomaticChanged = false;
DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
Model_Objects* anObjs = std::dynamic_pointer_cast<Model_Document>(aRootDoc)->objects();
if (!anObjs) return;
+ // two cycles: parameters are first to process
FeaturePtr aFeatureIter = anObjs->firstFeature();
std::set<FeaturePtr> aProcessedFeatures; // to avoid processing twice
for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
- updateFeature(aFeatureIter, aProcessedFeatures);
+ if (aFeatureIter->getKind() == "Parameter")
+ updateFeature(aFeatureIter, aProcessedFeatures);
+ }
+ aFeatureIter = anObjs->firstFeature();
+ for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
+ if (aFeatureIter->getKind() != "Parameter")
+ updateFeature(aFeatureIter, aProcessedFeatures);
}
if (isAutomaticChanged) myIsAutomatic = false;
static Events_Loop* aLoop = Events_Loop::loop();
static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
aLoop->flush(EVENT_DISP);
+ #ifdef DEB_UPDATE
+ std::cout<<"****** End processing"<<std::endl;
+ #endif
}
}
if (theFeature->isDisabled())
return;
+ #ifdef DEB_UPDATE
+ std::cout<<"Update Feature "<<theFeature->name()<<std::endl;
+ #endif
CompositeFeaturePtr aCompos = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
// If automatice update is not needed and feature attributes were not updated right now,
// do not execute it and do not update arguments.
// composite feature must be executed after sub-features execution
if (aCompos) {
+ // two cycles: parameters must be processed first
+ for(int a = 0; a < aCompos->numberOfSubs(); a++) {
+ FeaturePtr aSub = aCompos->subFeature(a);
+ if (aSub->getKind() == "Parameter")
+ updateFeature(aSub, theProcessed);
+ }
// number of subs can be changed in execution: like fillet
for(int a = 0; a < aCompos->numberOfSubs(); a++) {
FeaturePtr aSub = aCompos->subFeature(a);
- updateFeature(aSub, theProcessed);
+ if (aSub->getKind() != "Parameter")
+ updateFeature(aSub, theProcessed);
}
}
// this checking must be after the composite feature sub-elements processing:
if (myIsAutomatic && theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)
aJustUpdated = true;
+ // On abort, undo or redo execute is not needed: results in document are updated automatically
+ // But redisplay is needed: results are updated, must be also updated in the viewer.
+ if (aJustUpdated &&
+ !std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures()) {
+ if (!theFeature->isPersistentResult()) { // not persistent must be re-executed on abort, etc.
+ ModelAPI_ExecState aState = theFeature->data()->execState();
+ if (aFactory->validate(theFeature)) {
+ executeFeature(theFeature);
+ } else {
+ theFeature->eraseResults();
+ redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
+ }
+ } else {
+ redisplayWithResults(theFeature, ModelAPI_StateNothing);
+ if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { // it is done (in the tree)
+ theFeature->data()->execState(ModelAPI_StateDone);
+ }
+ }
+ return;
+ }
+
// execute feature if it must be updated
if (theFeature->isPreviewNeeded() || myIsFinish) {
- if (aJustUpdated &&
- std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures()) {
- ModelAPI_ExecState aState = theFeature->data()->execState();
- if (aFactory->validate(theFeature)) {
- executeFeature(theFeature);
- } else {
- theFeature->eraseResults();
- redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
- }
+ if (aJustUpdated) {
+ ModelAPI_ExecState aState = theFeature->data()->execState();
+ if (aFactory->validate(theFeature)) {
+ #ifdef DEB_UPDATE
+ std::cout<<"Execute Feature "<<theFeature->name()<<std::endl;
+ #endif
+ executeFeature(theFeature);
+ } else {
+ theFeature->eraseResults();
+ redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
+ }
}
} else { // preview is not needed => make state Done
if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) {
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
for (; aRIter != aResults.cend(); aRIter++) {
std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
- aRes->data()->execState(theState);
+ 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 (theFeature->data()->updateID() > aRes->data()->updateID()) {
aRes->data()->setUpdateID(theFeature->data()->updateID());
}
void Model_Update::updateArguments(FeaturePtr theFeature) {
// perform this method also for disabled features: to make "not done" state for
- // featuers referenced to the active and modified features
+ // features referenced to the active and modified features
static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
ObjectPtr aContext = aSel->context();
// update argument onlt if the referenced object is changed
if (aContext.get() && !aContext->isDisabled() &&
- aContext->data()->updateID() > theFeature->data()->updateID()) {
+ (myJustUpdated.find(aContext) != myJustUpdated.end() ||
+ aContext->data()->updateID() > theFeature->data()->updateID())) {
if (aState == ModelAPI_StateDone)
aState = ModelAPI_StateMustBeUpdated;
if (!aSel->update()) { // this must be done on execution since it may be long operation
ObjectPtr aContext = aSelAttr->context();
// update argument onlt if the referenced object is changed
if (aContext.get() && !aContext->isDisabled() &&
- aContext->data()->updateID() > theFeature->data()->updateID()) {
+ (myJustUpdated.find(aContext) != myJustUpdated.end() ||
+ aContext->data()->updateID() > theFeature->data()->updateID())) {
if (aState == ModelAPI_StateDone)
aState = ModelAPI_StateMustBeUpdated;
if (!aSelAttr->update()) {
// number of subs can be changed in execution: like fillet
for(int a = 0; a < aCompos->numberOfSubs(); a++) {
FeaturePtr aSub = aCompos->subFeature(a);
- if (myJustUpdated.find(aSub) != myJustUpdated.end() ||
- (aSub.get() && aSub->data()->updateID() > theFeature->data()->updateID())) {
- if (aState == ModelAPI_StateDone)
+ if (aSub.get() && aState == ModelAPI_StateDone) {
+ if (myJustUpdated.find(aSub) != myJustUpdated.end() ||
+ (aSub->data()->updateID() > theFeature->data()->updateID())) {
+ aState = ModelAPI_StateMustBeUpdated;
+ }
+ // also check that all results of subs were updated: composite also depends on the results
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter = aResults.begin();
+ for(; aResIter != aResults.end(); aResIter++) {
+ if (aResIter->get() && (*aResIter)->data()->isValid() && !(*aResIter)->isDisabled() &&
+ (myJustUpdated.find(*aResIter) != myJustUpdated.end() ||
+ ((*aResIter)->data()->updateID() > theFeature->data()->updateID()))) {
aState = ModelAPI_StateMustBeUpdated;
+ }
+ }
}
}
}