1 // Copyright (C) 2015-2023 CEA/DEN, EDF R&D, OPEN CASCADE
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
21 #include "OCCViewer_LightSourceDlg.h"
22 #include "OCCViewer.h"
23 #include "OCCViewer_ViewWindow.h"
24 #include "OCCViewer_ViewModel.h"
27 #include <SUIT_Session.h>
28 #include <QtxDoubleSpinBox.h>
29 #include <QtxColorButton.h>
33 #include <QVBoxLayout>
34 #include <QHBoxLayout>
36 #include <QPushButton>
38 #include <QStackedLayout>
39 #include <QRadioButton>
42 \class OCCViewer_LightSourceDlg
43 \brief Dialog allowing to assign parameters of light source
48 \param view - parent widget
51 OCCViewer_LightSourceDlg::OCCViewer_LightSourceDlg( OCCViewer_ViewWindow* view, OCCViewer_Viewer* model )
55 setObjectName( "OCCViewer_LightSourceDlg" );
56 setWindowTitle( tr( "LIGHT_SOURCE" ) );
59 setAttribute( Qt::WA_DeleteOnClose, true );
61 // Create layout for this dialog
62 QVBoxLayout* dlglayout = new QVBoxLayout( this );
63 dlglayout->setSpacing( 6 ); dlglayout->setMargin( 11 );
65 QGroupBox* typeGroup = new QGroupBox( tr( "TYPE" ), this );
66 QHBoxLayout* typeLayout = new QHBoxLayout( typeGroup );
67 typeLayout->setSpacing( 6 ); typeLayout->setMargin( 11 );
69 myDirType = new QRadioButton( tr( "DIRECTIONAL" ), typeGroup );
70 myPosType = new QRadioButton( tr( "POSITIONAL" ), typeGroup );
72 typeLayout->addWidget( myDirType );
73 typeLayout->addWidget( myPosType );
75 myStackedLayout = new QStackedLayout();
77 const double min = -RealLast();
78 const double max = RealLast();
80 /********************** Directional light **********************/
81 /* Controls for directional light:
82 Dx, Dy, Dz - direction
83 Headlight - headlight flag
84 Color - the color of a light source
87 QWidget* dirWidget = new QWidget( this );
88 QVBoxLayout* dirLayout = new QVBoxLayout( dirWidget );
89 dirLayout->setSpacing( 6 ); dirLayout->setMargin( 11 );
91 // Create "Direction" group
93 const double dir_step = 0.1;
95 QGroupBox* dirCoordGroup = new QGroupBox( tr( "DIRECTION" ), this );
96 QHBoxLayout* dirCoordLayout = new QHBoxLayout( dirCoordGroup );
97 dirCoordLayout->setSpacing( 6 ); dirCoordLayout->setMargin( 11 );
99 QLabel* dxLabel = new QLabel( tr("Dx:"), dirCoordGroup );
100 myDx = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
101 myDx->setValue( 0.0 );
102 myDx->setMinimumWidth( 80 );
104 QLabel* dyLabel = new QLabel( tr("Dy:"), dirCoordGroup );
105 myDy = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
106 myDy->setValue( 0.0 );
107 myDy->setMinimumWidth( 80 );
109 QLabel* dzLabel = new QLabel( tr("Dz:"), dirCoordGroup );
110 myDz = new QtxDoubleSpinBox( min, max, dir_step, dirCoordGroup );
111 myDz->setValue( -1.0 );
112 myDz->setMinimumWidth( 80 );
114 dirCoordLayout->addWidget( dxLabel );
115 dirCoordLayout->addWidget( myDx );
116 dirCoordLayout->addWidget( dyLabel );
117 dirCoordLayout->addWidget( myDy );
118 dirCoordLayout->addWidget( dzLabel );
119 dirCoordLayout->addWidget( myDz );
121 // Create "Parameters" group
123 QGroupBox* dirParamGroup = new QGroupBox( dirWidget );
124 QHBoxLayout* dirParamLayout = new QHBoxLayout( dirParamGroup );
125 dirParamLayout->setSpacing( 6 ); dirParamLayout->setMargin( 11 );
127 myDirHeadLight = new QCheckBox( tr("HEADLIGHT"), dirParamGroup );
128 myDirHeadLight->setChecked( false );
130 QLabel* aColorLabel = new QLabel( tr( "COLOR" ), dirParamGroup );
131 myDirColor = new QtxColorButton( dirParamGroup );
132 myDirColor->setColor( Qt::white );
134 dirParamLayout->addWidget( myDirHeadLight );
135 dirParamLayout->addWidget( aColorLabel );
136 dirParamLayout->addWidget( myDirColor );
137 dirParamLayout->addStretch();
139 dirLayout->addWidget( dirCoordGroup );
140 dirLayout->addWidget( dirParamGroup );
142 /********************** Positional light **********************/
143 /* Controls for positional light:
145 Headlight - headlight flag
146 Color - the color of a light source
149 QWidget* posWidget = new QWidget( this );
150 QVBoxLayout* posLayout = new QVBoxLayout( posWidget );
151 posLayout->setSpacing( 6 ); posLayout->setMargin( 11 );
153 // Create "Position" group
155 const double pos_step = 1.0;
157 QGroupBox* posCoordGroup = new QGroupBox( tr( "POSITION" ), posWidget );
158 QHBoxLayout* posCoordLayout = new QHBoxLayout( posCoordGroup );
159 posCoordLayout->setSpacing( 6 ); posCoordLayout->setMargin( 11 );
161 QLabel* xLabel = new QLabel( tr("X:"), posCoordGroup );
162 myX = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
163 myX->setValue( 0.0 );
164 myX->setMinimumWidth( 80 );
166 QLabel* yLabel = new QLabel( tr("Y:"), posCoordGroup );
167 myY = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
168 myY->setValue( 0.0 );
169 myY->setMinimumWidth( 80 );
171 QLabel* zLabel = new QLabel( tr("Z:"), posCoordGroup );
172 myZ = new QtxDoubleSpinBox( min, max, pos_step, posCoordGroup );
173 myZ->setValue( 0.0 );
174 myZ->setMinimumWidth( 80 );
176 posCoordLayout->addWidget( xLabel );
177 posCoordLayout->addWidget( myX );
178 posCoordLayout->addWidget( yLabel );
179 posCoordLayout->addWidget( myY );
180 posCoordLayout->addWidget( zLabel );
181 posCoordLayout->addWidget( myZ );
183 // Create "Parameters" group
185 QGroupBox* posParamGroup = new QGroupBox( posWidget );
186 QHBoxLayout* posParamLayout = new QHBoxLayout( posParamGroup );
187 posParamLayout->setSpacing( 6 ); posParamLayout->setMargin( 11 );
189 myPosHeadLight = new QCheckBox( tr("HEADLIGHT"), posParamGroup );
190 myPosHeadLight->setChecked( false );
192 aColorLabel = new QLabel( tr( "COLOR" ), posParamGroup );
193 myPosColor = new QtxColorButton( posParamGroup );
194 myPosColor->setColor( Qt::white );
196 posParamLayout->addWidget( myPosHeadLight );
197 posParamLayout->addWidget( aColorLabel );
198 posParamLayout->addWidget( myPosColor );
199 posParamLayout->addStretch();
201 posLayout->addWidget( posCoordGroup );
202 posLayout->addWidget( posParamGroup );
204 // add widgets in the stacked layout
205 myStackedLayout->addWidget( dirWidget );
206 myStackedLayout->addWidget( posWidget );
208 // Create "Buttons" group
210 QGroupBox* buttonGroup = new QGroupBox( this );
211 QHBoxLayout* buttonLayout = new QHBoxLayout( buttonGroup );
212 buttonLayout->setSpacing( 6 );
213 buttonLayout->setMargin( 11 );
215 QPushButton* okButton = new QPushButton( tr( "BUT_APPLY_AND_CLOSE" ), buttonGroup );
216 okButton->setDefault( true );
217 QPushButton* defaultButton = new QPushButton( tr( "BUT_DEFAULT" ), buttonGroup );
218 QPushButton* closeButton = new QPushButton( tr( "BUT_CLOSE" ), buttonGroup );
219 QPushButton* helpButton = new QPushButton( tr( "GEOM_BUT_HELP" ), buttonGroup );
221 buttonLayout->addWidget( okButton );
222 buttonLayout->addWidget( defaultButton );
223 buttonLayout->addStretch();
224 buttonLayout->addWidget( closeButton );
225 buttonLayout->addWidget( helpButton );
227 dlglayout->addWidget( typeGroup );
228 dlglayout->addLayout( myStackedLayout );
229 dlglayout->addWidget( buttonGroup );
231 this->setLayout( dlglayout );
237 // Signals and slots connections
238 connect( myDirType, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChanged() ) );
239 connect( myPosType, SIGNAL( clicked( bool ) ), this, SLOT( onTypeChanged() ) );
241 connect( myDx, SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
242 connect( myDy, SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
243 connect( myDz, SIGNAL( valueChanged( double ) ), this, SLOT( onDirChanged() ) );
244 connect( myDirHeadLight, SIGNAL( clicked( bool ) ), this, SLOT( onDirChanged() ) );
245 connect( myDirColor, SIGNAL( changed( QColor ) ), this, SLOT( onDirChanged() ) );
247 connect( myX, SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
248 connect( myY, SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
249 connect( myZ, SIGNAL( valueChanged( double ) ), this, SLOT( onPosChanged() ) );
250 connect( myPosHeadLight, SIGNAL( clicked( bool ) ), this, SLOT( onPosChanged() ) );
251 connect( myPosColor, SIGNAL( changed( QColor ) ), this, SLOT( onPosChanged() ) );
253 connect( okButton, SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
254 connect( defaultButton, SIGNAL( clicked() ), this, SLOT( ClickOnDefault() ) );
255 connect( closeButton, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) );
256 connect( helpButton, SIGNAL( clicked() ), this, SLOT( ClickOnHelp() ) );
258 resize( minimumSizeHint() );
264 OCCViewer_LightSourceDlg::~OCCViewer_LightSourceDlg()
266 ( myInType == V3d_DIRECTIONAL ) ? myModel->getViewer3d()->DelLight( myPosLight ) :
267 myModel->getViewer3d()->DelLight( myDirLight );
270 QString OCCViewer_LightSourceDlg::getName()
272 // return the name of object
273 return QString( "OCCViewer_LightSourceDlg" );
277 Initialization of initial values of widgets
279 void OCCViewer_LightSourceDlg::initParam( bool theIsDefault )
281 Handle(V3d_Light) aLight;
282 myModel->getViewer3d()->InitDefinedLights();
283 while ( myModel->getViewer3d()->MoreDefinedLights() )
285 aLight = myModel->getViewer3d()->DefinedLight();
286 if ( aLight->Type() == V3d_DIRECTIONAL ) {
287 myDirLight = Handle(V3d_DirectionalLight)::DownCast( aLight );
288 myPosLight = new V3d_PositionalLight( gp_Pnt(0, 0, 0) );
289 myModel->getViewer3d()->AddLight( myPosLight );
290 myDirType->setChecked( true );
291 myStackedLayout->setCurrentIndex(0);
294 if ( aLight->Type() == V3d_POSITIONAL ) {
295 myPosLight = Handle(V3d_PositionalLight)::DownCast( aLight );
296 myDirLight = new V3d_DirectionalLight();
297 myModel->getViewer3d()->AddLight( myDirLight );
298 myPosType->setChecked( true );
299 myStackedLayout->setCurrentIndex(1);
302 myModel->getViewer3d()->NextDefinedLights();
305 double aX=0., aY=0., aZ=0.;
306 Quantity_Color aColor = aLight->Color();
307 if( myDirType->isChecked() ) {
308 myDirColor->setColor( OCCViewer::color( aColor ) );
309 myDirLight->Direction( aX, aY, aZ );
310 myDx->setValue( aX );
311 myDy->setValue( aY );
312 myDz->setValue( aZ );
313 myDirHeadLight->setChecked( myDirLight->Headlight() );
315 else if( myPosType->isChecked() ) {
316 myPosColor->setColor( OCCViewer::color( aColor ) );
317 myPosLight->Position( aX, aY, aZ );
321 myPosHeadLight->setChecked( myPosLight->Headlight() );
324 if ( !theIsDefault ) {
325 myInX = aX; myInY = aY; myInZ = aZ;
327 myInHeadLight = aLight->Headlight();
328 myInType = aLight->Type();
333 SLOT: called on type of light source changed
335 void OCCViewer_LightSourceDlg::onTypeChanged()
339 myStackedLayout->setCurrentIndex( myPosType->isChecked() );
340 if( myPosType->isChecked() ) {
341 myModel->getViewer3d()->SetLightOff( myDirLight );
344 else if( myDirType->isChecked() ) {
345 myModel->getViewer3d()->SetLightOff( myPosLight );
351 SLOT: called on value of directional light source changed
353 void OCCViewer_LightSourceDlg::onDirChanged()
357 myModel->getViewer3d()->SetLightOff( myDirLight );
358 if ( !( myDx->value() == 0 && myDy->value() == 0 && myDz->value() == 0 ) ) {
359 myDirLight->SetDirection( myDx->value(), myDy->value(), myDz->value() );
360 myDirLight->SetColor( OCCViewer::color( myDirColor->color() ) );
361 myDirLight->SetHeadlight( myDirHeadLight->isChecked() );
362 myModel->getViewer3d()->SetLightOn( myDirLight );
364 myModel->getViewer3d()->UpdateLights();
368 SLOT: called on value of positional light source changed
370 void OCCViewer_LightSourceDlg::onPosChanged()
374 myModel->getViewer3d()->SetLightOff( myPosLight );
375 myPosLight->SetPosition( myX->value(), myY->value(), myZ->value() );
376 myPosLight->SetColor( OCCViewer::color( myPosColor->color() ) );
377 myPosLight->SetHeadlight( myPosHeadLight->isChecked() );
378 myModel->getViewer3d()->SetLightOn( myPosLight );
379 myModel->getViewer3d()->UpdateLights();
383 \brief SLOT on "Apply and Close" button click: sets current light source and closes dialog
385 void OCCViewer_LightSourceDlg::ClickOnOk()
387 // need save a current type for deleting other light when dialog will be closed
388 myInType = myDirType->isChecked() ? V3d_DIRECTIONAL : V3d_POSITIONAL;
393 \brief SLOT on "Default" button click: sets default light source
395 void OCCViewer_LightSourceDlg::ClickOnDefault()
398 myModel->setDefaultLights();
400 myModel->getViewer3d()->UpdateLights();
405 \brief SLOT on "Close" button click: sets initial light source and closes dialog
407 void OCCViewer_LightSourceDlg::ClickOnClose()
409 if( myInType == V3d_DIRECTIONAL ) {
410 myDirLight->SetDirection( myInX, myInY, myInZ );
411 myDirLight->SetColor( myInColor );
412 myDirLight->SetHeadlight( myInHeadLight );
413 myModel->getViewer3d()->SetLightOn( myDirLight );
416 myPosLight->SetPosition( myInX, myInY, myInZ );
417 myPosLight->SetColor( myInColor );
418 myPosLight->SetHeadlight( myInHeadLight );
419 myModel->getViewer3d()->SetLightOn( myPosLight );
425 \brief SLOT on help button click: opens a help page
427 void OCCViewer_LightSourceDlg::ClickOnHelp()
429 SUIT_Application* app = SUIT_Session::session()->activeApplication();
431 app->onHelpContextModule( "GUI", "occ_3d_viewer.html", "light-source" );