openscenegraph
osgViewer/ViewerEventHandlers
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2*
3* This library is open source and may be redistributed and/or modified under
4* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5* (at your option) any later version. The full license is in LICENSE file
6* included with this distribution, and on the openscenegraph.org website.
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
11* OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSGVIEWER_VIEWEREVENTHANDLERS
15#define OSGVIEWER_VIEWEREVENTHANDLERS 1
16
17#include <osg/AnimationPath>
18#include <osgText/Text>
19#include <osgGA/GUIEventHandler>
20#include <osgGA/AnimationPathManipulator>
21
22#include <osgViewer/GraphicsWindow>
23#include <osgViewer/Viewer>
24
25#include <osgDB/fstream>
26
27namespace osgViewer {
28
29/** Event handler for adding on screen help to Viewers.*/
30class OSGVIEWER_EXPORT HelpHandler : public osgGA::GUIEventHandler
31{
32 public:
33
34 HelpHandler(osg::ApplicationUsage* au=0);
35
36 void setApplicationUsage(osg::ApplicationUsage* au) { _applicationUsage = au; }
37 osg::ApplicationUsage* getApplicationUsage() { return _applicationUsage.get(); }
38 const osg::ApplicationUsage* getApplicationUsage() const { return _applicationUsage.get(); }
39
40 void setKeyEventTogglesOnScreenHelp(int key) { _keyEventTogglesOnScreenHelp = key; }
41 int getKeyEventTogglesOnScreenHelp() const { return _keyEventTogglesOnScreenHelp; }
42
43 void reset();
44
45 osg::Camera* getCamera() { return _camera.get(); }
46 const osg::Camera* getCamera() const { return _camera.get(); }
47
48 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
49
50 /** Get the keyboard and mouse usage of this manipulator.*/
51 virtual void getUsage(osg::ApplicationUsage& usage) const;
52
53 protected:
54
55 void setUpHUDCamera(osgViewer::ViewerBase* viewer);
56
57 void setUpScene(osgViewer::ViewerBase* viewer);
58
59 osg::ref_ptr<osg::ApplicationUsage> _applicationUsage;
60
61 int _keyEventTogglesOnScreenHelp;
62
63 bool _helpEnabled;
64
65 bool _initialized;
66 osg::ref_ptr<osg::Camera> _camera;
67 osg::ref_ptr<osg::Switch> _switch;
68
69};
70
71/**
72 * Event handler for adding on screen stats reporting to Viewers.
73 */
74class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler
75{
76 public:
77
78 StatsHandler();
79
80 enum StatsType
81 {
82 NO_STATS = 0,
83 FRAME_RATE = 1,
84 VIEWER_STATS = 2,
85 CAMERA_SCENE_STATS = 3,
86 VIEWER_SCENE_STATS = 4,
87 LAST = 5
88 };
89
90 void setKeyEventTogglesOnScreenStats(int key) { _keyEventTogglesOnScreenStats = key; }
91 int getKeyEventTogglesOnScreenStats() const { return _keyEventTogglesOnScreenStats; }
92
93 void setKeyEventPrintsOutStats(int key) { _keyEventPrintsOutStats = key; }
94 int getKeyEventPrintsOutStats() const { return _keyEventPrintsOutStats; }
95
96 double getBlockMultiplier() const { return _blockMultiplier; }
97
98 void reset();
99
100 osg::Camera* getCamera() { return _camera.get(); }
101 const osg::Camera* getCamera() const { return _camera.get(); }
102
103 virtual void collectWhichCamerasToRenderStatsFor(osgViewer::ViewerBase* viewer, osgViewer::ViewerBase::Cameras& cameras);
104
105 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
106
107 /** Get the keyboard and mouse usage of this manipulator.*/
108 virtual void getUsage(osg::ApplicationUsage& usage) const;
109
110 /** This allows the user to register additional stats lines that will
111 be added to the graph. The stats for these will be gotten from the
112 viewer (viewer->getViewerStats()). The stats can be displayed in
113 either or all of the following ways:
114
115 - A numeric time beside the stat name
116 Requires that an elapsed time be recorded in the viewer's stats
117 for the "timeTakenName".
118 - A bar in the top bar graph
119 Requires that two times (relative to the viewer's start tick) be
120 recorded in the viewer's stats for the "beginTimeName" and
121 "endTimeName".
122 - A line in the bottom graph
123 Requires that an elapsed time be recorded in the viewer's stats
124 for the "timeTakenName" and that the value be used as an average.
125
126 If you don't want a numeric value and a line in the bottom line
127 graph for your value, pass the empty string for timeTakenName. If
128 you don't want a bar in the graph, pass the empty string for
129 beginTimeName and endTimeName.
130
131 @param label The label to be displayed to identify the line in the stats.
132 @param textColor Will be used for the text label, the numeric time and the bottom line graph.
133 @param barColor Will be used for the bar in the top bar graph.
134 @param timeTakenName The name to be queried in the viewer stats for the numeric value (also used for the bottom line graph).
135 @param multiplier The multiplier to apply to the numeric value before displaying it in the stats.
136 @param average Whether to use the average value of the numeric value.
137 @param averageInInverseSpace Whether to average in inverse space (used for frame rate).
138 @param beginTimeName The name to be queried in the viewer stats for the begin time for the top bar graph.
139 @param endTimeName The name to be queried in the viewer stats for the end time for the top bar graph.
140 @param maxValue The value to use as maximum in the bottom line graph. Stats will be clamped between 0 and that value, and it will be the highest visible value in the graph.
141 */
142 void addUserStatsLine(const std::string& label, const osg::Vec4& textColor, const osg::Vec4& barColor,
143 const std::string& timeTakenName, float multiplier, bool average, bool averageInInverseSpace,
144 const std::string& beginTimeName, const std::string& endTimeName, float maxValue);
145
146 void removeUserStatsLine(const std::string& label);
147
148protected:
149
150 void setUpHUDCamera(osgViewer::ViewerBase* viewer);
151 void setWindowSize(int width, int height);
152
153 osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color);
154
155 osg::Geometry* createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
156
157 osg::Geometry* createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
158
159 osg::Geometry* createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks);
160
161 void createTimeStatsLine(const std::string& lineLabel, osg::Vec3 pos,
162 const osg::Vec4& textColor, const osg::Vec4& barColor, osg::Stats* viewerStats, osg::Stats* stats,
163 const std::string& timeTakenName, float multiplier, bool average, bool averageInInverseSpace,
164 const std::string& beginTimeName, const std::string& endTimeName);
165
166 void createCameraTimeStats(osg::Vec3& pos, bool acquireGPUStats, osg::Stats* viewerStats, osg::Camera* camera);
167
168 void setUpScene(osgViewer::ViewerBase* viewer);
169
170 void updateThreadingModelText();
171
172 int _keyEventTogglesOnScreenStats;
173 int _keyEventPrintsOutStats;
174
175 int _statsType;
176
177 bool _initialized;
178 osg::ref_ptr<osg::Camera> _camera;
179
180 osg::ref_ptr<osg::Switch> _switch;
181
182 osg::ref_ptr<osg::Geode> _statsGeode;
183
184 ViewerBase::ThreadingModel _threadingModel;
185 osg::ref_ptr<osgText::Text> _threadingModelText;
186
187 unsigned int _frameRateChildNum;
188 unsigned int _viewerChildNum;
189 unsigned int _cameraSceneChildNum;
190 unsigned int _viewerSceneChildNum;
191 unsigned int _numBlocks;
192 double _blockMultiplier;
193
194 float _statsWidth;
195 float _statsHeight;
196
197 std::string _font;
198 float _startBlocks;
199 float _leftPos;
200 float _characterSize;
201 float _lineHeight;
202
203 struct UserStatsLine
204 {
205 std::string label;
206 osg::Vec4 textColor;
207 osg::Vec4 barColor;
208 std::string timeTakenName;
209 float multiplier;
210 bool average;
211 bool averageInInverseSpace;
212 std::string beginTimeName;
213 std::string endTimeName;
214 float maxValue;
215
216 UserStatsLine(const std::string& label_, const osg::Vec4& textColor_, const osg::Vec4& barColor_,
217 const std::string& timeTakenName_, float multiplier_, bool average_, bool averageInInverseSpace_,
218 const std::string& beginTimeName_, const std::string& endTimeName_, float maxValue_)
219 : label(label_), textColor(textColor_), barColor(barColor_),
220 timeTakenName(timeTakenName_), multiplier(multiplier_), average(average_), averageInInverseSpace(averageInInverseSpace_),
221 beginTimeName(beginTimeName_), endTimeName(endTimeName_), maxValue(maxValue_)
222 {
223 }
224 };
225
226 typedef std::vector<UserStatsLine> UserStatsLines;
227 UserStatsLines _userStatsLines;
228
229};
230
231/** Event handler allowing to change the screen resolution (in windowed mode) and toggle between fullscreen and windowed mode. */
232class OSGVIEWER_EXPORT WindowSizeHandler : public osgGA::GUIEventHandler
233{
234public:
235
236 WindowSizeHandler();
237
238 /** Get the keyboard and mouse usage of this manipulator.*/
239 virtual void getUsage(osg::ApplicationUsage &usage) const;
240
241 void setKeyEventToggleFullscreen(int key) { _keyEventToggleFullscreen = key; }
242 int getKeyEventToggleFullscreen() const { return _keyEventToggleFullscreen; }
243
244 void setToggleFullscreen(bool flag) { _toggleFullscreen = flag; }
245 bool getToggleFullscreen() const { return _toggleFullscreen; }
246
247 void setKeyEventWindowedResolutionUp(int key) { _keyEventWindowedResolutionUp = key; }
248 int getKeyEventWindowedResolutionUp() const { return _keyEventWindowedResolutionUp; }
249 void setKeyEventWindowedResolutionDown(int key) { _keyEventWindowedResolutionDown = key; }
250 int getKeyEventWindowedResolutionDown() const { return _keyEventWindowedResolutionDown; }
251
252 void setChangeWindowedResolution(bool flag) { _changeWindowedResolution = flag; }
253 bool getChangeWindowedResolution() const { return _changeWindowedResolution; }
254
255 virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
256
257protected:
258
259 void toggleFullscreen(osgViewer::GraphicsWindow *window);
260 void changeWindowedResolution(osgViewer::GraphicsWindow *window, bool increase);
261
262 unsigned int getNearestResolution(int screenWidth, int screenHeight, int width, int height) const;
263
264 int _keyEventToggleFullscreen;
265 bool _toggleFullscreen;
266
267 int _keyEventWindowedResolutionUp;
268 int _keyEventWindowedResolutionDown;
269 bool _changeWindowedResolution;
270 std::vector<osg::Vec2> _resolutionList;
271 int _currentResolutionIndex;
272};
273
274/** Event handler allowing to change the viewer threading model */
275class OSGVIEWER_EXPORT ThreadingHandler : public osgGA::GUIEventHandler
276{
277public:
278
279 ThreadingHandler();
280
281 /** Get the keyboard and mouse usage of this manipulator.*/
282 virtual void getUsage(osg::ApplicationUsage &usage) const;
283
284 void setKeyEventChangeThreadingModel(int key) { _keyEventChangeThreadingModel = key; }
285 int getKeyEventChangeThreadingModel() const { return _keyEventChangeThreadingModel; }
286
287 void setChangeThreadingModel(bool flag) { _changeThreadingModel = flag; }
288 bool getChangeThreadingModel() const { return _changeThreadingModel; }
289
290 void setKeyEventChangeEndBarrierPosition(int key) { _keyEventChangeEndBarrierPosition = key; }
291 int getKeyEventChangeEndBarrierPosition() const { return _keyEventChangeEndBarrierPosition; }
292
293 void setChangeEndBarrierPosition(bool flag) { _changeEndBarrierPosition = flag; }
294 bool getChangeEndBarrierPosition() const { return _changeEndBarrierPosition; }
295
296 bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
297
298protected:
299
300 int _keyEventChangeThreadingModel;
301 bool _changeThreadingModel;
302
303 int _keyEventChangeEndBarrierPosition;
304 bool _changeEndBarrierPosition;
305
306 osg::Timer_t _tickOrLastKeyPress;
307};
308
309/**
310 * Event handler allowing the user to record the animation "path" of a camera. In it's current
311 * implementation, this handler cannot guarantee the final view matrix is correct; it is
312 * conceivable that the matrix may be one frame off. Eh--not a big deal! :)
313 * TODO: Write the file as we go, not when it's all done.
314 * TODO: Create an osgviewer on-screen indication that animation is taking place.
315*/
316class OSGVIEWER_EXPORT RecordCameraPathHandler : public osgGA::GUIEventHandler
317{
318public:
319
320 RecordCameraPathHandler(const std::string &filename = "saved_animation.path", float fps = 25.0f);
321
322 void setKeyEventToggleRecord(int key) { _keyEventToggleRecord = key; }
323 int getKeyEventToggleRecord() const { return _keyEventToggleRecord; }
324
325 void setKeyEventTogglePlayback(int key) { _keyEventTogglePlayback = key; }
326 int getKeyEventTogglePlayback() const { return _keyEventTogglePlayback; }
327
328 void setAutoIncrementFilename( bool autoinc = true ) { _autoinc = autoinc?0:-1; }
329
330 virtual void getUsage(osg::ApplicationUsage &usage) const;
331
332 bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
333
334protected:
335
336 std::string _filename;
337 int _autoinc;
338 osgDB::ofstream _fout;
339
340 int _keyEventToggleRecord;
341 int _keyEventTogglePlayback;
342
343
344 bool _currentlyRecording;
345 bool _currentlyPlaying;
346 double _interval;
347 double _delta;
348 osg::Timer_t _animStartTime;
349 osg::Timer_t _lastFrameTime;
350 osg::ref_ptr<osg::AnimationPath> _animPath;
351 osg::ref_ptr<osgGA::AnimationPathManipulator> _animPathManipulator;
352 osg::ref_ptr<osgGA::CameraManipulator> _oldManipulator;
353};
354
355/** Event handler for increase/decreasing LODScale.*/
356class OSGVIEWER_EXPORT LODScaleHandler : public osgGA::GUIEventHandler
357{
358 public:
359
360 LODScaleHandler();
361
362 void setKeyEventIncreaseLODScale(int key) { _keyEventIncreaseLODScale = key; }
363 int getKeyEventIncreaseLODScale() const { return _keyEventIncreaseLODScale; }
364
365 void setKeyEventDecreaseLODScale(int key) { _keyEventDecreaseLODScale = key; }
366 int getKeyEventDecreaseLODScale() const { return _keyEventDecreaseLODScale; }
367
368 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
369
370 /** Get the keyboard and mouse usage of this manipulator.*/
371 virtual void getUsage(osg::ApplicationUsage& usage) const;
372
373 protected:
374
375
376 int _keyEventIncreaseLODScale;
377 int _keyEventDecreaseLODScale;
378
379
380};
381
382/** Event handler for toggling SyncToVBlank.*/
383class OSGVIEWER_EXPORT ToggleSyncToVBlankHandler : public osgGA::GUIEventHandler
384{
385 public:
386
387 ToggleSyncToVBlankHandler();
388
389 void setKeyEventToggleSyncToVBlankHandler(int key) { _keyEventToggleSyncToVBlank = key; }
390 int getKeyEventToggleSyncToVBlankHandler() const { return _keyEventToggleSyncToVBlank; }
391
392 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
393
394 /** Get the keyboard and mouse usage of this manipulator.*/
395 virtual void getUsage(osg::ApplicationUsage& usage) const;
396
397 protected:
398
399
400 int _keyEventToggleSyncToVBlank;
401
402
403};
404
405
406/** Event handler that will capture the screen on key press. */
407class OSGVIEWER_EXPORT ScreenCaptureHandler : public osgGA::GUIEventHandler
408{
409 public:
410
411 /** Abstract base class for what to do when a screen capture happens. */
412 class CaptureOperation : public osg::Referenced
413 {
414 public:
415 virtual void operator()(const osg::Image& image, const unsigned int context_id) = 0;
416 };
417
418 /** Concrete implementation of a CaptureOperation that writes the screen capture to a file. */
419 class OSGVIEWER_EXPORT WriteToFile : public CaptureOperation
420 {
421 public:
422 enum SavePolicy
423 {
424 OVERWRITE,
425 SEQUENTIAL_NUMBER
426 // ... any others?
427 };
428
429 WriteToFile(const std::string& filename, const std::string& extension, SavePolicy savePolicy = SEQUENTIAL_NUMBER);
430
431 virtual void operator()(const osg::Image& image, const unsigned int context_id);
432
433 void setSavePolicy(SavePolicy savePolicy) { _savePolicy = savePolicy; }
434 SavePolicy getSavePolicy() const { return _savePolicy; }
435
436 protected:
437
438 WriteToFile& operator = (const WriteToFile&) { return *this; }
439
440 const std::string _filename;
441 const std::string _extension;
442
443 SavePolicy _savePolicy;
444
445 std::vector<unsigned int> _contextSaveCounter;
446 };
447
448 /** @param defaultOperation : operation to do when screen capture happens. */
449 /** @param numFrames >0: capture that number of frames. <0: capture all frames, call stopCapture() to stop it. */
450 ScreenCaptureHandler(CaptureOperation* defaultOperation = 0, int numFrames = 1);
451
452 void setKeyEventTakeScreenShot(int key) { _keyEventTakeScreenShot = key; }
453 int getKeyEventTakeScreenShot() const { return _keyEventTakeScreenShot; }
454
455 void setKeyEventToggleContinuousCapture(int key) { _keyEventToggleContinuousCapture = key; }
456 int getKeyEventToggleContinuousCapture() const { return _keyEventToggleContinuousCapture; }
457
458 void setCaptureOperation(CaptureOperation* operation);
459 CaptureOperation* getCaptureOperation() const;
460
461 // aa will point to an osgViewer::View, so we will take a screenshot
462 // of that view's graphics contexts.
463 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
464
465 /** Capture the given viewer's views on the next frame. */
466 virtual void captureNextFrame(osgViewer::ViewerBase& viewer);
467
468 /** Set the number of frames to capture.
469 @param numFrames >0: capture that number of frames. <0: capture all frames, call stopCapture() to stop it. */
470 void setFramesToCapture(int numFrames);
471
472 /** Get the number of frames to capture. */
473 int getFramesToCapture() const;
474
475 /** Start capturing any viewer(s) the handler is attached to at the
476 end of the next frame. */
477 void startCapture();
478
479 /** Stop capturing. */
480 void stopCapture();
481
482 /** Get the keyboard and mouse usage of this manipulator.*/
483 virtual void getUsage(osg::ApplicationUsage& usage) const;
484
485 protected:
486 bool _startCapture;
487 bool _stopCapture;
488
489 int _keyEventTakeScreenShot;
490 int _keyEventToggleContinuousCapture;
491 // there could be a key to start taking screenshots every new frame
492
493 osg::ref_ptr<CaptureOperation> _operation;
494 osg::ref_ptr<osg::Camera::DrawCallback> _callback;
495
496 void addCallbackToViewer(osgViewer::ViewerBase& viewer);
497 void removeCallbackFromViewer(osgViewer::ViewerBase& viewer);
498 osg::Camera* findAppropriateCameraForCallback(osgViewer::ViewerBase& viewer);
499};
500
501/** InteractiveImage is an event handler that computes the mouse coordinates in an images coordinate frame
502 * and then passes keyboard and mouse events to it. This event handler is useful for vnc or browser
503 * surfaces in the 3D scene.*/
504class OSGVIEWER_EXPORT InteractiveImageHandler : public osgGA::GUIEventHandler, public osg::DrawableCullCallback
505{
506public:
507
508 /// Constructor to use when the InteractiveImage is in the 3D scene (i.e. not in a fullscreen HUD overlay).
509 InteractiveImageHandler(osg::Image* image);
510 /// Constructor to use when the InteractiveImage is in a fullscreen HUD overlay.
511 InteractiveImageHandler(osg::Image* image, osg::Texture2D* texture, osg::Camera* camera);
512
513 META_Object(osgViewer, InteractiveImageHandler);
514
515 virtual NodeCallback* asNodeCallback() { return osg::NodeCallback::asNodeCallback(); }
516 virtual const NodeCallback* asNodeCallback() const { return osg::NodeCallback::asNodeCallback(); }
517
518 virtual DrawableEventCallback* asDrawableEventCallback() { return osg::DrawableEventCallback::asDrawableEventCallback(); }
519 virtual const DrawableEventCallback* asDrawableEventCallback() const { return osg::DrawableEventCallback::asDrawableEventCallback(); }
520
521 virtual DrawableCullCallback* asDrawableCullCallback() { return osg::DrawableCullCallback::asDrawableCullCallback(); }
522 virtual const DrawableCullCallback* asDrawableCullCallback() const { return osg::DrawableCullCallback::asDrawableCullCallback(); }
523
524 virtual osgGA::EventHandler* asEventHandler() { return osgGA::EventHandler::asEventHandler(); }
525 virtual const osgGA::EventHandler* asEventHandler() const { return osgGA::EventHandler::asEventHandler(); }
526
527 // use the osgGA::GUIEventHandler implementation of run.
528 virtual bool run(osg::Object* object, osg::Object* data) { return osgGA::GUIEventHandler::run(object, data); }
529
530 virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
531
532 virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const;
533
534protected:
535
536 virtual ~InteractiveImageHandler() {}
537
538 InteractiveImageHandler():
539 _fullscreen(false) {}
540
541 InteractiveImageHandler(const InteractiveImageHandler&,const osg::CopyOp& = osg::CopyOp::SHALLOW_COPY):
542 osg::Object(), osg::Callback(), osgGA::GUIEventHandler(), osg::DrawableCullCallback(), _fullscreen(false) {}
543
544 bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const;
545
546 void resize(int width, int height);
547
548 osg::observer_ptr<osg::Image> _image;
549 osg::observer_ptr<osg::Texture2D> _texture;
550
551 bool _fullscreen;
552 osg::observer_ptr<osg::Camera> _camera;
553
554};
555
556}
557
558#endif