//function : RecomputeSelectionOnly
//purpose :
//=======================================================================
-void AIS_InteractiveContext::RecomputeSelectionOnly(const Handle(AIS_InteractiveObject)& anIObj)
+void AIS_InteractiveContext::RecomputeSelectionOnly (const Handle(AIS_InteractiveObject)& theIO)
{
- if(anIObj.IsNull()) return;
- mgrSelector->RecomputeSelection(anIObj);
-
+ if (theIO.IsNull())
+ {
+ return;
+ }
+ mgrSelector->RecomputeSelection (theIO);
- TColStd_ListOfInteger LI;
- TColStd_ListIteratorOfListOfInteger Lit;
- ActivatedModes(anIObj,LI);
- if(!HasOpenedContext()){
- if(!myObjects.IsBound(anIObj)) return;
-
- if (myObjects(anIObj)->GraphicStatus() == AIS_DS_Displayed)
+ if (HasOpenedContext())
+ {
+ for (Standard_Integer aContextIdx = 1; aContextIdx <= myLocalContexts.Extent(); aContextIdx++)
{
- for(Lit.Initialize(LI);Lit.More();Lit.Next())
- {
- mgrSelector->Activate(anIObj,Lit.Value(),myMainSel);
- }
+ myLocalContexts (aContextIdx)->ClearOutdatedSelection (theIO, Standard_False);
}
+ return;
+ }
+
+ if (!myObjects.IsBound (theIO) ||
+ myObjects (theIO)->GraphicStatus() != AIS_DS_Displayed)
+ {
+ return;
+ }
+
+ TColStd_ListOfInteger aModes;
+ ActivatedModes (theIO, aModes);
+ TColStd_ListIteratorOfListOfInteger aModesIter (aModes);
+ for (; aModesIter.More(); aModesIter.Next())
+ {
+ mgrSelector->Activate (theIO, aModesIter.Value(), myMainSel);
}
}
mgrSelector->Update(theIObj);
+ for (Standard_Integer aContextIdx = 1; aContextIdx <= myLocalContexts.Extent(); aContextIdx++)
+ {
+ myLocalContexts (aContextIdx)->ClearOutdatedSelection (theIObj, Standard_False);
+ }
+
if (theUpdateViewer)
{
if (!myObjects.IsBound (theIObj))
---Purpose: Clears local context selection.
-- @param toUpdateViewer [in] if TRUE the viewer will be updated.
- ClearSelected (me : mutable;
- theIO : InteractiveObject from AIS;
- toUpdateViewer : Boolean from Standard = Standard_True);
- ---Purpose: Removes an interactive object from the local context selection.
- -- Method deselects all associated entity owners.
+ ClearOutdatedSelection (me : mutable;
+ theIO : InteractiveObject from AIS;
+ toClearDeactivated : Boolean from Standard);
+ ---Purpose: Clears outdated selection and detection of owners for the
+ -- interactive object. Use this method if selection structures
+ -- of the interactive object have changed. The method unhilights
+ -- and removes outdated entity owners from lists of selected
+ -- and detected owners.
-- @param theIO [in] the interactive object.
- -- @param toUpdateViewer [in] if TRUE the viewer will be updated.
+ -- @param toClearDeactivated [in] pass TRUE to treat deactivated
+ -- entity owners as 'outdated' when clearing the selection.
---Category: GET THE DETECTED
#include <AIS_LocalContext.jxx>
#include <StdSelect_BRepOwner.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
#include <TColStd_MapOfTransient.hxx>
#include <TColStd_MapIteratorOfMapOfTransient.hxx>
#include <Prs3d_Presentation.hxx>
}
//==================================================
-// Function: ClearSelected
+// Function: ClearOutdatedSelection
// Purpose :
//==================================================
-void AIS_LocalContext::ClearSelected (const Handle(AIS_InteractiveObject)& theIO,
- const Standard_Boolean toUpdateViewer)
+void AIS_LocalContext::ClearOutdatedSelection (const Handle(AIS_InteractiveObject)& theIO,
+ const Standard_Boolean toClearDeactivated)
{
+ // 1. Collect selectable entities
+ SelectMgr_IndexedMapOfOwner aValidOwners;
+
+ const TColStd_ListOfInteger& aModes = SelectionModes (theIO);
+
+ TColStd_ListIteratorOfListOfInteger aModeIter (aModes);
+ for (; aModeIter.More(); aModeIter.Next())
+ {
+ int aMode = aModeIter.Value();
+ if (!theIO->HasSelection(aMode))
+ {
+ continue;
+ }
+
+ if (toClearDeactivated && !mySM->IsActivated (theIO, myMainVS, aMode))
+ {
+ continue;
+ }
+
+ Handle(SelectMgr_Selection) aSelection = theIO->Selection(aMode);
+ for (aSelection->Init(); aSelection->More(); aSelection->Next())
+ {
+ Handle(SelectBasics_SensitiveEntity) anEntity = aSelection->Sensitive();
+ if (anEntity.IsNull())
+ {
+ continue;
+ }
+
+ Handle(SelectMgr_EntityOwner) anOwner =
+ Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
+
+ if (anOwner.IsNull())
+ {
+ continue;
+ }
+
+ aValidOwners.Add(anOwner);
+ }
+ }
+
+ // 2. Refresh context's detection and selection and keep only active owners
// Keep last detected object for lastindex initialization.
Handle(SelectMgr_EntityOwner) aLastPicked = myMainVS->OnePicked();
- // Remove the interactive object from detected sequence
- for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
+ // Remove entity owners from detected sequences
+ for (Standard_Integer anIdx = 1; anIdx <= myDetectedSeq.Length(); ++anIdx)
{
- Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
- if (!aDetectedIO.IsNull() && aDetectedIO == theIO)
+ Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (anIdx));
+ if (anOwner.IsNull() || anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
{
- myAISDetectedSeq.Remove (anIdx--);
+ continue;
+ }
+
+ myDetectedSeq.Remove (anIdx--);
+
+ if (anIdx < myCurDetected)
+ {
+ myCurDetected--;
}
}
+ myCurDetected = Max (myCurDetected, 1);
- Standard_Integer aHilightMode = theIO->HasHilightMode() ? theIO->HilightMode() : 0;
+ Standard_Boolean isAISRemainsDetected = Standard_False;
- // Remove entity owners from AIS_Selection
+ // 3. Remove entity owners from AIS_Selection
+ const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
Handle(AIS_Selection) aSelection = AIS_Selection::Selection (mySelName.ToCString());
AIS_NListTransient::Iterator anIter (aSelection->Objects());
AIS_NListTransient aRemoveEntites;
continue;
}
- aRemoveEntites.Append (anOwner);
+ if (aValidOwners.Contains (anOwner))
+ {
+ isAISRemainsDetected = Standard_True;
+ }
- if (IsSelected (anOwner))
+ aRemoveEntites.Append (anOwner);
+ anOwner->SetSelected (Standard_False);
+ for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews())
{
- anOwner->Unhilight (myMainPM, aHilightMode);
+ Unhilight (anOwner, aViewer->ActiveView());
}
}
+
AIS_NListTransient::Iterator anIterRemove (aRemoveEntites);
for (; anIterRemove.More(); anIterRemove.Next())
{
aSelection->Select (anIterRemove.Value());
}
- // Remove entity owners from myMapOfOwner
+ // 4. Remove entity owners from myMapOfOwner
SelectMgr_IndexedMapOfOwner anOwnersToKeep;
- const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
for (Standard_Integer anIdx = 1; anIdx <= myMapOfOwner.Extent(); anIdx++)
{
Handle(SelectMgr_EntityOwner) anOwner = myMapOfOwner (anIdx);
continue;
}
- if (anOwner->Selectable() != theIO)
+ if (anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
{
anOwnersToKeep.Add (anOwner);
}
myMapOfOwner.Assign (anOwnersToKeep);
mylastindex = myMapOfOwner.FindIndex (aLastPicked);
- if (toUpdateViewer)
+ if (!isAISRemainsDetected)
{
- aViewer->Update();
+ // Remove the interactive object from detected sequences
+ for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
+ {
+ Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
+ if (aDetectedIO.IsNull() || aDetectedIO != theIO)
+ {
+ continue;
+ }
+
+ myAISDetectedSeq.Remove (anIdx--);
+
+ if (anIdx < myAISCurDetected)
+ {
+ myAISCurDetected--;
+ }
+ }
+ myAISCurDetected = Max (myAISCurDetected, 1);
}
}
{
myCurDetected = 1;
}
- Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myCurDetected);
+ Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
if (anOwner.IsNull())
{
return 0;
{
myCurDetected = 1;
}
- Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myCurDetected);
+ Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
if (anOwner.IsNull())
{
return 0;
--- /dev/null
+puts "============"
+puts "OCC24966"
+puts "============"
+puts ""
+####################################################################################
+# Problem in local selection mode with selected objects staying in the viewer
+# Outdated entity owners remain selected after recompute of presentation in
+# local context.
+# The following cases are tested:
+# o Recompute should not clear per-object selection (neutral selection context).
+# o Recompute should clear per-owner selection (local selection context).
+####################################################################################
+
+set check_recomputed_x 227
+set check_recomputed_y 269
+set check_untouched_x 239
+set check_untouched_y 309
+
+vinit View1
+vpoint p1 100 100 0
+vpoint p2 150 150 0
+vpoint p3 100 150 0
+vplane pln1 p1 p2 p3
+veraseall
+vdisplay pln1 p1 p2 p3
+vselect 0 0 2500 2500
+vchangeplane pln1 x=100 y=100 z=200 dx=0.707 dy=0.707 dz=0.707
+vfit
+
+checkcolor $check_recomputed_x $check_recomputed_y 0.8 0.8 0.8
+if { $stat != 1 } {
+ puts "Error : Neutral selection of updated object is erased."
+}
+
+checkcolor $check_untouched_x $check_untouched_y 0.8 0.8 0.8
+if { $stat != 1 } {
+ puts "Error : Neutral selection of unmodified object is erased."
+}
+
+vinit View2
+vpoint p4 100 100 0
+vpoint p5 150 150 0
+vpoint p6 100 150 0
+vplane pln2 p4 p5 p6
+veraseall
+vdisplay -local pln2 p4 p5 p6
+vselect 0 0 2500 2500
+vchangeplane pln2 x=100 y=100 z=200 dx=0.707 dy=0.707 dz=0.707
+vfit
+
+checkcolor $check_recomputed_x $check_recomputed_y 0 1 0
+if { $stat != 1 } {
+ puts "Error : Local (renewed) selection of updated object is not updated."
+}
+
+checkcolor $check_untouched_x $check_untouched_y 0.8 0.8 0.8
+if { $stat != 1 } {
+ puts "Error : Local selection of unmodified object is erased."
+}
+
+vdump ${imagedir}/${casename}_View1.png
+vdump ${imagedir}/${casename}_View2.png