ATLAS Offline Software
Loading...
Searching...
No Matches
VP1CustomTourEditor.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class VP1CustomTourEditor //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: September 2008 //
12// //
14
17#include "ui_vp1customtoureditor.h"
18
25
26#include <Inventor/nodes/SoGroup.h>
27#include <Inventor/nodes/SoCamera.h>
28#include <Inventor/SbBox.h>
29
30#include <QAction>
31#include <QShortcut>
32#include <QCloseEvent>
33#include <QScrollBar>
34#include <QtCoreVersion>
35
36#include <iostream>
37
38//____________________________________________________________________
40public:
42 Ui::VP1CustomTourEditorForm ui;
45 QList<VP1CustomTourFrameWidget*> frames;
50 int countEnabledFrames( int& nEnabledPerspectiveFrames,
51 int& nEnabledOrthographicFrames ) const;
53
54};
55
56
57//____________________________________________________________________
59{
60 VP1Serialise s(0/*version*/);
61 QList<QByteArray> frameStates;
62 for (VP1CustomTourFrameWidget*frame : m_d->frames) {
63 frameStates << frame->serialise();
64 s.ignoreWidget(frame);
65 }
66 s.save(frameStates);
67 s.save(m_d->ui.doubleSpinBox_theta);
68 s.save(m_d->ui.doubleSpinBox_radius);
69 s.save(m_d->ui.groupBox_utilityZoom);
70 s.warnUnsaved(this);
71 return s.result();
72}
73
74//____________________________________________________________________
75void VP1CustomTourEditor::setState(const QByteArray& ba)
76{
77 for (VP1CustomTourFrameWidget*frame : m_d->frames)
78 frame->deleteLater();
79 m_d->frames.clear();
80
81 VP1Deserialise s(ba);
82 if (s.version()!=0)
83 return;
84 QList<QByteArray> frameStates = s.restore<QList<QByteArray> >();
85 s.restore(m_d->ui.doubleSpinBox_theta);
86 s.restore(m_d->ui.doubleSpinBox_radius);
87 s.restore(m_d->ui.groupBox_utilityZoom);
88 s.warnUnrestored(this);
89
90 m_d->ui.widget_utilityZoomContents->setVisible(m_d->ui.groupBox_utilityZoom->isChecked());
91
92 for (const QByteArray& ba2 : frameStates)
93 m_d->addFrame(new VP1CustomTourFrameWidget(ba2));
94 m_d->updateFrameListVisuals();
96}
97
98
99//____________________________________________________________________
101 : QWidget(0,Qt::WindowStaysOnTopHint), m_d(new Imp)
102{
103
104 m_d->theclass = this;
105 m_d->ui.setupUi(this);
106 m_d->ui.groupBox_utilityZoom->setChecked(false);
107 m_d->ui.widget_utilityZoomContents->setVisible(false);
108 m_d->viewer = viewer;
109 setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png")));
110 m_d->frameHolderWidget = new QWidget;
111 m_d->ui.scrollArea->setWidgetResizable(true);
112 m_d->ui.scrollArea->setWidget(m_d->frameHolderWidget);
113
114 connect(new QShortcut(QKeySequence(Qt::Key_Escape), this),SIGNAL(activated()),this,SLOT(hide()));
115 connect(m_d->ui.pushButton_close,SIGNAL(clicked()),this,SLOT(hide()));
116
117 connect(m_d->ui.pushButton_addCurrentView,SIGNAL(clicked()),this,SLOT(buttonClicked()));
118 connect(m_d->ui.pushButton_refreshPreviews,SIGNAL(clicked()),this,SLOT(buttonClicked()));
119 connect(m_d->ui.pushButton_execute,SIGNAL(clicked()),this,SLOT(buttonClicked()));
120 connect(m_d->ui.pushButton_utilityZoomShow,SIGNAL(clicked()),this,SLOT(buttonClicked()));
121
122 m_d->objectsToDisableWhenTourUnavailable << m_d->ui.pushButton_execute;
123
125}
126
127//____________________________________________________________________
129{
130 m_d->frameHolderWidget->deleteLater();
131 for (VP1CustomTourFrameWidget*frame : m_d->frames)
132 frame->deleteLater();
133 delete m_d;
134}
135
136//____________________________________________________________________
138{
139 ev->ignore();
140 hide();
141}
142
143//____________________________________________________________________
145{
146 // std::cout<<"VP1CustomTourEditor::Imp::addFrame %= "<<frame->clipVolumePercentOfATLAS()<<std::endl;
147 frames << frame;
148 connect(frame,SIGNAL(requestStepToEarlier()),theclass,SLOT(frameStepToEarlier()));
149 connect(frame,SIGNAL(requestStepToLater()),theclass,SLOT(frameStepToLater()));
150 connect(frame,SIGNAL(requestDelete()),theclass,SLOT(frameDelete()));
151 connect(frame,SIGNAL(requestShow()),theclass,SLOT(frameShow()));
152 connect(frame,SIGNAL(requestSwap(VP1CustomTourFrameWidget*,VP1CustomTourFrameWidget*)),
154 connect(frame,SIGNAL(frameEnableStateChanged()),theclass,SLOT(enabledFrameListChanged()));
155}
156
157//____________________________________________________________________
159{
160 bool save = frameHolderWidget->updatesEnabled();
161 if (save)
162 frameHolderWidget->setUpdatesEnabled(false);
163 int sliderpos=ui.scrollArea->verticalScrollBar()->value();
164 for (QObject * o : frameHolderWidget->children()) {
165 if (o->isWidgetType()) {
166 static_cast<QWidget*>(o)->setVisible(false);
167 o->setParent(0);
168 }
169 }
170 delete frameHolderWidget->layout();
171 QVBoxLayout * vlayout = new QVBoxLayout;
172 for (VP1CustomTourFrameWidget*frame : frames) {
173 vlayout->addWidget(frame);
174 frame->setParent(frameHolderWidget);
175 frame->setVisible(true);
176 }
177 vlayout->addStretch(1);
178 frameHolderWidget->setLayout(vlayout);
180 sliderpos=std::max(ui.scrollArea->verticalScrollBar()->minimum(),
181 std::min(ui.scrollArea->verticalScrollBar()->maximum(),sliderpos));
182 ui.scrollArea->verticalScrollBar()->setValue(sliderpos);
183 theclass->enabledFrameListChanged();
184 if (save)
185 frameHolderWidget->setUpdatesEnabled(true);
186
187}
188
189//____________________________________________________________________
191{
192 int iframe(m_d->frames.indexOf(dynamic_cast<VP1CustomTourFrameWidget*>(sender())));
193 if (iframe<=0)
194 return;//not found or already at start
195#if QTCORE_VERSION >= 0x050D00
196 m_d->frames.swapItemsAt(iframe-1,iframe);
197#else
198 m_d->frames.swap(iframe-1,iframe);
199#endif
200 m_d->updateFrameListVisuals();
201}
202
203//____________________________________________________________________
205{
206 int iframe(m_d->frames.indexOf(dynamic_cast<VP1CustomTourFrameWidget*>(sender())));
207 if (iframe<0)
208 return;
209 if (iframe>=m_d->frames.count()-1)
210 return;//already at end
211#if QTCORE_VERSION >= 0x050D00
212 m_d->frames.swapItemsAt(iframe,iframe+1);
213#else
214 m_d->frames.swap(iframe,iframe+1);
215#endif
216 m_d->updateFrameListVisuals();
217}
218
219//____________________________________________________________________
221{
222 VP1CustomTourFrameWidget * frame = dynamic_cast<VP1CustomTourFrameWidget*>(sender());
223 if (!frame)
224 return;
225 m_d->frames.removeAll(frame);
226 frame->deleteLater();
227 m_d->updateFrameStepControlsEnablement();
229}
230
231//____________________________________________________________________
233{
234 VP1CustomTourFrameWidget * frame = dynamic_cast<VP1CustomTourFrameWidget*>(sender());
235 if (!frame)
236 return;
237
238 if (frame->camStateIsPerspective()==m_d->viewer->currentCamIsPerspective()) {
239 //Zoom there:
240 SoCamera * cam = m_d->viewer->getCamera();
241 SoNode * root = m_d->viewer->getSceneGraph();
242 if (!cam||!root||!root->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))
243 return;
244
245 if (m_d->viewer->isAnimating())
246 m_d->viewer->stopAnimating();
247 VP1CameraHelper::animatedZoomToCameraState( cam,static_cast<SoGroup*>(root),frame->camState(),
248 frame->zoomToFrameTime(),
251 frame->zoomToFrameForcedCircular() );
252 } else {
253 //Go there directly:
254 m_d->viewer->toggleCameraType();
255 SoCamera * cam = m_d->viewer->getCamera();
256 if (!cam)
257 return;
258 QByteArray ba(frame->camState());
260 }
261}
262
263//____________________________________________________________________
265{
266 for (int i = 0; i < frames.count(); ++i) {
267 VP1CustomTourFrameWidget*frame = frames.at(i);
268 bool earlier(true), later(true);
269 if (i==0)
270 earlier = false;
271 if (i==frames.count()-1)
272 later = false;
273 frame->setStepToEarlierControlsEnabled(earlier);
274 frame->setStepToLaterControlsEnabled(later);
275 }
276}
277
278//____________________________________________________________________
280 VP1CustomTourFrameWidget * frame2 )
281{
282 int iframe1(m_d->frames.indexOf(frame1));
283 int iframe2(m_d->frames.indexOf(frame2));
284 if ( iframe1==iframe2
285 ||iframe1<0
286 ||iframe2<0
287 ||iframe1>=m_d->frames.count()
288 ||iframe2>=m_d->frames.count() )
289 return;
290#if QTCORE_VERSION >= 0x050D00
291 m_d->frames.swapItemsAt(iframe1,iframe2);
292#else
293 m_d->frames.swap(iframe1,iframe2);
294#endif
295 m_d->updateFrameListVisuals();
296}
297
298//____________________________________________________________________
300{
301 if (m_d->ui.pushButton_addCurrentView==sender()) {
302 VP1CustomTourFrameWidget * frame = new VP1CustomTourFrameWidget(m_d->viewer->currentCamIsPerspective(),
303 m_d->viewer->currentCameraState());
304 m_d->addFrame(frame);
305 m_d->updateFrameSnapshot(frame);
306 m_d->updateFrameListVisuals();
307 } else if (m_d->ui.pushButton_refreshPreviews==sender()) {
308 for (VP1CustomTourFrameWidget*frame : m_d->frames)
309 m_d->updateFrameSnapshot(frame);
310 } else if (m_d->ui.pushButton_execute==sender()) {
311 m_d->viewer->startCustomTour();
312 } else if (m_d->ui.pushButton_utilityZoomShow==sender()) {
313 SoCamera * cam = m_d->viewer->getCamera();
314 SoNode * root = m_d->viewer->getSceneGraph();
315 if (!cam||!root||!root->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))
316 return;
317
318 double r(m_d->ui.doubleSpinBox_radius->value()*1000.0/*meters*/);
319 double theta(m_d->ui.doubleSpinBox_theta->value()/180.0*M_PI);
320 theta += M_PI;
321 while (theta<0) theta += 2*M_PI;
322 while (theta>2*M_PI) theta -= 2*M_PI;
323 double a(r/sqrt(3.0));
324 SbBox3f box(-a,-a,-a,a,a,a);
325 SbVec3f lookat = SbVec3f(sin(theta),0,cos(theta));
326 SbVec3f upvec = SbVec3f(0,1,0);
327 bool notifyenabled = cam->enableNotify(false);
328 m_d->viewer->resetCamera();
329 VP1CameraHelper::animatedZoomToBBox( cam,static_cast<SoGroup*>(root),
330 box, 0.0, 100.0, 1.0,lookat,upvec);
331 if (notifyenabled)
332 cam->enableNotify(true);//Don't touch here - to avoid showing
333 //the reset cam state (the camera helper
334 //will touch it when modifying it)
335 }
336}
337
338//____________________________________________________________________
340{
341 QPixmap pm = viewer->getSnapShotFromCamState(frame->camStateIsPerspective(),frame->camState(),
342 frame->snapShotWidth(),frame->snapShotHeight());
343 if (!pm.isNull())
344 frame->setSnapshot(pm);
345}
346
347//____________________________________________________________________
348int VP1CustomTourEditor::Imp::countEnabledFrames( int& nEnabledPerspectiveFrames,
349 int& nEnabledOrthographicFrames ) const
350{
351 nEnabledPerspectiveFrames = 0;
352 nEnabledOrthographicFrames = 0;
353 for (VP1CustomTourFrameWidget*frame : frames) {
354 if (frame->frameIsEnabled()) {
355 if (frame->camStateIsPerspective())
356 ++nEnabledPerspectiveFrames;
357 else
358 ++nEnabledOrthographicFrames;
359 }
360 }
361 return nEnabledPerspectiveFrames+nEnabledOrthographicFrames;
362}
363
364
365//____________________________________________________________________
367{
368 int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
369 int n = m_d->countEnabledFrames( nEnabledPerspectiveFrames,
370 nEnabledOrthographicFrames );
371 QString s("dummy");
372 bool enable(true);
373 if (n<2) {
374 s = "Add at least two frames for tour";
375 enable=false;
376 } else {
377 if (nEnabledPerspectiveFrames>0&&nEnabledOrthographicFrames>0) {
378 s = "Mixed camera types are forbidden";
379 enable=false;
380 } else {
381 if (nEnabledPerspectiveFrames>0)
382 s="Perspective camera tour";
383 else
384 s="Orthographic camera tour";
385 }
386 }
387 m_d->ui.label_statustext->setText(s);
388
389 for (QObject * o : m_d->objectsToDisableWhenTourUnavailable) {
390 if (o->isWidgetType())
391 static_cast<QWidget*>(o)->setEnabled(enable);
392 else
393 static_cast<QAction*>(o)->setEnabled(enable);
394 }
395}
396
397//____________________________________________________________________
399{
400 int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
401 int n = m_d->countEnabledFrames( nEnabledPerspectiveFrames,
402 nEnabledOrthographicFrames );
403 if (nEnabledPerspectiveFrames>0&&nEnabledOrthographicFrames>0)
404 return false;
405 return n>=2;
406}
407
408//____________________________________________________________________
410{
411 int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
412 m_d->countEnabledFrames( nEnabledPerspectiveFrames,
413 nEnabledOrthographicFrames );
414
415 return nEnabledOrthographicFrames==0;
416}
417
418//____________________________________________________________________
419void VP1CustomTourEditor::addTourToAnimationSequencer(AnimationSequencer& as,bool jumpDirectlyToFirstFrame) const
420{
421 if (!tourAvailable())
422 return;
423 bool firstInDirectJump(jumpDirectlyToFirstFrame);
424 for (VP1CustomTourFrameWidget*frame : m_d->frames) {
425 if (frame->frameIsEnabled()) {
426 double t(frame->zoomToFrameTime());
427 if (firstInDirectJump) {
428 t = 0.0;
429 firstInDirectJump = false;
430 }
431
432 // std::cout<<"addTourToAnimationSequencer %="<<frame->clipVolumePercentOfATLAS()<<std::endl;
433 as.sequence().addFrame(frame->camState(),t,
435 frame->clipVolumePercentOfATLAS() );
436 if (frame->stayOnFrameTime()>0.0)
437 as.sequence().addFrame(frame->camState(),frame->stayOnFrameTime(),false, false, frame->clipVolumePercentOfATLAS());
438 }
439 }
440}
441
443 emit clipVolumePercentOfATLAS( percent );
444
445 // Let's assume ATLAS is 40m long. So emit this.
446 emit clipVolumeRadiusChanged( percent * 400 );
447}
448
449
450//____________________________________________________________________
452{
453 if (o)
454 m_d->objectsToDisableWhenTourUnavailable << o;
455}
#define M_PI
Scalar theta() const
theta method
static Double_t a
void addFrame(REGION reg, const SbVec3f &dir, const SbVec3f &upvec, double t, bool variableSpeed=false, bool forceCircular=false, double clip=100.0)
AnimationSequence & sequence()
static VP1CameraHelper * animatedZoomToCameraState(SoCamera *camera, SoGroup *sceneroot, const QByteArray &camstate, double duration_in_secs=1.0, double clipVolPercent=100.0, double lastClipVolPercent=100.0, bool varySpeed=true, bool forceCircular=false)
static VP1CameraHelper * animatedZoomToBBox(SoCamera *camera, SoGroup *sceneroot, const SbBox3f &box, double duration_in_secs=1.0, double clipVolPercent=100.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999), bool varySpeed=true, bool forceCircular=false)
int countEnabledFrames(int &nEnabledPerspectiveFrames, int &nEnabledOrthographicFrames) const
VP1CustomTourEditor * theclass
void addFrame(VP1CustomTourFrameWidget *frame)
Ui::VP1CustomTourEditorForm ui
QList< VP1CustomTourFrameWidget * > frames
void updateFrameSnapshot(VP1CustomTourFrameWidget *)
QList< QObject * > objectsToDisableWhenTourUnavailable
void swap(VP1CustomTourFrameWidget *, VP1CustomTourFrameWidget *)
void disableObjectWhenTourNotAvailable(QObject *)
void addTourToAnimationSequencer(AnimationSequencer &, bool jumpDirectlyToFirstFrame) const
void setClipVolumePercentOfATLAS(double)
QByteArray state() const
VP1CustomTourEditor(VP1ExaminerViewer *)
void setState(const QByteArray &)
void closeEvent(QCloseEvent *)
void clipVolumeRadiusChanged(double)
void clipVolumePercentOfATLAS(double)
const QByteArray & camState() const
static bool deserializeSoCameraParameters(QByteArray &, SoCamera &)
int r
Definition globals.cxx:22
int ev
Definition globals.cxx:25