]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Rework selection and preselection & add multi-selection support
authorThomas Galland <thomas.galland@kitware.com>
Mon, 28 Oct 2024 16:10:31 +0000 (17:10 +0100)
committerThomas Galland <thomas.galland@kitware.com>
Fri, 22 Nov 2024 14:15:01 +0000 (15:15 +0100)
Add multi-selection support

src/.vscode/c_cpp_properties.json [new file with mode: 0644]
src/SPV3D/SPV3D_CADSelection.cxx
src/SPV3D/SPV3D_CADSelection.h

diff --git a/src/.vscode/c_cpp_properties.json b/src/.vscode/c_cpp_properties.json
new file mode 100644 (file)
index 0000000..72c68a3
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "configurations": [
+        {
+            "name": "Linux",
+            "compileCommands": "${workspaceFolder}/../../../BUILD/GUI/compile_commands.json",
+            "intelliSenseMode": "linux-gcc-x64",
+            "cStandard": "c17",
+            "cppStandard": "c++14"
+        }
+    ],
+    "version": 4
+}
\ No newline at end of file
index 94ef5a2b2c4a552b4156a0e8553760726a13b1e0..30e65b6f66a8bdba2d5fef18a1d91a51ad1c7fc6 100644 (file)
@@ -34,6 +34,7 @@
 #include <vtkPVRenderViewSettings.h>
 #include <vtkSMRenderViewProxy.h>
 #include <vtkSMPropertyHelper.h>
+#include <vtkSMSelectionHelper.h>
 #include <vtkSMSessionProxyManager.h>
 #include <vtkSMStringVectorProperty.h>
 #include <vtkSMRepresentationProxy.h>
 
 #include "SPV3D_Prs.h"
 
+// TO REMOVE
+#include <algorithm>
+#include <iterator>
+#include "vtkSMProxyManager.h"
+#include <regex>
+#include <set>
+#include <unordered_set>
+namespace
+{
+void ReplaceString(std::string& source, const std::string& replace, const std::string& with)
+{
+  const std::regex reg("[a-zA-Z0-9]+");
+  for (auto match = std::sregex_iterator(source.begin(), source.end(), reg);
+       match != std::sregex_iterator(); ++match)
+  {
+    if (match->str() == replace)
+    {
+      source.replace(match->position(), match->length(), with);
+    }
+  }
+}
+enum class CombineOperation
+{
+  DEFAULT = 0,
+  ADDITION = 1,
+  SUBTRACTION = 2,
+  TOGGLE = 3
+};
+const std::string SubSelectionBaseName = "s";
+bool CombineSelection(vtkSMSourceProxy* appendSelections1,
+  vtkSMSourceProxy* appendSelections2, CombineOperation combineOperation, bool deepCopy)
+{
+  if (!appendSelections1 || !appendSelections2)
+  {
+    return false;
+  }
+  if (vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements() == 0)
+  {
+    return false;
+  }
+  if (deepCopy)
+  {
+    if (vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements() == 0)
+    {
+      // create a combined appendSelections which is deep copy of appendSelections2
+      vtkSMSessionProxyManager* pxm = vtkSMProxyManager::GetProxyManager()->GetSessionProxyManager(
+        appendSelections2->GetSession());
+      vtkSmartPointer<vtkSMSourceProxy> combinedAppendSelections;
+      combinedAppendSelections.TakeReference(
+        vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("filters", "AppendSelections")));
+
+      vtkSMPropertyHelper(combinedAppendSelections, "Expression")
+        .Set(vtkSMPropertyHelper(appendSelections2, "Expression").GetAsString());
+      vtkSMPropertyHelper(combinedAppendSelections, "InsideOut")
+        .Set(vtkSMPropertyHelper(appendSelections2, "InsideOut").GetAsInt());
+
+      // add selection input and names of appendSelections2
+      unsigned int numInputs =
+        vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements();
+      for (unsigned int i = 0; i < numInputs; ++i)
+      {
+        auto selectionSource = vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(i);
+        vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
+        selectionSourceCopy.TakeReference(
+          vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
+        selectionSourceCopy->Copy(selectionSource);
+        selectionSourceCopy->UpdateVTKObjects();
+
+        vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
+        vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
+          .Set(i, vtkSMPropertyHelper(appendSelections2, "SelectionNames").GetAsString(i));
+      }
+      appendSelections2->Copy(combinedAppendSelections);
+      appendSelections2->UpdateVTKObjects();
+      return true;
+    }
+  }
+  else
+  {
+    if (vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements() == 0)
+    {
+      return true;
+    }
+  }
+  if (combineOperation == CombineOperation::DEFAULT)
+  {
+    return true;
+  }
+  // appendSelections1 serves as input1 and appendSelections2 serves as input2.
+  // The result of this function will be appended into appendSelections2.
+
+  // The appendSelections1 is combine-able with the appendSelections2 if they have the same
+  // FieldType/ElementType and if they have the same ContainingCells
+  // Checking only one of the inputs is sufficient.
+  vtkSMProxy* firstSelectionSourceAP1 =
+    vtkSMPropertyHelper(appendSelections1, "Input").GetAsProxy(0);
+  vtkSMProxy* firstSelectionSourceAP2 =
+    vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(0);
+
+  // SelectionQuerySource has element type and not field type
+  int fieldTypeOfFirstSelectionSourceAP1 = firstSelectionSourceAP1->GetProperty("FieldType")
+    ? vtkSMPropertyHelper(firstSelectionSourceAP1, "FieldType").GetAsInt()
+    : vtkSelectionNode::ConvertAttributeTypeToSelectionField(
+        vtkSMPropertyHelper(firstSelectionSourceAP1, "ElementType").GetAsInt());
+  int fieldTypeOfFirstSelectionSourceAP2 = firstSelectionSourceAP2->GetProperty("FieldType")
+    ? vtkSMPropertyHelper(firstSelectionSourceAP2, "FieldType").GetAsInt()
+    : vtkSelectionNode::ConvertAttributeTypeToSelectionField(
+        vtkSMPropertyHelper(firstSelectionSourceAP2, "ElementType").GetAsInt());
+  if (fieldTypeOfFirstSelectionSourceAP1 != fieldTypeOfFirstSelectionSourceAP2)
+  {
+    return false;
+  }
+
+  if (vtkSMPropertyHelper(firstSelectionSourceAP1, "ContainingCells", true).GetAsInt() !=
+    vtkSMPropertyHelper(firstSelectionSourceAP2, "ContainingCells", true).GetAsInt())
+  {
+    return false;
+  }
+
+  unsigned int numInputsAP1 = vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements();
+  // find the largest selection name id of the appendSelections2
+  int maxId = -1;
+  for (unsigned int i = 0; i < numInputsAP1; ++i)
+  {
+    // get the selection name
+    std::string selectionName =
+      vtkSMPropertyHelper(appendSelections1, "SelectionNames").GetAsString(i);
+    // remove the S prefix
+    selectionName.erase(0, SubSelectionBaseName.size());
+    // get the id
+    maxId = std::max(maxId, std::stoi(selectionName));
+  }
 
+  // create new expression and selection names from appendSelections2's selections sources
+  std::string newExpressionAP2 = vtkSMPropertyHelper(appendSelections2, "Expression").GetAsString();
+  unsigned int numInputsAP2 = vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements();
+  std::list<std::string> newSelectionNamesAP2;
+  for (int i = static_cast<int>(numInputsAP2) - 1; i >= 0; --i)
+  {
+    const std::string oldSelectionName = vtkSMPropertyHelper(appendSelections2, "SelectionNames")
+                                           .GetAsString(static_cast<unsigned int>(i));
+    std::string newSelectionName = oldSelectionName;
+    // remove the S prefix
+    newSelectionName.erase(0, SubSelectionBaseName.size());
+    // compute new selection name id
+    int selectionNameId = std::atoi(newSelectionName.c_str()) + maxId + 1;
+    newSelectionName = SubSelectionBaseName + std::to_string(selectionNameId);
+    // save new selection name
+    newSelectionNamesAP2.push_front(newSelectionName);
+    // update the expression
+    ReplaceString(newExpressionAP2, oldSelectionName, newSelectionName);
+  }
+
+  // create a combined appendSelections
+  vtkSMSessionProxyManager* pxm =
+    vtkSMProxyManager::GetProxyManager()->GetSessionProxyManager(appendSelections2->GetSession());
+  vtkSmartPointer<vtkSMSourceProxy> combinedAppendSelections;
+  combinedAppendSelections.TakeReference(
+    vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("filters", "AppendSelections")));
+  // add selection input and names of appendSelections1 to appendSelections2
+  for (unsigned int i = 0; i < numInputsAP1; ++i)
+  {
+    auto selectionSource = vtkSMPropertyHelper(appendSelections1, "Input").GetAsProxy(i);
+    if (deepCopy)
+    {
+      vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
+      selectionSourceCopy.TakeReference(
+        vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
+      selectionSourceCopy->Copy(selectionSource);
+      selectionSourceCopy->UpdateVTKObjects();
+      vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
+    }
+    else
+    {
+      vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSource);
+    }
+    vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
+      .Set(i, vtkSMPropertyHelper(appendSelections1, "SelectionNames").GetAsString(i));
+  }
+  auto iter = newSelectionNamesAP2.begin();
+  for (unsigned int i = 0; i < numInputsAP2; ++i, ++iter)
+  {
+    auto selectionSource = vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(i);
+    if (deepCopy)
+    {
+      vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
+      selectionSourceCopy.TakeReference(
+        vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
+      selectionSourceCopy->Copy(selectionSource);
+      selectionSourceCopy->UpdateVTKObjects();
+      vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
+    }
+    else
+    {
+      vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSource);
+    }
+    vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
+      .Set(numInputsAP1 + i, iter->c_str());
+  }
+
+  // add inside out qualifier to the expressions
+  const int insideOutAP1 = vtkSMPropertyHelper(appendSelections1, "InsideOut").GetAsInt();
+  std::string newExpressionAP1 = vtkSMPropertyHelper(appendSelections1, "Expression").GetAsString();
+  if (numInputsAP1 > 1)
+  {
+    newExpressionAP1 = '(' + newExpressionAP1 + ')';
+  }
+  newExpressionAP1 = (insideOutAP1 ? "!" : "") + newExpressionAP1;
+
+  const int insideOutAP2 = vtkSMPropertyHelper(appendSelections2, "InsideOut").GetAsInt();
+  if (numInputsAP2 > 1)
+  {
+    newExpressionAP2 = '(' + newExpressionAP2 + ')';
+  }
+  newExpressionAP2 = (insideOutAP2 ? "!" : "") + newExpressionAP2;
+
+  // combine appendSelections1 and appendSelections2 expressions
+  std::string newCombinedExpression;
+  switch (combineOperation)
+  {
+    case CombineOperation::ADDITION:
+    {
+      newCombinedExpression = newExpressionAP1 + '|' + newExpressionAP2;
+      break;
+    }
+    case CombineOperation::SUBTRACTION:
+    {
+      newCombinedExpression = newExpressionAP1 + "&!" + newExpressionAP2;
+      break;
+    }
+    case CombineOperation::TOGGLE:
+    default:
+    {
+      newCombinedExpression = newExpressionAP1 + '^' + newExpressionAP2;
+      break;
+    }
+  }
+  vtkSMPropertyHelper(combinedAppendSelections, "Expression").Set(newCombinedExpression.c_str());
+  appendSelections2->Copy(combinedAppendSelections);
+  appendSelections2->UpdateVTKObjects();
+  // cout << "Expression : " << newCombinedExpression << endl;
+  return true;
+}
+bool IgnoreSelection(
+  vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+{
+  return CombineSelection(
+    appendSelections1, appendSelections2, CombineOperation::DEFAULT, deepCopy);
+}
+bool AddSelection(
+  vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+{
+  return CombineSelection(
+    appendSelections1, appendSelections2, CombineOperation::ADDITION, deepCopy);
+}
+bool SubtractSelection(
+  vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+{
+  return CombineSelection(
+    appendSelections1, appendSelections2, CombineOperation::SUBTRACTION, deepCopy);
+}
+bool ToggleSelection(
+  vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+{
+  return CombineSelection(
+    appendSelections1, appendSelections2, CombineOperation::TOGGLE, deepCopy);
+}
+}
 
 //-----------------------------------------------------------------------------
 SPV3D_CADSelection::SPV3D_CADSelection(QObject *parent,
@@ -246,6 +514,7 @@ void SPV3D_CADSelection::beginSelection()
 //-----------------------------------------------------------------------------
 void SPV3D_CADSelection::endSelection()
 {
+  cout << "End Selection " << endl;
   if (!this->View)
   {
     return;
@@ -269,6 +538,7 @@ void SPV3D_CADSelection::endSelection()
 
     if (this->CurrentRepresentation != nullptr)
     {
+      cout << "???" << endl;
       vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
       vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
 
@@ -288,7 +558,7 @@ void SPV3D_CADSelection::onMouseMove()
 {
   if (!this->DisablePreSelection && vtkPVRenderViewSettings::GetInstance()->GetEnableFastPreselection())
   {
-    this->fastSelection(true);
+    this->fastPreSelection();
   }
 
   // get preselected id here
@@ -340,8 +610,106 @@ void SPV3D_CADSelection::onRightButtonRelease()
   this->DisablePreSelection = false;
 }
 
+namespace SelectionUtilities
+{
+//-----------------------------------------------------------------------------
+bool SetSelectionFromValues(vtkSMRepresentationProxy* repr, const std::set<std::pair<vtkIdType, vtkIdType>>& values)
+{
+  vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
+  vtkSmartPointer<vtkSMProxy> newSelectionSource;
+  newSelectionSource.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
+  vtkSMPropertyHelper(newSelectionSource, "ArrayName").Set("Solid id");
+  vtkSMPropertyHelper(newSelectionSource, "FieldType").Set("CELL");
+  vtkSMPropertyHelper(newSelectionSource, "Values").SetNumberOfElements(values.size());
+  vtkSMPropertyHelper(newSelectionSource, "Values").RemoveAllValues();
+  for (const auto& pair: values)
+  {
+    std::array<vtkIdType, 2> pairValues = {pair.first, pair.second};
+    vtkSMPropertyHelper(newSelectionSource, "Values").Append(pairValues.data(), 2);
+  }
+  newSelectionSource->UpdateVTKObjects();
+
+  vtkSMPropertyHelper(repr, "Selection").Set(newSelectionSource);
+  repr->UpdateVTKObjects();
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+void SetSelection(vtkSMRepresentationProxy* repr, vtkSMSourceProxy* selectionSource)
+{
+  selectionSource->UpdateVTKObjects();
+
+  vtkSMPropertyHelper(repr, "Selection").Set(selectionSource);
+  repr->UpdateVTKObjects();
+}
+
+//-----------------------------------------------------------------------------
+void RemoveSelection(vtkSMRepresentationProxy* repr)
+{
+  // Under the hood, we simply add an empty selection source
+  vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
+  vtkSmartPointer<vtkSMProxy> emptySelection;
+  emptySelection.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
+  emptySelection->UpdateVTKObjects();
+
+  vtkSMPropertyHelper(repr, "Selection").Set(emptySelection);
+  repr->UpdateVTKObjects();
+}
+
+//-----------------------------------------------------------------------------
+bool GetSelectionValues(vtkSMProxy* selectionSourceProxy, std::set<std::pair<vtkIdType, vtkIdType>>& values)
+{
+  if (selectionSourceProxy)
+  {
+    auto allValues = vtkSMPropertyHelper(selectionSourceProxy, "Values").GetIdTypeArray();
+    for (int i = 0; i < allValues.size(); i+=2) // skip process ids
+    {
+      values.insert(std::make_pair(allValues[i], allValues[i+1]));
+    }
+    return true;
+  }
+  return false;
+}
+}
+
+namespace SelectionOperations
+{
 //-----------------------------------------------------------------------------
-void SPV3D_CADSelection::fastSelection(bool presel)
+void Union(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
+{
+  result.clear();
+  std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
+
+  std::set_union(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
+}
+
+//-----------------------------------------------------------------------------
+void Difference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
+{
+  result.clear();
+  std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
+
+  std::set_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
+}
+
+//-----------------------------------------------------------------------------
+void SymmetricDifference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
+{
+  result.clear();
+  std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
+  SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
+
+  std::set_symmetric_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
+}
+}
+
+//-----------------------------------------------------------------------------
+void SPV3D_CADSelection::fastSelection()
 {
   vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
   assert(rmp != nullptr);
@@ -379,12 +747,109 @@ void SPV3D_CADSelection::fastSelection(bool presel)
   vtkSMRepresentationProxy* repr =
     vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
 
-  // Forward the selection to the server
-  if (repr && !presel)
+  // If something has been preselected or selected
+  if (status)
+  {
+    // If the selection occurs on a new represention, clean the selection on the
+    // current representation before continuing
+    if (this->CurrentRepresentation != nullptr && repr != this->CurrentRepresentation)
+    {
+      SelectionUtilities::RemoveSelection(this->CurrentRepresentation);
+    }
+
+    this->CurrentRepresentation = repr;
+
+    // Set the selection (selection source) to the current representation
+    vtkSMSourceProxy* currentSelection = vtkSMSourceProxy::SafeDownCast(vtkSMPropertyHelper(repr, "Selection").GetAsProxy());
+
+    vtkSMSourceProxy* newSelection = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
+    // vtkSmartPointer<vtkSMSourceProxy> newAppendSelections;
+    // newAppendSelections.TakeReference(vtkSMSourceProxy::SafeDownCast(
+    //   vtkSMSelectionHelper::NewAppendSelectionsFromSelectionSource(selectionSource)));
+
+    switch (this->getSelectionModifier())
+    {
+      case pqView::PV_SELECTION_ADDITION:
+      {
+        std::set<std::pair<vtkIdType, vtkIdType>> values;
+        SelectionOperations::Union(currentSelection, newSelection, values);
+        SelectionUtilities::SetSelectionFromValues(repr, values);
+        break;
+      }
+      case pqView::PV_SELECTION_SUBTRACTION:
+      {
+        std::set<std::pair<vtkIdType, vtkIdType>> values;
+        SelectionOperations::Difference(currentSelection, newSelection, values);
+        SelectionUtilities::SetSelectionFromValues(repr, values);
+        break;     
+      }
+      case pqView::PV_SELECTION_TOGGLE:
+      {
+        std::set<std::pair<vtkIdType, vtkIdType>> values;
+        SelectionOperations::SymmetricDifference(currentSelection, newSelection, values);
+        SelectionUtilities::SetSelectionFromValues(repr, values);
+        break;
+      }
+      case pqView::PV_SELECTION_DEFAULT:
+      default:
+        // Just keep the current selection
+        SelectionUtilities::SetSelection(repr, newSelection);
+        break;
+    }
+    // vtkSMPropertyHelper(repr, "Selection").Set(newAppendSelections);
+    // repr->UpdateVTKObjects();
+  }
+  else if (this->CurrentRepresentation != nullptr)
+  {
+    // If nothing has been selected then clean current representation
+    // with an "empty" selection source
+    SelectionUtilities::RemoveSelection(repr);
+  }
+
+  this->View->forceRender();
+  this->View->forceRender();
+  // TODO improve this to avoid double render
+}
+
+//-----------------------------------------------------------------------------
+void SPV3D_CADSelection::fastPreSelection()
+{
+  vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
+  assert(rmp != nullptr);
+
+  int x = rmp->GetInteractor()->GetEventPosition()[0];
+  int y = rmp->GetInteractor()->GetEventPosition()[1];
+  this->MousePosition[0] = x;
+  this->MousePosition[1] = y;
+
+  int region[4] = { x, y, x, y };
+
+  // Do the selection on the current region (client side)
+  vtkNew<vtkCollection> selectedRepresentations;
+  vtkNew<vtkCollection> selectionSources;
+  bool status = false;
+  switch (this->Mode)
   {
-    repr->InvokeCommand("BeginSelect");
+    case SELECT_SOLIDS:
+      status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Solid id");
+      break;
+    case SELECT_FACES:
+      status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Face id");
+      break;
+    case SELECT_EDGES:
+      status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Edge id");
+      break;
+    case SELECT_VERTICES:
+      status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Vertex id");
+      break;
+    default:
+      qCritical("Invalid call to SPV3D_CADSelection::fastSelection");
+      return;
   }
 
+  vtkSMRepresentationProxy* repr =
+    vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
+
   // If something has been preselected or selected
   if (status)
   {
@@ -395,7 +860,7 @@ void SPV3D_CADSelection::fastSelection(bool presel)
       vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
       vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
 
-      vtkSMPropertyHelper(this->CurrentRepresentation, "Selection").Set(emptySel);
+      vtkSMPropertyHelper(this->CurrentRepresentation, "PreSelection").Set(emptySel);
       this->CurrentRepresentation->UpdateVTKObjects();
       emptySel->Delete();
     }
@@ -405,7 +870,7 @@ void SPV3D_CADSelection::fastSelection(bool presel)
     // Set the selection (selection source) to the current representation
     // TODO: There should be some cases where we append instead. Which ones ? When a modifier is pressed ? (i.e. the Control Key)
     vtkSMSourceProxy* sel = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
-    vtkSMPropertyHelper(repr, "Selection").Set(sel);
+    vtkSMPropertyHelper(repr, "PreSelection").Set(sel);
     repr->UpdateVTKObjects();
   }
 
@@ -416,7 +881,7 @@ void SPV3D_CADSelection::fastSelection(bool presel)
     vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
     vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
 
-    vtkSMPropertyHelper(this->CurrentRepresentation, "Selection").Set(emptySel);
+    vtkSMPropertyHelper(this->CurrentRepresentation, "PreSelection").Set(emptySel);
     this->CurrentRepresentation->UpdateVTKObjects();
     this->CurrentRepresentation = nullptr;
     emptySel->Delete();
@@ -425,11 +890,6 @@ void SPV3D_CADSelection::fastSelection(bool presel)
   this->View->forceRender();
   this->View->forceRender();
   // TODO improve this to avoid double render
-
-  if (repr && !presel)
-  {
-    repr->InvokeCommand("EndSelect");
-  }
 }
 
 //-----------------------------------------------------------------------------
@@ -437,6 +897,8 @@ void SPV3D_CADSelection::selectionChanged(vtkObject*, unsigned long, void* calld
 {
   BEGIN_UNDO_EXCLUDE();
 
+  cout << "Selection changed: should not enter there !" << endl;
+
   int selectionModifier = this->getSelectionModifier();
   int* region = reinterpret_cast<int*>(calldata);
 // Simple version check to change once 5.10 support is dropped
@@ -444,7 +906,7 @@ void SPV3D_CADSelection::selectionChanged(vtkObject*, unsigned long, void* calld
   //this->View->selectOnSurface(region, selectionModifier);
   END_UNDO_EXCLUDE();
 
-  this->endSelection();
+  // this->endSelection();
 }
 
 //-----------------------------------------------------------------------------
@@ -457,7 +919,7 @@ int SPV3D_CADSelection::getSelectionModifier()
 
   bool ctrl = rmp->GetInteractor()->GetControlKey() == 1;
   bool shift = rmp->GetInteractor()->GetShiftKey() == 1;
-  selectionModifier = pqView::PV_SELECTION_TOGGLE;
+  // selectionModifier = pqView::PV_SELECTION_TOGGLE;
 
   if (ctrl)
   {
@@ -484,8 +946,10 @@ void SPV3D_CADSelection::cleanupObservers()
   this->ObservedObject = nullptr;
 }
 
+//-----------------------------------------------------------------------------
 std::set<std::string> SPV3D_CADSelection::GetSelectedObEntry()
 {
+  // std::cout << "Get Selected Ob Entry" << std::endl;
   std::set<std::string> EntryList;
 
   // get preselected id here
@@ -501,40 +965,21 @@ std::set<std::string> SPV3D_CADSelection::GetSelectedObEntry()
     return EntryList;
   }
 
-  // Retrieve the wanted information property
-  vtkSMProperty* selectionProperty = proxyRepresentation->GetProperty("Selection");
-  if (selectionProperty == nullptr)
-  {
-    qWarning()<< "The representation named '" << proxyRepresentation->GetXMLName()<< "' did not have a property named 'Selection'.";
-    return EntryList;
-  }
-
-  // Force to update the information property
-  proxyRepresentation->UpdatePropertyInformation(selectionProperty);
-
-  // Extract all selected indices
-  std::vector<int> selectedIdx =
-   vtkSMPropertyHelper(proxyRepresentation,"SelectedIDInfo").GetIntArray();
-
-  std::cout << "(Client) Received selected entries from server:" << std::endl;
-
-  if (selectedIdx.empty())
+  vtkSMProxy* selInfo = vtkSMPropertyHelper(proxyRepresentation, "Selection").GetAsProxy(0);
+  if (selInfo)
   {
-    qWarning() << "There is no selected id for now.";
-  }
-  else
-  {
-    // Convert all selectedId from Representation in entry type and insert them in set
-    for(std::size_t i = 0; i < selectedIdx.size(); i++)
+    auto ids = vtkSMPropertyHelper(selInfo, "Values").GetIdTypeArray();
+    for (const auto id : ids)
     {
-      std::cout << selectedIdx[i] << std::endl;
-      EntryList.insert( SPV3D_Prs::FromVtkIdToEntry(static_cast<vtkIdType>(selectedIdx[i])) );
+      // cout << "Values : " << id << endl;
+      EntryList.insert(SPV3D_Prs::FromVtkIdToEntry(id));
     }
   }
-  return EntryList;
 
+  return EntryList;
 }
 
+//-----------------------------------------------------------------------------
 // TODO: Prefer passing parameters by const ref rather than by copy
 void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryList)
 {
@@ -543,7 +988,6 @@ void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryLis
     return;
   }
 
-
   vtkSMProxy* proxyRepresentation = this->Representation->getProxy();
   if (!proxyRepresentation) 
   {
@@ -552,7 +996,7 @@ void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryLis
   }
   // this->View->forceRender();
 
-  proxyRepresentation->InvokeCommand("BeginSelect");
+  // proxyRepresentation->InvokeCommand("BeginSelect");
 
   // Create a new selection source on the server side and its proxy on the client side
   vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
@@ -566,13 +1010,13 @@ void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryLis
   vtkIdType processNumber = 0;
 
   // Retrieve entry ids and put them in a vector
-  std::cout << "(Client) Sending selected entries to server:" << std::endl;
+  // std::cout << "(Client) Sending selected entries to server:" << std::endl;
   
   // TODO: Make sure this works for multiple selections
   for (const std::string& entryName: EntryList)
   {
     vtkIdType solidId = SPV3D_Prs::FromEntryToVtkId(entryName.c_str());
-    std::cout << "(Client) " << solidId << std::endl;
+    // std::cout << "(Client) " << solidId << std::endl;
 
     // This takes pairs of values as (process number, value).
     std::array<vtkIdType, 2> values = {solidId, processNumber};
@@ -580,8 +1024,8 @@ void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryLis
   }
 
   selectionSource->UpdateVTKObjects();
-  
-  vtkSMPropertyHelper(proxyRepresentation, "Selection").Set(selectionSource);
+  // cout << "SetSelectionFromEntrySet" << endl;
+  // vtkSMPropertyHelper(proxyRepresentation, "Selection").Set(selectionSource);
   proxyRepresentation->UpdateVTKObjects();
   
   selectionSource->Delete();
@@ -593,7 +1037,7 @@ void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryLis
   this->View->forceRender();
   rmp->StillRender();
 
-  proxyRepresentation->InvokeCommand("EndSelect");
+  // proxyRepresentation->InvokeCommand("EndSelect");
   
 
 }
index 84bfd040ee4ae8278b88efa22877555c2a090e2c..e50d1a92a7ed5e62d7e4e53eed204210b386ef3b 100644 (file)
@@ -153,7 +153,12 @@ private:
   /**
    * makes fast selection.
    */
-  void fastSelection(bool presel = false);
+  void fastSelection();
+
+  /**
+   * makes fast selection.
+   */
+  void fastPreSelection();
 
   /**
    * cleans up observers.