X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_Displayer.cpp;h=bc1bb7526ef53b8c8cd54e6cef675f5ec8adc8a3;hb=12620e8f983d03617d0bc6292e880dd55119a9ff;hp=4fb6a729bdba4c794c1beda317f8bda876aeb36f;hpb=868158fe6d39b25e60ac528295b1c908821e4af5;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_Displayer.cpp b/src/XGUI/XGUI_Displayer.cpp index 4fb6a729b..bc1bb7526 100644 --- a/src/XGUI/XGUI_Displayer.cpp +++ b/src/XGUI/XGUI_Displayer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -68,6 +73,11 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10; ///< defines the local context mouse //#define DEBUG_COMPOSILID_DISPLAY // Workaround for bug #25637 + +//#define DEBUG_OCCT_SHAPE_SELECTION + +#define WORKAROUND_UNTIL_27523_IS_FIXED + void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList) { // Get from null point @@ -100,11 +110,10 @@ QString qIntListInfo(const QIntList& theValues, const QString& theSeparator = QS } XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop) - : myWorkshop(theWorkshop), myEnableUpdateViewer(true), myNeedUpdate(false), - myIsTrihedronActive(false) + : myWorkshop(theWorkshop), myNeedUpdate(false), + myIsTrihedronActive(true), myViewerBlockedRecursiveCount(0) { - enableUpdateViewer(true); - myCustomPrs = std::shared_ptr(new XGUI_CustomPrs()); + myCustomPrs = std::shared_ptr(new XGUI_CustomPrs(theWorkshop)); } XGUI_Displayer::~XGUI_Displayer() @@ -159,7 +168,10 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) std::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); if (aShapePtr.get() != NULL) { anAIS = AISObjectPtr(new GeomAPI_AISObject()); - anAIS->setImpl(new Handle(AIS_InteractiveObject)(new ModuleBase_ResultPrs(aResult))); + Handle(AIS_InteractiveObject) anAISPrs = myWorkshop->module()->createPresentation(aResult); + if (anAISPrs.IsNull()) + anAISPrs = new ModuleBase_ResultPrs(aResult); + anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs)); //anAIS->createShape(aShapePtr); isShading = true; } @@ -174,7 +186,7 @@ bool XGUI_Displayer::display(ObjectPtr theObject, bool theUpdateViewer) return aDisplayed; } -bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) +bool canBeShaded(Handle(AIS_InteractiveObject) theAIS, ModuleBase_IModule* theModule) { Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(theAIS); if (!aShapePrs.IsNull()) { @@ -186,10 +198,7 @@ bool canBeShaded(Handle(AIS_InteractiveObject) theAIS) return false; else { // Check that the presentation is not a sketch - Handle(ModuleBase_ResultPrs) aPrs = Handle(ModuleBase_ResultPrs)::DownCast(theAIS); - if (!aPrs.IsNull()) - return !aPrs->isSketchMode(); - return true; + return theModule->canBeShaded(theAIS); } } return false; @@ -250,7 +259,7 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) Handle(AIS_InteractiveObject) anAIS = anObject->impl(); if (!anAIS.IsNull()) { emit beforeObjectErase(theObject, anObject); - aContext->Remove(anAIS, theUpdateViewer); + aContext->Remove(anAIS, false/*update viewer*/); aErased = true; } } @@ -262,6 +271,10 @@ bool XGUI_Displayer::erase(ObjectPtr theObject, const bool theUpdateViewer) qDebug(QString("erase object: %1").arg(aPtrStr.str().c_str()).toStdString().c_str()); qDebug(getResult2AISObjectMapInfo().c_str()); #endif + + if (theUpdateViewer) + updateViewer(); + return aErased; } @@ -316,7 +329,26 @@ bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer) arg(!isEqualShapes || isCustomized).arg(isEqualShapes).arg(isCustomized).toStdString().c_str()); #endif if (!isEqualShapes || isCustomized) { + /// if shapes are equal and presentation are customized, selection should be restored + bool aNeedToRestoreSelection = isEqualShapes && isCustomized; + if (aNeedToRestoreSelection) + myWorkshop->module()->storeSelection(); + +#ifdef WORKAROUND_UNTIL_27523_IS_FIXED + if (!myActiveSelectionModes.contains(0)) + aContext->Activate(aAISIO, 0); +#endif + aContext->Redisplay(aAISIO, false); + +#ifdef WORKAROUND_UNTIL_27523_IS_FIXED + if (!myActiveSelectionModes.contains(0)) + aContext->Deactivate(aAISIO, 0); +#endif + + if (aNeedToRestoreSelection) + myWorkshop->module()->restoreSelection(); + aRedisplayed = true; #ifdef DEBUG_FEATURE_REDISPLAY qDebug(" Redisplay happens"); @@ -404,6 +436,74 @@ int XGUI_Displayer::getSelectionMode(int theShapeType) AIS_Shape::SelectionMode((TopAbs_ShapeEnum)theShapeType); } +bool XGUI_Displayer::isVisible(XGUI_Displayer* theDisplayer, const ObjectPtr& theObject) +{ + bool aVisible = false; + GeomPresentablePtr aPrs = std::dynamic_pointer_cast(theObject); + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aPrs.get() || aResult.get()) { + aVisible = theDisplayer->isVisible(theObject); + // compsolid is not visualized in the viewer, but should have presentation when all sub solids are + // visible. It is useful for highlight presentation where compsolid shape is selectable + if (!aVisible && aResult.get() && aResult->groupName() == ModelAPI_ResultCompSolid::group()) { + ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast(aResult); + if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids + bool anAllSubsVisible = aCompsolidResult->numberOfSubs() > 0; + for(int i = 0; i < aCompsolidResult->numberOfSubs() && anAllSubsVisible; i++) { + anAllSubsVisible = theDisplayer->isVisible(aCompsolidResult->subResult(i)); + } + aVisible = anAllSubsVisible; + } + } + } + // it is possible that feature is presentable and has results, so we should check visibility + // of results if presentation is not shown (e.g. Sketch Circle/Arc features) + if (!aVisible) { + // check if all results of the feature are visible + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + aVisible = !aResults.empty(); + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) { + aVisible = aVisible && theDisplayer->isVisible(*aIt); + } + } + return aVisible; +} + +#ifdef DEBUG_ACTIVATE_OBJECTS +QString getModeInfo(const int theMode) +{ + QString anInfo = "Undefined"; + switch(theMode) { + case 0: anInfo = "SHAPE(0)"; break; + case 1: anInfo = "VERTEX(1)"; break; + case 2: anInfo = "EDGE(2)"; break; + case 3: anInfo = "WIRE(3)"; break; + case 4: anInfo = "FACE(4)"; break; + case 5: anInfo = "SHELL(5)"; break; + case 6: anInfo = "SOLID(6)"; break; + case 7: anInfo = "COMPSOLID(7)"; break; + case 8: anInfo = "COMPOUND(8)"; break; + case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools + case 101: anInfo = "Sel_Constraint(101)"; break; + case 102: anInfo = "Sel_Dimension_All(102)"; break; + case 103: anInfo = "Sel_Dimension_Line(103)"; break; + case 104: anInfo = "Sel_Dimension_Text(104)"; break; + default: break; + } + return anInfo; +} + +QString getModesInfo(const QIntList& theModes) +{ + QStringList aModesInfo; + for (int i = 0, aSize = theModes.size(); i < aSize; i++) + aModesInfo.append(getModeInfo(theModes[i])); + return QString("[%1] = %2").arg(aModesInfo.size()).arg(aModesInfo.join(", ")); +} +#endif + void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrList& theObjList, const bool theUpdateViewer) { @@ -421,9 +521,10 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL } QString anInfoStr = anInfo.join(", "); - qDebug(QString("activateObjects: aModes[%1] = %2, myActiveSelectionModes[%3] = %4, objects = %5"). - arg(aModes.size()).arg(qIntListInfo(aModes)). - arg(myActiveSelectionModes.size()).arg(qIntListInfo(myActiveSelectionModes)). + qDebug(QString("activateObjects: new modes%1, active modes%2, objects[%3] = %4"). + arg(getModesInfo(aModes)). + arg(getModesInfo(myActiveSelectionModes)). + arg(theObjList.size()). arg(anInfoStr). toStdString().c_str()); #endif @@ -457,7 +558,7 @@ void XGUI_Displayer::activateObjects(const QIntList& theModes, const QObjectPtrL Handle(AIS_InteractiveObject) aTrihedron; if (isTrihedronActive()) { aTrihedron = getTrihedron(); - if (!aTrihedron.IsNull()) + if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) aPrsList.Append(aTrihedron); } if (aPrsList.Extent() == 0) @@ -492,20 +593,27 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const aContext->ActivatedModes(anAIS, aModes); return aModes.Extent() > 0; } -void XGUI_Displayer::setSelected(const QList& theValues, bool theUpdateViewer) +void XGUI_Displayer::setSelected(const QList& theValues, bool theUpdateViewer) { Handle(AIS_InteractiveContext) aContext = AISContext(); if (aContext.IsNull()) return; if (aContext->HasOpenedContext()) { - aContext->UnhilightSelected(); - aContext->ClearSelected(); - foreach (ModuleBase_ViewerPrs aPrs, theValues) { - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull()) { + aContext->UnhilightSelected(false); + aContext->ClearSelected(false); + NCollection_Map aShapesToBeSelected; + + foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) { + const GeomShapePtr& aGeomShape = aPrs->shape(); + if (aGeomShape.get() && !aGeomShape->isNull()) { + const TopoDS_Shape& aShape = aGeomShape->impl(); +#ifdef DEBUG_OCCT_SHAPE_SELECTION aContext->AddOrRemoveSelected(aShape, false); +#else + aShapesToBeSelected.Add(aShape); +#endif } else { - ObjectPtr anObject = aPrs.object(); + ObjectPtr anObject = aPrs->object(); ResultPtr aResult = std::dynamic_pointer_cast(anObject); if (aResult.get() && isVisible(aResult)) { AISObjectPtr anObj = myResult2AISObjectMap[aResult]; @@ -521,11 +629,13 @@ void XGUI_Displayer::setSelected(const QList& theValues, } } } + if (!aShapesToBeSelected.IsEmpty()) + XGUI_Displayer::AddOrRemoveSelectedShapes(aContext, aShapesToBeSelected); } else { - aContext->UnhilightCurrents(); - aContext->ClearCurrents(); - foreach (ModuleBase_ViewerPrs aPrs, theValues) { - ObjectPtr anObject = aPrs.object(); + aContext->UnhilightCurrents(false); + aContext->ClearCurrents(false); + foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) { + ObjectPtr anObject = aPrs->object(); ResultPtr aResult = std::dynamic_pointer_cast(anObject); if (aResult.get() && isVisible(aResult)) { AISObjectPtr anObj = myResult2AISObjectMap[aResult]; @@ -559,7 +669,7 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer) Handle(AIS_InteractiveObject) anIO = aAISObj->impl(); if (!anIO.IsNull()) { emit beforeObjectErase(aObj, aAISObj); - aContext->Remove(anIO, false); + aContext->Remove(anIO, false/*update viewer*/); aErased = true; } } @@ -574,42 +684,47 @@ bool XGUI_Displayer::eraseAll(const bool theUpdateViewer) return aErased; } -#define DEACTVATE_COMP(TheComp) \ - if (!TheComp.IsNull()) \ - aContext->Deactivate(TheComp); +void deactivateObject(Handle(AIS_InteractiveContext) theContext, + Handle(AIS_InteractiveObject) theObject, + const bool theClear = true) +{ + if (!theObject.IsNull()) { + theContext->Deactivate(theObject); + //if (theClear) { + //theObject->ClearSelected(); + // theContext->LocalContext()->ClearOutdatedSelection(theObject, true); + //} + } +} -void XGUI_Displayer::deactivateTrihedron() const +void XGUI_Displayer::deactivateTrihedron(const bool theUpdateViewer) const { Handle(AIS_InteractiveObject) aTrihedron = getTrihedron(); - if (!aTrihedron.IsNull()) { + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (!aTrihedron.IsNull() && aContext->IsDisplayed(aTrihedron)) { Handle(AIS_Trihedron) aTrie = Handle(AIS_Trihedron)::DownCast(aTrihedron); - Handle(AIS_InteractiveContext) aContext = AISContext(); - aContext->Deactivate(aTrie); - DEACTVATE_COMP(aTrie->XAxis()); - DEACTVATE_COMP(aTrie->YAxis()); - DEACTVATE_COMP(aTrie->Axis()); - DEACTVATE_COMP(aTrie->Position()); - DEACTVATE_COMP(aTrie->XYPlane()); - DEACTVATE_COMP(aTrie->XZPlane()); - DEACTVATE_COMP(aTrie->YZPlane()); + deactivateObject(aContext, aTrie); + + /// #1136 hidden axis are selected in sketch + /// workaround for Cascade: there is a crash in AIS_LocalContext::ClearOutdatedSelection + /// for Position AIS object in SelectionModes. + deactivateObject(aContext, aTrie->XAxis()); + deactivateObject(aContext, aTrie->YAxis()); + deactivateObject(aContext, aTrie->Axis()); + deactivateObject(aContext, aTrie->Position()); + + deactivateObject(aContext, aTrie->XYPlane()); + deactivateObject(aContext, aTrie->XZPlane()); + deactivateObject(aContext, aTrie->YZPlane()); + + if (theUpdateViewer) + updateViewer(); } } Handle(AIS_InteractiveObject) XGUI_Displayer::getTrihedron() const { - Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull()) { - AIS_ListOfInteractive aList; - aContext->DisplayedObjects(aList, true); - AIS_ListIteratorOfListOfInteractive aIt; - for (aIt.Initialize(aList); aIt.More(); aIt.Next()) { - Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aIt.Value()); - if (!aTrihedron.IsNull()) { - return aTrihedron; - } - } - } - return Handle(AIS_InteractiveObject)(); + return myWorkshop->viewer()->trihedron(); } void XGUI_Displayer::openLocalContext() @@ -736,20 +851,28 @@ ObjectPtr XGUI_Displayer::getObject(const Handle(AIS_InteractiveObject)& theIO) bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled) { - bool aWasEnabled = myEnableUpdateViewer; + bool aWasEnabled = isUpdateEnabled(); + if (isEnabled) + myViewerBlockedRecursiveCount--; + else + myViewerBlockedRecursiveCount++; - myEnableUpdateViewer = isEnabled; - if (myNeedUpdate && myEnableUpdateViewer) { + if (myNeedUpdate && isUpdateEnabled()) { updateViewer(); myNeedUpdate = false; } return aWasEnabled; } +bool XGUI_Displayer::isUpdateEnabled() const +{ + return myViewerBlockedRecursiveCount == 0; +} + void XGUI_Displayer::updateViewer() const { Handle(AIS_InteractiveContext) aContext = AISContext(); - if (!aContext.IsNull() && myEnableUpdateViewer) { + if (!aContext.IsNull() && isUpdateEnabled()) { myWorkshop->viewer()->Zfitall(); aContext->UpdateCurrentViewer(); } else { @@ -762,13 +885,15 @@ void XGUI_Displayer::activateAIS(const Handle(AIS_InteractiveObject)& theIO, { Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext(); if (!aContext.IsNull()) { - aContext->Activate(theIO, theMode, theUpdateViewer); + aContext->Activate(theIO, theMode, false); #ifdef DEBUG_ACTIVATE_AIS ObjectPtr anObject = getObject(theIO); anInfo.append(ModuleBase_Tools::objectInfo((*anIt))); qDebug(QString("activateAIS: theMode = %1, object = %2").arg(theMode).arg(anInfo).toStdString().c_str()); #endif + if (theUpdateViewer) + updateViewer(); } } @@ -795,7 +920,7 @@ Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const if (!aContext.IsNull() && !aContext->HasOpenedContext()) { aContext->OpenLocalContext(); if (!isTrihedronActive()) - deactivateTrihedron(); + deactivateTrihedron(true); aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0); aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0); } @@ -819,7 +944,7 @@ bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele Handle(AIS_InteractiveContext) aContext = AISContext(); Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!aContext.IsNull() && !anAISIO.IsNull()) { - aContext->Display(anAISIO, 0/*wireframe*/, 0, theUpdateViewer, true, AIS_DS_Displayed); + aContext->Display(anAISIO, 0/*wireframe*/, 0, false/*update viewer*/, true, AIS_DS_Displayed); aDisplayed = true; aContext->Deactivate(anAISIO); aContext->Load(anAISIO); @@ -834,6 +959,8 @@ bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSele } } } + if (theUpdateViewer) + updateViewer(); } return aDisplayed; } @@ -845,10 +972,12 @@ bool XGUI_Displayer::eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer) if (!aContext.IsNull()) { Handle(AIS_InteractiveObject) anAISIO = theAIS->impl(); if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) { - aContext->Remove(anAISIO, theUpdateViewer); + aContext->Remove(anAISIO, false/*update viewer*/); aErased = true; } } + if (aErased && theUpdateViewer) + updateViewer(); return aErased; } @@ -997,7 +1126,7 @@ bool XGUI_Displayer::canBeShaded(ObjectPtr theObject) const return false; Handle(AIS_InteractiveObject) anAIS = aAISObj->impl(); - return ::canBeShaded(anAIS); + return ::canBeShaded(anAIS, myWorkshop->module()); } bool XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO, @@ -1141,6 +1270,75 @@ void XGUI_Displayer::activateTrihedron(bool theIsActive) { myIsTrihedronActive = theIsActive; if (!myIsTrihedronActive) { - deactivateTrihedron(); + deactivateTrihedron(true); + } +} + +void XGUI_Displayer::displayTrihedron(bool theToDisplay) const +{ + Handle(AIS_InteractiveContext) aContext = AISContext(); + if (aContext.IsNull()) + return; + + Handle(AIS_Trihedron) aTrihedron = myWorkshop->viewer()->trihedron(); + + if (theToDisplay) { + if (!aContext->IsDisplayed(aTrihedron)) + aContext->Display(aTrihedron, + 0 /*wireframe*/, + -1 /* selection mode */, + Standard_True /* update viewer*/, + Standard_False /* allow decomposition */, + AIS_DS_Displayed /* xdisplay status */); + + if (!isTrihedronActive()) + deactivateTrihedron(false); + else + activate(aTrihedron, myActiveSelectionModes, false); + } else { + deactivateTrihedron(false); + //aContext->LocalContext()->ClearOutdatedSelection(aTrihedron, true); + // the selection from the previous activation modes should be cleared manually (#26172) + + aContext->Erase(aTrihedron); + } + + updateViewer(); +} + +QIntList XGUI_Displayer::activeSelectionModes() const +{ + QIntList aModes; + foreach (int aMode, myActiveSelectionModes) { + // aMode < 9 is a Shape Enum values + aModes << ((aMode < 9)? AIS_Shape::SelectionType(aMode) : aMode); + } + return aModes; +} + +void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) theContext, + const NCollection_Map& theShapesToBeSelected) +{ + Handle(AIS_LocalContext) aLContext = theContext->LocalContext(); + TCollection_AsciiString aSelectionName = aLContext->SelectionName(); + aLContext->UnhilightPicked(Standard_False); + + NCollection_Map aShapesSelected; + + NCollection_List anActiveOwners; + aLContext->MainSelector()->ActiveOwners(anActiveOwners); + NCollection_List::Iterator anOwnersIt (anActiveOwners); + Handle(SelectMgr_EntityOwner) anOwner; + for (; anOwnersIt.More(); anOwnersIt.Next()) { + anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value()); + Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner); + if (!BROwnr.IsNull() && BROwnr->HasShape() && theShapesToBeSelected.Contains(BROwnr->Shape())) { + if (aShapesSelected.Contains(BROwnr->Shape())) + continue; + AIS_Selection::Selection(aSelectionName.ToCString())->Select(anOwner); + anOwner->SetSelected (Standard_True); + aShapesSelected.Add(BROwnr->Shape()); + } } + aLContext->HilightPicked(Standard_False); }