Salome HOME
Updated copyright comment
[modules/gui.git] / src / SPV3D / SPV3D_ViewWindow.cxx
1 // Copyright (C) 2023-2024  CEA, EDF
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SPV3D_ViewWindow.h"
21
22 #include "SPV3D_ViewModel.h"
23
24 #include <QMenu>
25 #include <QToolBar>
26 #include <QTimer>
27 #include <QEvent>
28 #include <QFileInfo>
29 #include <QSignalMapper>
30 #include <QXmlStreamWriter>
31 #include <QXmlStreamReader>
32 #include <QXmlStreamAttributes>
33
34 #include <pqView.h>
35
36 #include "QtxAction.h"
37
38 #include "SUIT_Session.h"
39 #include "SUIT_MessageBox.h"
40 #include "SUIT_Accel.h"
41 #include "SUIT_Tools.h"
42 #include "SUIT_ResourceMgr.h"
43 #include "SUIT_Accel.h"
44 #include "SUIT_OverrideCursor.h"
45 #include "SUIT_ViewManager.h"
46 #include "QtxActionToolMgr.h"
47 #include "QtxMultiAction.h"
48 #include "QtxActionGroup.h"
49
50 #include <pqCameraReaction.h>
51 #include <pqParaViewBehaviors.h>
52 #include <pqRenderView.h>
53
54 #include "SALOME_ListIO.hxx"
55 #include "SPV3D_Prs.h"
56
57 #include <QToolBar>
58
59 // Use workaround for rendering transparent object over MESA
60 #define USE_WORKAROUND_FOR_MESA
61
62 /*!
63   Constructor
64 */
65 SPV3D_ViewWindow::SPV3D_ViewWindow(SUIT_Desktop* theDesktop, SPV3D_ViewModel* theModel):
66   PV3DViewer_ViewWindow(theDesktop, theModel),
67   myModel(theModel)
68 {
69 }
70
71 #include <pqRenderViewSelectionReaction.h>
72 #include <pqPipelineSource.h>
73 #include <vtkSMRenderViewProxy.h>
74 #include <vtkCollection.h>
75 #include <vtkSMRepresentationProxy.h>
76 #include <vtkSMPropertyHelper.h>
77 #include <vtkSMProxyManager.h>
78 #include <vtkRenderer.h>
79 #include <vtkSMSessionProxyManager.h>
80
81 #include "SPV3D_CADSelection.h"
82
83 void SPV3D_ViewWindow::init()
84 {
85   pqView *view(myModel->getView());
86   pqRenderView *renderView(qobject_cast<pqRenderView *>(view));
87   QWidget *wid = view->widget();
88   wid->setParent( this );
89   setCentralWidget( wid );
90   //
91   this->
92   myToolBar = toolMgr()->createToolBar( tr("LBL_TOOLBAR_LABEL"),                       // title (language-dependant)
93                                         QString( "PV3DViewerViewOperations" ),          // name (language-independant)
94                                         false );
95   QAction* resetCenterAction =
96     toolMgr()->toolBar(myToolBar)->addAction(QIcon(":/pqWidgets/Icons/pqResetCamera.svg"), tr( "MNU_FITALL" ) );
97   new pqCameraReaction(resetCenterAction, pqCameraReaction::RESET_CAMERA);
98   QAction *showCenterAction =
99     toolMgr()->toolBar(myToolBar)->addAction(QIcon(":/pqWidgets/Icons/pqShowCenterAxes.svg"), tr( "DSC_SHOW_TRIHEDRON" ) );
100   showCenterAction->setCheckable(true);
101   QObject::connect(showCenterAction, &QAction::toggled, this, &SPV3D_ViewWindow::showCenterAxes);
102   
103   // Pick a new center of rotation on the surface of the mesh
104   QAction* pickCenterAction = toolMgr()->toolBar(myToolBar)->addAction(QIcon(":/pqWidgets/Icons/pqPickCenter.svg"), tr( "MNU_CHANGINGROTATIONPOINT_VIEW" ) );
105   pickCenterAction->setCheckable(true);
106   pqRenderViewSelectionReaction* selectionReaction = new pqRenderViewSelectionReaction(
107     pickCenterAction, renderView, pqRenderViewSelectionReaction::SELECT_CUSTOM_BOX);
108
109   QObject::connect(selectionReaction,
110     QOverload<int, int, int, int>::of(&pqRenderViewSelectionReaction::selectedCustomBox), this,
111     &SPV3D_ViewWindow::pickCenterOfRotation);
112   //
113   mySelection = new SPV3D_CADSelection(this,renderView,SPV3D_CADSelection::SELECT_SOLIDS);
114   QAction *selectionAction =  toolMgr()->toolBar(myToolBar)->addAction(SUIT_Session::session()->resourceMgr()->loadPixmap( "VTKViewer", tr( "ICON_SVTK_PRESELECTION_STANDARD" ) ), tr( "MNU_SVTK_PRESELECTION_STANDARD" ) );
115   selectionAction->setCheckable(true);
116   QObject::connect(selectionAction, &QAction::toggled, this, &SPV3D_ViewWindow::goSelect);
117 }
118
119 void SPV3D_ViewWindow::goSelect(bool val)
120 {
121   if(val)
122     {
123       pqView* activeView(myModel->getView());
124       if (!activeView)
125       {
126         return;
127       }
128       for(const auto& elt : myPrs)
129       {
130         pqPipelineSource *geometrySource = elt.second->GetSourceProducer();
131         if(geometrySource)
132         {
133           vtkSMProxy* repr = activeView->getViewProxy()->FindRepresentation(
134             geometrySource->getSourceProxy(), 0);
135           repr->InvokeCommand("Reset");
136         }
137       }
138       activeView->forceRender();
139       activeView->render();
140       activeView->resetDisplay();
141     }
142   mySelection->actionTriggered(val);
143 }
144
145 //-----------------------------------------------------------------------------
146 void SPV3D_ViewWindow::pickCenterOfRotation(int posx, int posy)
147 {
148   pqView *view(myModel->getView());
149   pqRenderView *renderView(qobject_cast<pqRenderView *>(view));
150   if (!renderView)
151     return;
152
153   // Taken from vtkSMRenderViewProxy::ConvertDisplayToPointOnSurface
154   // TODO : we can use this function directly if we make a simple correction in ParaView :
155   // replace the vtkSMPVRepresentationProxy::SafeDownCast(...) by
156   // vtkSMRepresentationProxy::SafeDownCast(...), like done bellow
157   int region[4] = { posx, posy, posx, posy };
158   vtkNew<vtkCollection> representations;
159   vtkNew<vtkCollection> sources;
160
161   vtkSMRenderViewProxy* renderViewProxy = renderView->getRenderViewProxy();
162   renderViewProxy->SelectSurfaceCells(region, representations, sources, false);
163
164   // If a point has been selected
165   if (representations->GetNumberOfItems() > 0 && sources->GetNumberOfItems() > 0)
166   {
167     vtkSMRepresentationProxy* rep =
168       vtkSMRepresentationProxy::SafeDownCast(representations->GetItemAsObject(0));
169     vtkSMProxy* input = vtkSMPropertyHelper(rep, "Input").GetAsProxy(0);
170     vtkSMSourceProxy* selection = vtkSMSourceProxy::SafeDownCast(sources->GetItemAsObject(0));
171
172     // Setup a ray that starts at the center of the camera and ends
173     // at the end of the scene
174     double nearDisplayPoint[3] = { (double)posx, (double)posy, 0.0 };
175     double farDisplayPoint[3] = { (double)posx, (double)posy, 1.0 };
176     double farLinePoint[3] = { 0.0, 0.0, 0.0 };
177     double nearLinePoint[3] = { 0.0, 0.0, 0.0 };
178
179     vtkRenderer* renderer = renderViewProxy->GetRenderer();
180
181     // Compute the near ray point
182     renderer->SetDisplayPoint(nearDisplayPoint);
183     renderer->DisplayToWorld();
184     const double* world = renderer->GetWorldPoint();
185     for (int i = 0; i < 3; i++)
186     {
187       nearLinePoint[i] = world[i] / world[3];
188     }
189
190     // Compute the far ray point
191     renderer->SetDisplayPoint(farDisplayPoint);
192     renderer->DisplayToWorld();
193     world = renderer->GetWorldPoint();
194     for (int i = 0; i < 3; i++)
195     {
196       farLinePoint[i] = world[i] / world[3];
197     }
198
199     // Compute the intersection of the ray with the mesh
200     vtkSMProxyManager* proxyManager = vtkSMProxyManager::GetProxyManager();
201     vtkSMSessionProxyManager* sessionProxyManager = proxyManager->GetActiveSessionProxyManager();
202     vtkSMProxy* pickingHelper = sessionProxyManager->NewProxy("misc", "PickingHelper");
203
204     vtkSMPropertyHelper(pickingHelper, "Input").Set(input);
205     vtkSMPropertyHelper(pickingHelper, "Selection").Set(selection);
206     vtkSMPropertyHelper(pickingHelper, "PointA").Set(nearLinePoint, 3);
207     vtkSMPropertyHelper(pickingHelper, "PointB").Set(farLinePoint, 3);
208     vtkSMPropertyHelper(pickingHelper, "SnapOnMeshPoint").Set(false);
209     pickingHelper->UpdateVTKObjects();
210     pickingHelper->UpdateProperty("Update", 1);
211
212     double center[3] = { 0.0, 0.0, 0.0 };
213     vtkSMPropertyHelper(pickingHelper, "Intersection").UpdateValueFromServer();
214     vtkSMPropertyHelper(pickingHelper, "Intersection").Get(center, 3);
215     pickingHelper->Delete();
216
217     // Update the camera
218     vtkSMRenderViewProxy* renderViewProxy = renderView->getRenderViewProxy();
219     vtkSMPropertyHelper(renderViewProxy, "CenterOfRotation").Set(center, 3);
220     vtkSMPropertyHelper(renderViewProxy, "CameraFocalPoint").Set(center, 3);
221     renderViewProxy->UpdateVTKObjects();
222     renderView->render();
223   }
224 }
225
226 void SPV3D_ViewWindow::showCenterAxes(bool show_axes)
227 {
228   if(!myModel)
229     return;
230   pqRenderView* renderView = qobject_cast<pqRenderView*>(myModel->getView());
231   if (!renderView)
232     return;
233   renderView->setCenterAxesVisibility(show_axes);
234   renderView->render();
235 }
236
237 SPV3D_Prs *SPV3D_ViewWindow::findOrCreatePrs( const char* entry )
238 {
239   std::string entryCpp( entry );
240   SPV3D_Prs *prsOut( new SPV3D_Prs( entry, this ) );
241   for(auto& prs : myPrs)
242   {
243     if(entryCpp == prs.first)
244     {
245       prsOut->SetPVRenderInfo( prs.second.get() );
246       return prsOut;
247     }
248   }
249   std::unique_ptr<SPV3D_EXPORTSPV3DData> data(new SPV3D_EXPORTSPV3DData);
250   prsOut->SetPVRenderInfo( data.get() );
251   std::pair<std::string, std::unique_ptr<SPV3D_EXPORTSPV3DData> > p(entryCpp,std::move(data));
252   myPrs.emplace_back( std::move(p) );
253   return prsOut;
254 }
255
256 SPV3D_EXPORTSPV3DData *SPV3D_ViewWindow::isEntryAlreadyExist( const char* entry ) const
257 {
258   std::string entryCpp( entry );
259   for(const auto& prs : myPrs)
260   {
261     if(entryCpp == prs.first)
262       return prs.second.get();
263   }
264   return nullptr;
265 }
266
267 /*!
268   Destructor
269 */
270 SPV3D_ViewWindow::~SPV3D_ViewWindow()
271 {
272 }
273
274 bool SPV3D_ViewWindow::isVisible(const Handle(SALOME_InteractiveObject)& theIObject)
275 {
276   std::string entryCpp( theIObject->getEntry() );
277   for(auto& prs : myPrs)
278   {
279     if(entryCpp == prs.first )
280       return prs.second->IsVisible();
281   }
282   return false;
283 }
284
285 /*!
286   Display object
287   \param theIO - object
288   \param theImmediatly - update viewer
289 */
290 void SPV3D_ViewWindow::Display(const Handle(SALOME_InteractiveObject)& /*theIO*/,
291                               bool /*theImmediatly*/) 
292 {
293 }
294
295 /*!
296   Erase object
297   \param theIO - object
298   \param theImmediatly - update viewer
299 */
300 void SPV3D_ViewWindow::Erase(const Handle(SALOME_InteractiveObject)& /*theIO*/,
301                             bool /*theImmediatly*/)
302 {
303 }
304
305 /*!
306   Display only passed object
307   \param theIO - object
308 */
309 void SPV3D_ViewWindow::DisplayOnly(const Handle(SALOME_InteractiveObject)& /*theIO*/)
310 {
311 }
312
313
314 /*!
315   Display all objects in view
316 */
317 void SPV3D_ViewWindow::DisplayAll() 
318 {
319 }
320
321 /*!
322   Erase all objects in view
323 */
324 void SPV3D_ViewWindow::EraseAll() 
325 {
326   for(auto& prs : myPrs)
327   {
328     prs.second->Hide();
329   }
330   if(myModel)
331     myModel->render();
332 }
333
334 /*!
335   Updates current viewer
336 */
337 void SPV3D_ViewWindow::Repaint(bool )//(bool theUpdateTrihedron)
338 {
339   if(myModel)
340     myModel->render();
341 }
342
343 /*!
344   Enables/disables selection.
345   \param theEnable if true - selection will be enabled
346 */
347 void SPV3D_ViewWindow::SetSelectionEnabled( bool /*theEnable*/ )
348 {
349 }
350
351 /*!
352   Emits key pressed
353 */
354 void SPV3D_ViewWindow::onKeyPressed(QKeyEvent* event)
355 {
356   emit keyPressed( this, event );
357 }
358
359 /*!
360   Emits key released
361 */
362 void SPV3D_ViewWindow::onKeyReleased(QKeyEvent* event)
363 {
364   emit keyReleased( this, event );
365 }
366
367 /*!
368   Emits mouse pressed
369 */
370 void SPV3D_ViewWindow::onMousePressed(QMouseEvent* event)
371 {
372   emit mousePressed(this, event);
373 }
374
375 /*!
376   Emits mouse released
377 */
378 void SPV3D_ViewWindow::onMouseReleased(QMouseEvent* event)
379 {
380   emit mouseReleased( this, event );
381 }
382
383 /*!
384   Emits mouse moving
385 */
386 void SPV3D_ViewWindow::onMouseMoving(QMouseEvent* event)
387 {
388   emit mouseMoving( this, event );
389 }
390
391 /*!
392   Emits mouse double clicked
393 */
394 void SPV3D_ViewWindow::onMouseDoubleClicked( QMouseEvent* event )
395 {
396   emit mouseDoubleClicked( this, event );
397 }
398
399 /*!
400   Custom show event handler
401 */
402 void SPV3D_ViewWindow::showEvent( QShowEvent * theEvent ) 
403 {
404   emit Show( theEvent );
405 }
406
407 /*!
408   Custom hide event handler
409 */
410 void SPV3D_ViewWindow::hideEvent( QHideEvent * theEvent ) 
411 {
412   emit Hide( theEvent );
413 }