1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
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.
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.
14#ifndef OSGVIEWER_VIEWEREVENTHANDLERS
15#define OSGVIEWER_VIEWEREVENTHANDLERS 1
17#include <osg/AnimationPath>
18#include <osgText/Text>
19#include <osgGA/GUIEventHandler>
20#include <osgGA/AnimationPathManipulator>
22#include <osgViewer/GraphicsWindow>
23#include <osgViewer/Viewer>
25#include <osgDB/fstream>
29/** Event handler for adding on screen help to Viewers.*/
30class OSGVIEWER_EXPORT HelpHandler : public osgGA::GUIEventHandler
34 HelpHandler(osg::ApplicationUsage* au=0);
36 void setApplicationUsage(osg::ApplicationUsage* au) { _applicationUsage = au; }
37 osg::ApplicationUsage* getApplicationUsage() { return _applicationUsage.get(); }
38 const osg::ApplicationUsage* getApplicationUsage() const { return _applicationUsage.get(); }
40 void setKeyEventTogglesOnScreenHelp(int key) { _keyEventTogglesOnScreenHelp = key; }
41 int getKeyEventTogglesOnScreenHelp() const { return _keyEventTogglesOnScreenHelp; }
45 osg::Camera* getCamera() { return _camera.get(); }
46 const osg::Camera* getCamera() const { return _camera.get(); }
48 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
50 /** Get the keyboard and mouse usage of this manipulator.*/
51 virtual void getUsage(osg::ApplicationUsage& usage) const;
55 void setUpHUDCamera(osgViewer::ViewerBase* viewer);
57 void setUpScene(osgViewer::ViewerBase* viewer);
59 osg::ref_ptr<osg::ApplicationUsage> _applicationUsage;
61 int _keyEventTogglesOnScreenHelp;
66 osg::ref_ptr<osg::Camera> _camera;
67 osg::ref_ptr<osg::Switch> _switch;
72 * Event handler for adding on screen stats reporting to Viewers.
74class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler
85 CAMERA_SCENE_STATS = 3,
86 VIEWER_SCENE_STATS = 4,
90 void setKeyEventTogglesOnScreenStats(int key) { _keyEventTogglesOnScreenStats = key; }
91 int getKeyEventTogglesOnScreenStats() const { return _keyEventTogglesOnScreenStats; }
93 void setKeyEventPrintsOutStats(int key) { _keyEventPrintsOutStats = key; }
94 int getKeyEventPrintsOutStats() const { return _keyEventPrintsOutStats; }
96 double getBlockMultiplier() const { return _blockMultiplier; }
100 osg::Camera* getCamera() { return _camera.get(); }
101 const osg::Camera* getCamera() const { return _camera.get(); }
103 virtual void collectWhichCamerasToRenderStatsFor(osgViewer::ViewerBase* viewer, osgViewer::ViewerBase::Cameras& cameras);
105 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
107 /** Get the keyboard and mouse usage of this manipulator.*/
108 virtual void getUsage(osg::ApplicationUsage& usage) const;
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:
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
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.
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.
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.
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);
146 void removeUserStatsLine(const std::string& label);
150 void setUpHUDCamera(osgViewer::ViewerBase* viewer);
151 void setWindowSize(int width, int height);
153 osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color);
155 osg::Geometry* createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
157 osg::Geometry* createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
159 osg::Geometry* createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks);
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);
166 void createCameraTimeStats(osg::Vec3& pos, bool acquireGPUStats, osg::Stats* viewerStats, osg::Camera* camera);
168 void setUpScene(osgViewer::ViewerBase* viewer);
170 void updateThreadingModelText();
172 int _keyEventTogglesOnScreenStats;
173 int _keyEventPrintsOutStats;
178 osg::ref_ptr<osg::Camera> _camera;
180 osg::ref_ptr<osg::Switch> _switch;
182 osg::ref_ptr<osg::Geode> _statsGeode;
184 ViewerBase::ThreadingModel _threadingModel;
185 osg::ref_ptr<osgText::Text> _threadingModelText;
187 unsigned int _frameRateChildNum;
188 unsigned int _viewerChildNum;
189 unsigned int _cameraSceneChildNum;
190 unsigned int _viewerSceneChildNum;
191 unsigned int _numBlocks;
192 double _blockMultiplier;
200 float _characterSize;
208 std::string timeTakenName;
211 bool averageInInverseSpace;
212 std::string beginTimeName;
213 std::string endTimeName;
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_)
226 typedef std::vector<UserStatsLine> UserStatsLines;
227 UserStatsLines _userStatsLines;
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
238 /** Get the keyboard and mouse usage of this manipulator.*/
239 virtual void getUsage(osg::ApplicationUsage &usage) const;
241 void setKeyEventToggleFullscreen(int key) { _keyEventToggleFullscreen = key; }
242 int getKeyEventToggleFullscreen() const { return _keyEventToggleFullscreen; }
244 void setToggleFullscreen(bool flag) { _toggleFullscreen = flag; }
245 bool getToggleFullscreen() const { return _toggleFullscreen; }
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; }
252 void setChangeWindowedResolution(bool flag) { _changeWindowedResolution = flag; }
253 bool getChangeWindowedResolution() const { return _changeWindowedResolution; }
255 virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
259 void toggleFullscreen(osgViewer::GraphicsWindow *window);
260 void changeWindowedResolution(osgViewer::GraphicsWindow *window, bool increase);
262 unsigned int getNearestResolution(int screenWidth, int screenHeight, int width, int height) const;
264 int _keyEventToggleFullscreen;
265 bool _toggleFullscreen;
267 int _keyEventWindowedResolutionUp;
268 int _keyEventWindowedResolutionDown;
269 bool _changeWindowedResolution;
270 std::vector<osg::Vec2> _resolutionList;
271 int _currentResolutionIndex;
274/** Event handler allowing to change the viewer threading model */
275class OSGVIEWER_EXPORT ThreadingHandler : public osgGA::GUIEventHandler
281 /** Get the keyboard and mouse usage of this manipulator.*/
282 virtual void getUsage(osg::ApplicationUsage &usage) const;
284 void setKeyEventChangeThreadingModel(int key) { _keyEventChangeThreadingModel = key; }
285 int getKeyEventChangeThreadingModel() const { return _keyEventChangeThreadingModel; }
287 void setChangeThreadingModel(bool flag) { _changeThreadingModel = flag; }
288 bool getChangeThreadingModel() const { return _changeThreadingModel; }
290 void setKeyEventChangeEndBarrierPosition(int key) { _keyEventChangeEndBarrierPosition = key; }
291 int getKeyEventChangeEndBarrierPosition() const { return _keyEventChangeEndBarrierPosition; }
293 void setChangeEndBarrierPosition(bool flag) { _changeEndBarrierPosition = flag; }
294 bool getChangeEndBarrierPosition() const { return _changeEndBarrierPosition; }
296 bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
300 int _keyEventChangeThreadingModel;
301 bool _changeThreadingModel;
303 int _keyEventChangeEndBarrierPosition;
304 bool _changeEndBarrierPosition;
306 osg::Timer_t _tickOrLastKeyPress;
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.
316class OSGVIEWER_EXPORT RecordCameraPathHandler : public osgGA::GUIEventHandler
320 RecordCameraPathHandler(const std::string &filename = "saved_animation.path", float fps = 25.0f);
322 void setKeyEventToggleRecord(int key) { _keyEventToggleRecord = key; }
323 int getKeyEventToggleRecord() const { return _keyEventToggleRecord; }
325 void setKeyEventTogglePlayback(int key) { _keyEventTogglePlayback = key; }
326 int getKeyEventTogglePlayback() const { return _keyEventTogglePlayback; }
328 void setAutoIncrementFilename( bool autoinc = true ) { _autoinc = autoinc?0:-1; }
330 virtual void getUsage(osg::ApplicationUsage &usage) const;
332 bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
336 std::string _filename;
338 osgDB::ofstream _fout;
340 int _keyEventToggleRecord;
341 int _keyEventTogglePlayback;
344 bool _currentlyRecording;
345 bool _currentlyPlaying;
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;
355/** Event handler for increase/decreasing LODScale.*/
356class OSGVIEWER_EXPORT LODScaleHandler : public osgGA::GUIEventHandler
362 void setKeyEventIncreaseLODScale(int key) { _keyEventIncreaseLODScale = key; }
363 int getKeyEventIncreaseLODScale() const { return _keyEventIncreaseLODScale; }
365 void setKeyEventDecreaseLODScale(int key) { _keyEventDecreaseLODScale = key; }
366 int getKeyEventDecreaseLODScale() const { return _keyEventDecreaseLODScale; }
368 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
370 /** Get the keyboard and mouse usage of this manipulator.*/
371 virtual void getUsage(osg::ApplicationUsage& usage) const;
376 int _keyEventIncreaseLODScale;
377 int _keyEventDecreaseLODScale;
382/** Event handler for toggling SyncToVBlank.*/
383class OSGVIEWER_EXPORT ToggleSyncToVBlankHandler : public osgGA::GUIEventHandler
387 ToggleSyncToVBlankHandler();
389 void setKeyEventToggleSyncToVBlankHandler(int key) { _keyEventToggleSyncToVBlank = key; }
390 int getKeyEventToggleSyncToVBlankHandler() const { return _keyEventToggleSyncToVBlank; }
392 bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
394 /** Get the keyboard and mouse usage of this manipulator.*/
395 virtual void getUsage(osg::ApplicationUsage& usage) const;
400 int _keyEventToggleSyncToVBlank;
406/** Event handler that will capture the screen on key press. */
407class OSGVIEWER_EXPORT ScreenCaptureHandler : public osgGA::GUIEventHandler
411 /** Abstract base class for what to do when a screen capture happens. */
412 class CaptureOperation : public osg::Referenced
415 virtual void operator()(const osg::Image& image, const unsigned int context_id) = 0;
418 /** Concrete implementation of a CaptureOperation that writes the screen capture to a file. */
419 class OSGVIEWER_EXPORT WriteToFile : public CaptureOperation
429 WriteToFile(const std::string& filename, const std::string& extension, SavePolicy savePolicy = SEQUENTIAL_NUMBER);
431 virtual void operator()(const osg::Image& image, const unsigned int context_id);
433 void setSavePolicy(SavePolicy savePolicy) { _savePolicy = savePolicy; }
434 SavePolicy getSavePolicy() const { return _savePolicy; }
438 WriteToFile& operator = (const WriteToFile&) { return *this; }
440 const std::string _filename;
441 const std::string _extension;
443 SavePolicy _savePolicy;
445 std::vector<unsigned int> _contextSaveCounter;
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);
452 void setKeyEventTakeScreenShot(int key) { _keyEventTakeScreenShot = key; }
453 int getKeyEventTakeScreenShot() const { return _keyEventTakeScreenShot; }
455 void setKeyEventToggleContinuousCapture(int key) { _keyEventToggleContinuousCapture = key; }
456 int getKeyEventToggleContinuousCapture() const { return _keyEventToggleContinuousCapture; }
458 void setCaptureOperation(CaptureOperation* operation);
459 CaptureOperation* getCaptureOperation() const;
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);
465 /** Capture the given viewer's views on the next frame. */
466 virtual void captureNextFrame(osgViewer::ViewerBase& viewer);
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);
472 /** Get the number of frames to capture. */
473 int getFramesToCapture() const;
475 /** Start capturing any viewer(s) the handler is attached to at the
476 end of the next frame. */
479 /** Stop capturing. */
482 /** Get the keyboard and mouse usage of this manipulator.*/
483 virtual void getUsage(osg::ApplicationUsage& usage) const;
489 int _keyEventTakeScreenShot;
490 int _keyEventToggleContinuousCapture;
491 // there could be a key to start taking screenshots every new frame
493 osg::ref_ptr<CaptureOperation> _operation;
494 osg::ref_ptr<osg::Camera::DrawCallback> _callback;
496 void addCallbackToViewer(osgViewer::ViewerBase& viewer);
497 void removeCallbackFromViewer(osgViewer::ViewerBase& viewer);
498 osg::Camera* findAppropriateCameraForCallback(osgViewer::ViewerBase& viewer);
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
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);
513 META_Object(osgViewer, InteractiveImageHandler);
515 virtual NodeCallback* asNodeCallback() { return osg::NodeCallback::asNodeCallback(); }
516 virtual const NodeCallback* asNodeCallback() const { return osg::NodeCallback::asNodeCallback(); }
518 virtual DrawableEventCallback* asDrawableEventCallback() { return osg::DrawableEventCallback::asDrawableEventCallback(); }
519 virtual const DrawableEventCallback* asDrawableEventCallback() const { return osg::DrawableEventCallback::asDrawableEventCallback(); }
521 virtual DrawableCullCallback* asDrawableCullCallback() { return osg::DrawableCullCallback::asDrawableCullCallback(); }
522 virtual const DrawableCullCallback* asDrawableCullCallback() const { return osg::DrawableCullCallback::asDrawableCullCallback(); }
524 virtual osgGA::EventHandler* asEventHandler() { return osgGA::EventHandler::asEventHandler(); }
525 virtual const osgGA::EventHandler* asEventHandler() const { return osgGA::EventHandler::asEventHandler(); }
527 // use the osgGA::GUIEventHandler implementation of run.
528 virtual bool run(osg::Object* object, osg::Object* data) { return osgGA::GUIEventHandler::run(object, data); }
530 virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
532 virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const;
536 virtual ~InteractiveImageHandler() {}
538 InteractiveImageHandler():
539 _fullscreen(false) {}
541 InteractiveImageHandler(const InteractiveImageHandler&,const osg::CopyOp& = osg::CopyOp::SHALLOW_COPY):
542 osg::Object(), osg::Callback(), osgGA::GUIEventHandler(), osg::DrawableCullCallback(), _fullscreen(false) {}
544 bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const;
546 void resize(int width, int height);
548 osg::observer_ptr<osg::Image> _image;
549 osg::observer_ptr<osg::Texture2D> _texture;
552 osg::observer_ptr<osg::Camera> _camera;