1 // Copyright (C) 2023 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SPV3D_CADSelection.h"
22 #include <pqActiveObjects.h>
23 #include <pqRenderView.h>
24 #include <pqUndoStack.h>
25 #include <pqCoreUtilities.h>
27 #include <vtkDataObject.h>
28 #include <vtkCollection.h>
29 #include <vtkRenderWindowInteractor.h>
30 #include <vtkPVRenderView.h>
31 #include <vtkPVDataInformation.h>
32 #include <vtkPVArrayInformation.h>
33 #include <vtkPVRenderViewSettings.h>
34 #include <vtkSMRenderViewProxy.h>
35 #include <vtkSMPropertyHelper.h>
36 #include <vtkSMSessionProxyManager.h>
37 #include <vtkSMStringVectorProperty.h>
38 #include <vtkSMRepresentationProxy.h>
39 #include <vtkPVDataSetAttributesInformation.h>
41 //-----------------------------------------------------------------------------
42 SPV3D_CADSelection::SPV3D_CADSelection(QObject *parent,
43 pqRenderView* view, SelectionMode mode):QObject(parent)
47 this->PreviousRenderViewMode = -1;
48 this->MousePosition[0] = 0;
49 this->MousePosition[1] = 0;
50 //this->selectionComboBox = comboBox;
52 for (size_t i = 0; i < sizeof(this->ObserverIds) / sizeof(this->ObserverIds[0]); ++i)
54 this->ObserverIds[i] = 0;
57 //QObject::connect(button, SIGNAL(toggled(bool)), this, SLOT(actionTriggered(bool)));
59 // if view == nullptr, we track the active view.
63 &pqActiveObjects::instance(), SIGNAL(viewChanged(pqView*)), this, SLOT(setView(pqView*)));
64 // this ensure that the enabled-state is set correctly.
65 this->setView(nullptr);
68 this->setRepresentation(nullptr);
69 QObject::connect(&pqActiveObjects::instance(),
70 SIGNAL(representationChanged(pqDataRepresentation*)), this,
71 SLOT(setRepresentation(pqDataRepresentation*)));
73 vtkPVRenderViewSettings::GetInstance()->SetEnableFastPreselection(true);
75 this->updateEnableState();
78 //-----------------------------------------------------------------------------
79 SPV3D_CADSelection::~SPV3D_CADSelection()
81 this->cleanupObservers();
84 //-----------------------------------------------------------------------------
85 void SPV3D_CADSelection::SetMode(const SPV3D_CADSelection::SelectionMode mode)
90 //-----------------------------------------------------------------------------
91 void SPV3D_CADSelection::updateEnableState()
95 //auto paction = this->parentAction();
97 if (this->Representation)
99 vtkSMProxy* proxy = this->Representation->getProxy();
100 vtkSMStringVectorProperty* prop =
101 vtkSMStringVectorProperty::SafeDownCast(proxy->GetProperty("ColorArrayName"));
104 int association = std::atoi(prop->GetElement(3));
105 const char* arrayName = prop->GetElement(4);
107 vtkPVDataInformation* dataInfo = this->Representation->getInputDataInformation();
109 vtkPVDataSetAttributesInformation* info = nullptr;
110 if (association == vtkDataObject::CELL &&
111 this->Mode == SELECT_FACES)
113 info = dataInfo->GetCellDataInformation();
115 if (association == vtkDataObject::POINT &&
116 this->Mode == SELECT_VERTICES)
118 info = dataInfo->GetPointDataInformation();
123 /*vtkPVArrayInformation* arrayInfo = */info->GetArrayInformation(arrayName);
124 //state = arrayInfo && arrayInfo->GetDataType() == VTK_ID_TYPE;
128 //paction->setEnabled(state);
131 //-----------------------------------------------------------------------------
132 void SPV3D_CADSelection::actionTriggered(bool val)
136 this->beginSelection();
140 this->endSelection();
144 //-----------------------------------------------------------------------------
145 void SPV3D_CADSelection::setView(pqView* view)
147 if (this->View != view)
149 // if we were currently in selection, finish that before changing the view.
150 this->endSelection();
153 this->View = qobject_cast<pqRenderView*>(view);
155 // update enable state.
156 //this->parentAction()->setEnabled(this->View != nullptr);
159 //-----------------------------------------------------------------------------
160 void SPV3D_CADSelection::setRepresentation(pqDataRepresentation* representation)
162 if (this->Representation != representation)
164 // if we are currently in selection, finish that before changing the representation.
165 this->endSelection();
167 if (this->Representation != nullptr)
169 QObject::disconnect(this->RepresentationConnection);
172 this->Representation = representation;
174 if (this->Representation != nullptr)
176 this->RepresentationConnection = this->connect(
177 this->Representation, SIGNAL(colorArrayNameModified()), SLOT(updateEnableState()));
180 // update enable state.
181 this->updateEnableState();
185 //-----------------------------------------------------------------------------
186 void SPV3D_CADSelection::beginSelection()
193 //QAction* actn = this->parentAction();
194 //if (actn->isCheckable())
196 //this->selectionComboBox->setEnabled(false);
198 vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
199 vtkSMPropertyHelper(rmp, "InteractionMode").Get(&this->PreviousRenderViewMode);
201 //QString currentPrimitive = this->selectionComboBox->currentText();
202 pqCoreUtilities::promptUser("SPV3D_CADSelection", QMessageBox::Information,
203 "Interactive Selection Information",
204 "You are entering interactive selection mode to highlight.\n"
205 "Move the mouse point over the dataset to interactively highlight elements.\n\n"
206 "Press Ctrl + click to add the currently highlighted element.\n"
207 "Press Shift + click to remove the element.\n\n"
208 "Click on Select button to exit this mode.",
209 QMessageBox::Ok | QMessageBox::Save);
210 this->View->setCursor(Qt::CrossCursor);
211 vtkSMPropertyHelper(rmp, "InteractionMode").Set(vtkPVRenderView::INTERACTION_MODE_SELECTION);
213 rmp->UpdateVTKObjects();
216 assert(this->ObserverIds[0] == 0 && this->ObservedObject == nullptr && this->ObserverIds[1] == 0);
217 this->ObservedObject = rmp->GetInteractor();
218 this->ObserverIds[0] = this->ObservedObject->AddObserver(
219 vtkCommand::MouseMoveEvent, this, &SPV3D_CADSelection::onMouseMove);
220 this->ObserverIds[1] = this->ObservedObject->AddObserver(vtkCommand::LeftButtonReleaseEvent,
221 this, &SPV3D_CADSelection::onLeftButtonRelease);
222 this->ObserverIds[2] = this->ObservedObject->AddObserver(vtkCommand::RightButtonPressEvent,
223 this, &SPV3D_CADSelection::onRightButtonPress);
224 this->ObserverIds[3] = this->ObservedObject->AddObserver(vtkCommand::RightButtonReleaseEvent,
225 this, &SPV3D_CADSelection::onRightButtonRelease);
227 //this->parentAction()->setChecked(true);
231 //-----------------------------------------------------------------------------
232 void SPV3D_CADSelection::endSelection()
239 if (this->PreviousRenderViewMode == -1)
244 //QAction* actn = this->parentAction();
245 //if (actn->isCheckable())
247 vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
248 vtkSMPropertyHelper(rmp, "InteractionMode").Set(this->PreviousRenderViewMode);
249 this->PreviousRenderViewMode = -1;
250 rmp->UpdateVTKObjects();
251 this->View->setCursor(QCursor());
252 this->cleanupObservers();
253 //this->parentAction()->setChecked(false);
255 if (this->CurrentRepresentation != nullptr)
257 vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
258 vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
260 this->CurrentRepresentation->UpdateVTKObjects();
261 this->CurrentRepresentation = nullptr;
267 //this->selectionComboBox->setEnabled(true);
271 //-----------------------------------------------------------------------------
272 void SPV3D_CADSelection::onMouseMove()
274 if (!this->DisablePreSelection && vtkPVRenderViewSettings::GetInstance()->GetEnableFastPreselection())
276 this->fastSelection(true);
280 //-----------------------------------------------------------------------------
281 void SPV3D_CADSelection::onLeftButtonRelease()
283 if (vtkPVRenderViewSettings::GetInstance()->GetEnableFastPreselection())
285 this->fastSelection();
289 //-----------------------------------------------------------------------------
290 void SPV3D_CADSelection::onRightButtonPress()
292 this->DisablePreSelection = true;
295 //-----------------------------------------------------------------------------
296 void SPV3D_CADSelection::onRightButtonRelease()
298 this->DisablePreSelection = false;
301 //-----------------------------------------------------------------------------
302 void SPV3D_CADSelection::fastSelection(bool presel)
304 vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
305 assert(rmp != nullptr);
307 int x = rmp->GetInteractor()->GetEventPosition()[0];
308 int y = rmp->GetInteractor()->GetEventPosition()[1];
309 this->MousePosition[0] = x;
310 this->MousePosition[1] = y;
312 int region[4] = { x, y, x, y };
314 vtkNew<vtkCollection> selectedRepresentations;
315 vtkNew<vtkCollection> selectionSources;
317 // Do the selection on the current region
321 status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Solid id");
324 status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Face id");
327 status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Edge id");
329 case SELECT_VERTICES:
330 status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Vertex id");
333 qCritical("Invalid call to SPV3D_CADSelection::fastSelection");
337 vtkSMRepresentationProxy* repr =
338 vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
342 repr->InvokeCommand("BeginSelect");
345 // If something has been preselected or selected
348 vtkSMRepresentationProxy* repr =
349 vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
351 // If the selection occurs on a new represention, clean the selection on the
352 // current representation before continuing
353 if (this->CurrentRepresentation != nullptr && repr != this->CurrentRepresentation)
355 vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
356 vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
358 vtkSMPropertyHelper(this->CurrentRepresentation, "Selection").Set(emptySel);
359 this->CurrentRepresentation->UpdateVTKObjects();
363 this->CurrentRepresentation = repr;
365 // Set the selection (selection source) to the current representation
366 vtkSMSourceProxy* sel = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
367 vtkSMPropertyHelper(repr, "Selection").Set(sel);
368 repr->UpdateVTKObjects();
370 // If nothing has been selected then clean current representation
371 // with an "empty" selection source
372 else if (this->CurrentRepresentation != nullptr)
374 vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
375 vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
377 vtkSMPropertyHelper(this->CurrentRepresentation, "Selection").Set(emptySel);
378 this->CurrentRepresentation->UpdateVTKObjects();
379 this->CurrentRepresentation = nullptr;
383 this->View->forceRender();
384 this->View->forceRender();
385 // TODO improve this to avoid double render
389 repr->InvokeCommand("EndSelect");
393 //-----------------------------------------------------------------------------
394 void SPV3D_CADSelection::selectionChanged(vtkObject*, unsigned long, void* calldata)
396 BEGIN_UNDO_EXCLUDE();
398 int selectionModifier = this->getSelectionModifier();
399 int* region = reinterpret_cast<int*>(calldata);
400 // Simple version check to change once 5.10 support is dropped
401 this->View->selectCellsOnSurface(region, selectionModifier);
402 //this->View->selectOnSurface(region, selectionModifier);
405 this->endSelection();
408 //-----------------------------------------------------------------------------
409 int SPV3D_CADSelection::getSelectionModifier()
411 int selectionModifier = pqView::PV_SELECTION_DEFAULT;//this->Superclass::getSelectionModifier();
413 vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
414 assert(rmp != nullptr);
416 bool ctrl = rmp->GetInteractor()->GetControlKey() == 1;
417 bool shift = rmp->GetInteractor()->GetShiftKey() == 1;
418 selectionModifier = pqView::PV_SELECTION_TOGGLE;
422 selectionModifier = pqView::PV_SELECTION_ADDITION;
426 selectionModifier = pqView::PV_SELECTION_SUBTRACTION;
428 return selectionModifier;
431 //-----------------------------------------------------------------------------
432 void SPV3D_CADSelection::cleanupObservers()
434 for (size_t i = 0; i < sizeof(this->ObserverIds) / sizeof(this->ObserverIds[0]); ++i)
436 if (this->ObservedObject != nullptr && this->ObserverIds[i] > 0)
438 this->ObservedObject->RemoveObserver(this->ObserverIds[i]);
440 this->ObserverIds[i] = 0;
442 this->ObservedObject = nullptr;