]> SALOME platform Git repositories - modules/gui.git/blob - src/OCCViewer/OCCViewer_LightSourceDlg.cxx
Salome HOME
Copyright update 2020
[modules/gui.git] / src / OCCViewer / OCCViewer_LightSourceDlg.cxx
1 // Copyright (C) 2015-2020  CEA/DEN, EDF R&D, OPEN CASCADE
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 // internal includes
21 #include "OCCViewer_LightSourceDlg.h"
22 #include "OCCViewer.h"
23 #include "OCCViewer_ViewWindow.h"
24 #include "OCCViewer_ViewModel.h"
25
26 // GUI includes
27 #include <SUIT_Session.h>
28 #include <QtxDoubleSpinBox.h>
29 #include <QtxColorButton.h>
30
31 // Qt includes
32 #include <QGroupBox>
33 #include <QVBoxLayout>
34 #include <QHBoxLayout>
35 #include <QLabel>
36 #include <QPushButton>
37 #include <QCheckBox>
38 #include <QStackedLayout>
39 #include <QRadioButton>
40
41 /*!
42   \class OCCViewer_LightSourceDlg
43   \brief Dialog allowing to assign parameters of light source
44 */
45
46 /*!
47   \brief Constructor
48   \param view - parent widget
49   \param model - viewer
50 */
51 OCCViewer_LightSourceDlg::OCCViewer_LightSourceDlg( OCCViewer_ViewWindow* view, OCCViewer_Viewer* model )
52   :QDialog( view ),
53   myModel( model )
54 {
55   setObjectName( "OCCViewer_LightSourceDlg" );
56   setWindowTitle( tr( "LIGHT_SOURCE" ) );
57   setModal( false );
58
59   setAttribute( Qt::WA_DeleteOnClose, true );
60
61   // Create layout for this dialog
62   QVBoxLayout* dlglayout = new QVBoxLayout( this );
63   dlglayout->setSpacing( 6 ); dlglayout->setMargin( 11 );
64
65   QGroupBox* typeGroup = new QGroupBox( tr( "TYPE" ), this );
66   QHBoxLayout* typeLayout = new QHBoxLayout( typeGroup );
67   typeLayout->setSpacing( 6 ); typeLayout->setMargin( 11 );
68
69   myDirType = new QRadioButton( tr( "DIRECTIONAL" ), typeGroup );
70   myPosType = new QRadioButton( tr( "POSITIONAL" ), typeGroup );
71
72   typeLayout->addWidget( myDirType );
73   typeLayout->addWidget( myPosType );
74
75   myStackedLayout = new QStackedLayout();
76
77   const double min = -RealLast();
78   const double max = RealLast();
79   const int precision = 3;
80
81   /**********************   Directional light   **********************/
82   /* Controls for directional light:
83      Dx, Dy, Dz - direction
84      Headlight - headlight flag
85      Color - the color of a light source
86   */
87
88   QWidget* dirWidget = new QWidget( this );
89   QVBoxLayout* dirLayout = new QVBoxLayout( dirWidget );
90   dirLayout->setSpacing( 6 ); dirLayout->setMargin( 11 );
91
92   // Create "Direction" group
93
94   const double dir_step = 0.1;
95
96   QGroupBox* dirCoordGroup = new QGroupBox( tr( "DIRECTION" ), this );
97   QHBoxLayout* dirCoordLayout = new QHBoxLayout( dirCoordGroup );
98   dirCoordLayout->setSpacing( 6 ); dirCoordLayout->setMargin( 11 );
99
100   QLabel* dxLabel = new QLabel( tr("Dx:"), dirCoordGroup );
101   myDx = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
102   myDx->setValue( 0.0 );
103   myDx->setMinimumWidth( 80 );
104
105   QLabel* dyLabel = new QLabel( tr("Dy:"), dirCoordGroup );
106   myDy = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
107   myDy->setValue( 0.0 );
108   myDy->setMinimumWidth( 80 );
109
110   QLabel* dzLabel = new QLabel( tr("Dz:"), dirCoordGroup );
111   myDz = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
112   myDz->setValue( -1.0 );
113   myDz->setMinimumWidth( 80 );
114
115   dirCoordLayout->addWidget( dxLabel );
116   dirCoordLayout->addWidget( myDx );
117   dirCoordLayout->addWidget( dyLabel );
118   dirCoordLayout->addWidget( myDy );
119   dirCoordLayout->addWidget( dzLabel );
120   dirCoordLayout->addWidget( myDz );
121
122   // Create "Parameters" group
123
124   QGroupBox* dirParamGroup = new QGroupBox( dirWidget );
125   QHBoxLayout* dirParamLayout = new QHBoxLayout( dirParamGroup );
126   dirParamLayout->setSpacing( 6 ); dirParamLayout->setMargin( 11 );
127
128   myDirHeadLight = new QCheckBox( tr("HEADLIGHT"), dirParamGroup );
129   myDirHeadLight->setChecked( false );
130
131   QLabel* aColorLabel = new QLabel( tr( "COLOR" ), dirParamGroup );
132   myDirColor = new QtxColorButton( dirParamGroup );
133   myDirColor->setColor( Qt::white );
134
135   dirParamLayout->addWidget( myDirHeadLight );
136   dirParamLayout->addWidget( aColorLabel );
137   dirParamLayout->addWidget( myDirColor );
138   dirParamLayout->addStretch();
139
140   dirLayout->addWidget( dirCoordGroup );
141   dirLayout->addWidget( dirParamGroup );
142
143   /**********************   Positional light   **********************/
144   /* Controls for positional light:
145      X, Y, Z - position
146      Headlight - headlight flag
147      Color - the color of a light source
148   */
149
150   QWidget* posWidget = new QWidget( this );
151   QVBoxLayout* posLayout = new QVBoxLayout( posWidget );
152   posLayout->setSpacing( 6 ); posLayout->setMargin( 11 );
153
154   // Create "Position" group
155
156   const double pos_step = 1.0;
157
158   QGroupBox* posCoordGroup = new QGroupBox( tr( "POSITION" ), posWidget );
159   QHBoxLayout* posCoordLayout = new QHBoxLayout( posCoordGroup );
160   posCoordLayout->setSpacing( 6 ); posCoordLayout->setMargin( 11 );
161
162   QLabel* xLabel = new QLabel( tr("X:"), posCoordGroup );
163   myX = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
164   myX->setValue( 0.0 );
165   myX->setMinimumWidth( 80 );
166
167   QLabel* yLabel = new QLabel( tr("Y:"), posCoordGroup );
168   myY = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
169   myY->setValue( 0.0 );
170   myY->setMinimumWidth( 80 );
171
172   QLabel* zLabel = new QLabel( tr("Z:"), posCoordGroup );
173   myZ = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
174   myZ->setValue( 0.0 );
175   myZ->setMinimumWidth( 80 );
176
177   posCoordLayout->addWidget( xLabel );
178   posCoordLayout->addWidget( myX );
179   posCoordLayout->addWidget( yLabel );
180   posCoordLayout->addWidget( myY );
181   posCoordLayout->addWidget( zLabel );
182   posCoordLayout->addWidget( myZ );
183
184   // Create "Parameters" group
185
186   QGroupBox* posParamGroup = new QGroupBox( posWidget );
187   QHBoxLayout* posParamLayout = new QHBoxLayout( posParamGroup );
188   posParamLayout->setSpacing( 6 ); posParamLayout->setMargin( 11 );
189
190   myPosHeadLight = new QCheckBox( tr("HEADLIGHT"), posParamGroup );
191   myPosHeadLight->setChecked( false );
192
193   aColorLabel = new QLabel( tr( "COLOR" ), posParamGroup );
194   myPosColor = new QtxColorButton( posParamGroup );
195   myPosColor->setColor( Qt::white );
196
197   posParamLayout->addWidget( myPosHeadLight );
198   posParamLayout->addWidget( aColorLabel );
199   posParamLayout->addWidget( myPosColor );
200   posParamLayout->addStretch();
201
202   posLayout->addWidget( posCoordGroup );
203   posLayout->addWidget( posParamGroup );
204
205   // add widgets in the stacked layout
206   myStackedLayout->addWidget( dirWidget );
207   myStackedLayout->addWidget( posWidget );
208
209   // Create "Buttons" group
210
211   QGroupBox* buttonGroup = new QGroupBox( this );
212   QHBoxLayout* buttonLayout = new QHBoxLayout( buttonGroup );
213   buttonLayout->setSpacing( 6 );
214   buttonLayout->setMargin( 11 );
215
216   QPushButton* okButton = new QPushButton( tr( "BUT_APPLY_AND_CLOSE" ), buttonGroup );
217   okButton->setDefault( true );
218   QPushButton* defaultButton = new QPushButton( tr( "BUT_DEFAULT" ), buttonGroup );
219   QPushButton* closeButton = new QPushButton( tr( "BUT_CLOSE" ), buttonGroup );
220   QPushButton* helpButton = new QPushButton( tr( "GEOM_BUT_HELP" ), buttonGroup );
221
222   buttonLayout->addWidget( okButton );
223   buttonLayout->addWidget( defaultButton );
224   buttonLayout->addStretch();
225   buttonLayout->addWidget( closeButton );
226   buttonLayout->addWidget( helpButton );
227
228   dlglayout->addWidget( typeGroup );
229   dlglayout->addLayout( myStackedLayout );
230   dlglayout->addWidget( buttonGroup );
231
232   this->setLayout( dlglayout );
233
234   // Initializations
235   initParam();
236   isBusy = false;
237
238   // Signals and slots connections
239   connect( myDirType,      SIGNAL( clicked( bool ) ),        this, SLOT( onTypeChanged() ) );
240   connect( myPosType,      SIGNAL( clicked( bool ) ),        this, SLOT( onTypeChanged() ) );
241
242   connect( myDx,           SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
243   connect( myDy,           SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
244   connect( myDz,           SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
245   connect( myDirHeadLight, SIGNAL( clicked( bool ) ),        this, SLOT( onDirChanged() ) );
246   connect( myDirColor,     SIGNAL( changed( QColor ) ),      this, SLOT( onDirChanged() ) );
247
248   connect( myX,            SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
249   connect( myY,            SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
250   connect( myZ,            SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
251   connect( myPosHeadLight, SIGNAL( clicked( bool ) ),        this, SLOT( onPosChanged() ) );
252   connect( myPosColor,     SIGNAL( changed( QColor ) ),      this, SLOT( onPosChanged() ) );
253
254   connect( okButton,       SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
255   connect( defaultButton,  SIGNAL( clicked() ), this, SLOT( ClickOnDefault() ) );
256   connect( closeButton,    SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) );
257   connect( helpButton,     SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) );
258
259   resize( minimumSizeHint() );
260 }
261
262 /*!
263   \brief Destructor
264 */
265 OCCViewer_LightSourceDlg::~OCCViewer_LightSourceDlg()
266 {
267   ( myInType == V3d_DIRECTIONAL ) ? myModel->getViewer3d()->DelLight( myPosLight ) :
268                                             myModel->getViewer3d()->DelLight( myDirLight );
269 }
270
271 QString OCCViewer_LightSourceDlg::getName()
272 {
273   // return the name of object
274   return QString( "OCCViewer_LightSourceDlg" );
275 }
276
277 /*!
278   Initialization of initial values of widgets
279 */
280 void OCCViewer_LightSourceDlg::initParam( bool theIsDefault )
281 {
282   Handle(V3d_Light) aLight;
283   myModel->getViewer3d()->InitDefinedLights();
284   while ( myModel->getViewer3d()->MoreDefinedLights() )
285   {
286     aLight = myModel->getViewer3d()->DefinedLight();
287     if ( aLight->Type() == V3d_DIRECTIONAL ) {
288       myDirLight = Handle(V3d_DirectionalLight)::DownCast( aLight );
289       myPosLight = new V3d_PositionalLight( gp_Pnt(0, 0, 0) );
290       myModel->getViewer3d()->AddLight( myPosLight );
291       myDirType->setChecked( true );
292       myStackedLayout->setCurrentIndex(0);
293       break;
294     }
295     if ( aLight->Type() == V3d_POSITIONAL ) {
296       myPosLight = Handle(V3d_PositionalLight)::DownCast( aLight );
297       myDirLight = new V3d_DirectionalLight();
298       myModel->getViewer3d()->AddLight( myDirLight );
299       myPosType->setChecked( true );
300       myStackedLayout->setCurrentIndex(1);
301       break;
302     }
303     myModel->getViewer3d()->NextDefinedLights();
304   }
305
306   double aX, aY, aZ;
307   Quantity_Color aColor = aLight->Color();
308   if( myDirType->isChecked() ) {
309     myDirColor->setColor( OCCViewer::color( aColor ) );
310     myDirLight->Direction( aX, aY, aZ );
311     myDx->setValue( aX );
312     myDy->setValue( aY );
313     myDz->setValue( aZ );
314     myDirHeadLight->setChecked( myDirLight->Headlight() );
315   }
316   else if( myPosType->isChecked() ) {
317     myPosColor->setColor( OCCViewer::color( aColor ) );
318     myPosLight->Position( aX, aY, aZ );
319     myX->setValue( aX );
320     myY->setValue( aY );
321     myZ->setValue( aZ );
322     myPosHeadLight->setChecked( myPosLight->Headlight() );
323   }
324
325   if ( !theIsDefault ) {
326     myInX = aX; myInY = aY; myInZ = aZ;
327     myInColor = aColor;
328     myInHeadLight = aLight->Headlight();
329     myInType = aLight->Type();
330   }
331 }
332
333 /*!
334   SLOT: called on type of light source changed
335 */
336 void OCCViewer_LightSourceDlg::onTypeChanged()
337 {
338   if( isBusy )
339     return;
340   myStackedLayout->setCurrentIndex( myPosType->isChecked() );
341   if( myPosType->isChecked() ) {
342     myModel->getViewer3d()->SetLightOff( myDirLight );
343     onPosChanged();
344   }
345   else if( myDirType->isChecked() ) {
346     myModel->getViewer3d()->SetLightOff( myPosLight );
347     onDirChanged();
348   }
349 }
350
351 /*!
352   SLOT: called on value of directional light source changed
353 */
354 void OCCViewer_LightSourceDlg::onDirChanged()
355 {
356   if( isBusy )
357     return;
358   myModel->getViewer3d()->SetLightOff( myDirLight );
359   if ( !( myDx->value() == 0 && myDy->value() == 0 && myDz->value() == 0 ) ) {
360     myDirLight->SetDirection( myDx->value(), myDy->value(), myDz->value() );
361     myDirLight->SetColor( OCCViewer::color( myDirColor->color() ) );
362     myDirLight->SetHeadlight( myDirHeadLight->isChecked() );
363     myModel->getViewer3d()->SetLightOn( myDirLight );
364   }
365   myModel->getViewer3d()->UpdateLights();
366 }
367
368 /*!
369   SLOT: called on value of positional light source changed
370 */
371 void OCCViewer_LightSourceDlg::onPosChanged()
372 {
373   if( isBusy )
374     return;
375   myModel->getViewer3d()->SetLightOff( myPosLight );
376   myPosLight->SetPosition( myX->value(), myY->value(), myZ->value() );
377   myPosLight->SetColor( OCCViewer::color( myPosColor->color() ) );
378   myPosLight->SetHeadlight( myPosHeadLight->isChecked() );
379   myModel->getViewer3d()->SetLightOn( myPosLight );
380   myModel->getViewer3d()->UpdateLights();
381 }
382
383 /*!
384   \brief SLOT on "Apply and Close" button click: sets current light source and closes dialog
385 */
386 void OCCViewer_LightSourceDlg::ClickOnOk()
387 {
388   // need save a current type for deleting other light when dialog will be closed
389   myInType = myDirType->isChecked() ? V3d_DIRECTIONAL : V3d_POSITIONAL;
390   close();
391 }
392
393 /*!
394   \brief SLOT on "Default" button click: sets default light source
395 */
396 void OCCViewer_LightSourceDlg::ClickOnDefault()
397 {
398   isBusy = true;
399   myModel->setDefaultLights();
400   initParam( true );
401   myModel->getViewer3d()->UpdateLights();
402   isBusy = false;
403 }
404
405 /*!
406   \brief SLOT on "Close" button click: sets initial light source and closes dialog
407 */
408 void OCCViewer_LightSourceDlg::ClickOnClose()
409 {
410   if( myInType == V3d_DIRECTIONAL ) {
411     myDirLight->SetDirection( myInX, myInY, myInZ );
412     myDirLight->SetColor( myInColor );
413     myDirLight->SetHeadlight( myInHeadLight );
414     myModel->getViewer3d()->SetLightOn( myDirLight );
415   }
416   else {
417     myPosLight->SetPosition( myInX, myInY, myInZ );
418     myPosLight->SetColor( myInColor );
419     myPosLight->SetHeadlight( myInHeadLight );
420     myModel->getViewer3d()->SetLightOn( myPosLight );
421   }
422   close();
423 }
424
425 /*!
426   \brief SLOT on help button click: opens a help page
427 */
428 void OCCViewer_LightSourceDlg::ClickOnHelp()
429 {
430   SUIT_Application* app = SUIT_Session::session()->activeApplication();
431   if ( app )
432     app->onHelpContextModule( "GUI", "occ_3d_viewer.html", "light-source" );
433 }