1/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2 *
3 * This software is open source and may be redistributed and/or modified under
4 * the terms of the GNU General Public License (GPL) version 2.0.
5 * The full license is in LICENSE.txt file included with this distribution,.
6 *
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * include LICENSE.txt for more details.
11*/
12
13#ifndef SLIDESHOWCONSTRUCTOR
14#define SLIDESHOWCONSTRUCTOR
15
16#include <osg/Vec3>
17#include <osg/Vec4>
18#include <osg/ImageUtils>
19#include <osg/Group>
20#include <osg/ClearNode>
21#include <osg/Switch>
22#include <osg/AnimationPath>
23#include <osg/TransferFunction>
24#include <osg/ImageStream>
25#include <osg/ImageSequence>
26#include <osg/ScriptEngine>
27#include <osgText/Text>
28#include <osgGA/GUIEventAdapter>
29
30#include <osgDB/FileUtils>
31
32#include <osgVolume/VolumeTile>
33#include <osgVolume/VolumeSettings>
34
35#include <osgPresentation/AnimationMaterial>
36#include <osgPresentation/SlideEventHandler>
37#include <osgPresentation/PropertyManager>
38#include <osgPresentation/Timeout>
39
40namespace osgPresentation
41{
42
43
44
45class OSGPRESENTATION_EXPORT HUDTransform : public osg::Transform
46{
47    public:
48
49        HUDTransform(HUDSettings* hudSettings);
50
51        virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const;
52
53        virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const;
54
55protected:
56
57        virtual ~HUDTransform();
58
59        osg::ref_ptr<HUDSettings> _hudSettings;
60
61};
62
63class OSGPRESENTATION_EXPORT SlideShowConstructor
64{
65public:
66
67
68    enum CoordinateFrame { SLIDE, MODEL };
69
70
71
72    LayerAttributes* getOrCreateLayerAttributes(osg::Node* node);
73
74    void setDuration(osg::Node* node,double duration)
75    {
76        getOrCreateLayerAttributes(node)->setDuration(duration);
77    }
78
79    void addKey(osg::Node* node,const KeyPosition& kp)
80    {
81        getOrCreateLayerAttributes(node)->addKey(kp);
82    }
83
84    void addRunString(osg::Node* node, const std::string& runString)
85    {
86        getOrCreateLayerAttributes(node)->addRunString(runString);
87    }
88
89    void setJump(osg::Node* node, const JumpData& jumpData)
90    {
91        getOrCreateLayerAttributes(node)->setJump(jumpData);
92    }
93
94    void addPresentationKey(const KeyPosition& kp)
95    {
96        if (!_presentationSwitch) createPresentation();
97        if (_presentationSwitch.valid()) addKey( _presentationSwitch.get(), kp);
98    }
99
100    void addPresentationRunString(const std::string& runString)
101    {
102        if (!_presentationSwitch) createPresentation();
103        if (_presentationSwitch.valid()) addRunString( _presentationSwitch.get(),runString);
104    }
105
106    void addSlideKey(const KeyPosition& kp)
107    {
108        if (!_slide) addSlide();
109        if (_slide.valid()) addKey(_slide.get(),kp);
110    }
111
112    void addSlideRunString(const std::string& runString)
113    {
114        if (!_slide) addSlide();
115        if (_slide.valid()) addRunString(_slide.get(),runString);
116    }
117
118    void setSlideJump(const JumpData& jumpData)
119    {
120        if (!_slide) addSlide();
121        if (_slide.valid()) setJump(_slide.get(),jumpData);
122    }
123
124    void addLayerKey(const KeyPosition& kp)
125    {
126        if (!_currentLayer) addLayer();
127        if (_currentLayer.valid()) addKey(_currentLayer.get(),kp);
128    }
129
130    void addLayerRunString(const std::string& runString)
131    {
132        if (!_currentLayer) addLayer();
133        if (_currentLayer.valid()) addRunString(_currentLayer.get(),runString);
134    }
135
136
137    void setLayerJump(const JumpData& jumpData)
138    {
139        if (!_currentLayer) addLayer();
140        if (_currentLayer.valid()) setJump(_currentLayer.get(),jumpData);
141    }
142
143
144
145    struct PositionData
146    {
147        PositionData():
148            frame(SlideShowConstructor::SLIDE),
149            position(0.0f,1.0f,0.0f),
150            //position(0.5f,0.5f,0.0f),
151            scale(1.0f,1.0f,1.0f),
152            rotate(0.0f,0.0f,0.0f,1.0f),
153            rotation(0.0f,0.0f,1.0f,0.0f),
154            absolute_path(false),
155            inverse_path(false),
156            path_time_offset(0.0),
157            path_time_multiplier(1.0f),
158            path_loop_mode(osg::AnimationPath::NO_LOOPING),
159            animation_material_time_offset(0.0),
160            animation_material_time_multiplier(1.0),
161            animation_material_loop_mode(AnimationMaterial::NO_LOOPING),
162            autoRotate(false),
163            autoScale(false),
164            hud(false) {}
165
166
167        bool requiresPosition() const
168        {
169            return (position[0]!=0.0f || position[1]!=1.0f || position[2]!=1.0f);
170        }
171
172        bool requiresScale() const
173        {
174            return (scale[0]!=1.0f || scale[1]!=1.0f || scale[2]!=1.0f);
175        }
176
177        bool requiresRotate() const
178        {
179            return rotate[0]!=0.0f;
180        }
181
182        bool requiresAnimation() const
183        {
184            return (rotation[0]!=0.0f || !path.empty());
185        }
186
187        bool requiresMaterialAnimation() const
188        {
189            return !animation_material_filename.empty() || !fade.empty();
190        }
191
192        CoordinateFrame                         frame;
193        osg::Vec3                               position;
194        osg::Vec3                               scale;
195        osg::Vec4                               rotate;
196        osg::Vec4                               rotation;
197        std::string                             animation_name;
198        bool                                    absolute_path;
199        bool                                    inverse_path;
200        double                                  path_time_offset;
201        double                                  path_time_multiplier;
202        osg::AnimationPath::LoopMode            path_loop_mode;
203        std::string                             path;
204        double                                  animation_material_time_offset;
205        double                                  animation_material_time_multiplier;
206        AnimationMaterial::LoopMode             animation_material_loop_mode;
207        std::string                             animation_material_filename;
208        std::string                             fade;
209        bool                                    autoRotate;
210        bool                                    autoScale;
211        bool                                    hud;
212    };
213
214    struct ModelData
215    {
216        ModelData() {}
217
218        std::string region;
219        std::string effect;
220        std::string options;
221    };
222
223    struct ImageData
224    {
225        ImageData():
226            width(1.0f),
227            height(1.0f),
228            region(0.0f,0.0f,1.0f,1.0f),
229            region_in_pixel_coords(false),
230            texcoord_rotate(0.0f),
231            loopingMode(osg::ImageStream::NO_LOOPING),
232            page(-1),
233            backgroundColor(1.0f,1.0f,1.0f,1.0f),
234            fps(30.0),
235            duration(-1.0),
236            imageSequence(false),
237            imageSequencePagingMode(osg::ImageSequence::PAGE_AND_DISCARD_USED_IMAGES),
238            imageSequenceInteractionMode(PLAY_AUTOMATICALLY_LIKE_MOVIE),
239            blendingHint(USE_IMAGE_ALPHA),
240            delayTime(0.0),
241            startTime(0.0),
242            stopTime(-1.0),
243            volume("")
244        {}
245
246        std::string                     options;
247        float                           width;
248        float                           height;
249        osg::Vec4                       region;
250        bool                            region_in_pixel_coords;
251        float                           texcoord_rotate;
252        osg::ImageStream::LoopingMode   loopingMode;
253        int                             page;
254        osg::Vec4                       backgroundColor;
255        double                          fps;
256        double                          duration;
257
258        bool                            imageSequence;
259        osg::ImageSequence::Mode        imageSequencePagingMode;
260
261        enum ImageSequenceInteractionMode
262        {
263            PLAY_AUTOMATICALLY_LIKE_MOVIE,
264            USE_MOUSE_X_POSITION,
265            USE_MOUSE_Y_POSITION
266        };
267        ImageSequenceInteractionMode imageSequenceInteractionMode;
268
269        enum BlendingHint
270        {
271            USE_IMAGE_ALPHA,
272            OFF,
273            ON
274        };
275
276        BlendingHint    blendingHint;
277
278        double          delayTime;
279        double          startTime;
280        double          stopTime;
281        std::string     volume;
282
283    };
284
285    struct VolumeData
286    {
287        typedef osgVolume::VolumeSettings::ShadingModel ShadingModel;
288        typedef osgVolume::VolumeSettings::Technique Technique;
289
290        VolumeData():
291            shadingModel(osgVolume::VolumeSettings::Standard),
292            useTabbedDragger(false),
293            useTrackballDragger(false),
294            region_in_pixel_coords(false),
295            alphaValue(),
296            cutoffValue(),
297            exteriorTransparencyFactorValue(),
298            sampleDensityValue(),
299            sampleRatioValue(),
300            colorSpaceOperation(osg::NO_COLOR_SPACE_OPERATION),
301            colorModulate(1.0f,1.0f,1.0f,1.0f),
302            technique(osgVolume::VolumeSettings::RayTraced)
303        {
304            hullPositionData.position = osg::Vec3(0.0,0.0,0.0);
305            hullPositionData.frame = osgPresentation::SlideShowConstructor::MODEL;
306        }
307
308        osg::ref_ptr<osgVolume::VolumeSettings> volumeSettings;
309
310        std::string                             options;
311        ShadingModel                            shadingModel;
312        osg::ref_ptr<osg::TransferFunction1D>   transferFunction;
313        bool                                    useTabbedDragger;
314        bool                                    useTrackballDragger;
315        std::string                             region;
316        bool                                    region_in_pixel_coords;
317        std::string                             alphaValue;
318        std::string                             cutoffValue;
319        std::string                             exteriorTransparencyFactorValue;
320        std::string                             sampleDensityValue;
321        std::string                             sampleDensityWhenMovingValue;
322
323        std::string                             sampleRatioValue;
324        std::string                             sampleRatioWhenMovingValue;
325
326        osg::ColorSpaceOperation                colorSpaceOperation;
327        osg::Vec4                               colorModulate;
328        Technique                               technique;
329        std::string                             hull;
330        PositionData                            hullPositionData;
331    };
332
333
334    struct FontData
335    {
336        FontData():
337            font("fonts/arial.ttf"),
338            layout(osgText::Text::LEFT_TO_RIGHT),
339            alignment(osgText::Text::LEFT_BASE_LINE),
340            axisAlignment(osgText::Text::XZ_PLANE),
341            characterSizeMode(osgText::Text::OBJECT_COORDS),
342            characterSize(0.04f),
343            maximumHeight(1.0f),
344            maximumWidth(1.0f),
345            color(1.0f,1.0f,1.0f,1.0f) {}
346
347        std::string                         font;
348        osgText::Text::Layout               layout;
349        osgText::Text::AlignmentType        alignment;
350        osgText::Text::AxisAlignment        axisAlignment;
351        osgText::Text::CharacterSizeMode    characterSizeMode;
352        float                               characterSize;
353        float                               maximumHeight;
354        float                               maximumWidth;
355        osg::Vec4                           color;
356    };
357
358    enum ScriptCallbackType
359    {
360        UPDATE_SCRIPT,
361        EVENT_SCRIPT
362    };
363
364    typedef std::pair<ScriptCallbackType, std::string> ScriptPair;
365
366    struct ScriptData
367    {
368        ScriptData() {}
369
370        typedef std::vector<ScriptPair> Scripts;
371        Scripts scripts;
372
373        bool hasScripts() const { return !scripts.empty(); }
374    };
375
376    SlideShowConstructor(osgDB::Options* options);
377
378    void createPresentation();
379
380    void setBackgroundColor(const osg::Vec4& color, bool updateClearNode);
381    const osg::Vec4& getBackgroundColor() const { return _backgroundColor; }
382
383    void setTextColor(const osg::Vec4& color);
384    const osg::Vec4& getTextColor() const { return _textFontDataDefault.color; }
385
386    void setPresentationName(const std::string& name);
387
388    void setPresentationAspectRatio(float aspectRatio);
389
390    void setPresentationAspectRatio(const std::string& str);
391
392    void setPresentationDuration(double duration);
393
394    void addScriptEngine(const std::string& scriptEngineName);
395
396    void addScriptFile(const std::string& name, const std::string& filename);
397
398    void addScript(const std::string& name, const std::string& language, const std::string& script);
399
400    void addSlide();
401
402    void selectSlide(int slideNum);
403
404
405    void setSlideTitle(const std::string& name, PositionData& positionData, FontData& fontData)
406    {
407        _titlePositionData = positionData;
408        _titleFontData = fontData;
409        _slideTitle = name;
410    }
411
412    void setSlideBackgrondHUD(bool hud) { _slideBackgroundAsHUD = hud; }
413    void setSlideBackground(const std::string& name) { _slideBackgroundImageFileName = name; }
414
415    void setSlideDuration(double duration);
416
417    Timeout* addTimeout();
418
419    void addLayer(bool inheritPreviousLayers=true, bool defineAsBaseLayer=false);
420
421    void selectLayer(int layerNum);
422
423    void setLayerDuration(double duration);
424
425
426    // title settings
427    FontData& getTitleFontData() { return _titleFontData; }
428    FontData& getTitleFontDataDefault() { return _titleFontDataDefault; }
429
430    PositionData& getTitlePositionData() { return _titlePositionData; }
431    PositionData& getTitlePositionDataDefault() { return _titlePositionDataDefault; }
432
433    // text settings
434    FontData& getTextFontData() { return _textFontData; }
435    FontData& getTextFontDataDefault() { return _textFontDataDefault; }
436
437    PositionData& getTextPositionData() { return _textPositionData; }
438    PositionData& getTextPositionDataDefault() { return _textPositionDataDefault; }
439
440    void translateTextCursor(const osg::Vec3& delta) { _textPositionData.position += delta; }
441
442    // image settings
443    PositionData& getImagePositionData() { return _imagePositionData; }
444    PositionData& getImagePositionDataDefault() { return _imagePositionDataDefault; }
445
446    // model settings
447    PositionData& getModelPositionData() { return _modelPositionData; }
448    PositionData& getModelPositionDataDefault() { return _modelPositionDataDefault; }
449
450
451    enum PresentationContext {
452        CURRENT_PRESENTATION,
453        CURRENT_SLIDE,
454        CURRENT_LAYER
455    };
456
457    void addEventHandler(PresentationContext presentationContext, osg::ref_ptr<osgGA::GUIEventHandler> handler);
458
459    void keyToDoOperation(PresentationContext presentationContext, int key, Operation operation, const JumpData& jumpData=JumpData());
460    void keyToDoOperation(PresentationContext presentationContext, int key, const std::string& command, Operation operation,  const JumpData& jumpData=JumpData());
461    void keyEventOperation(PresentationContext presentationContext, int key, const KeyPosition& keyPos,  const JumpData& jumpData=JumpData());
462
463    void layerClickToDoOperation(Operation operation,  const JumpData& jumpData=JumpData());
464    void layerClickToDoOperation(const std::string& command, Operation operation,  const JumpData& jumpData=JumpData());
465    void layerClickEventOperation(const KeyPosition& keyPos,  const JumpData& jumpData=JumpData());
466
467    void addPropertyAnimation(PresentationContext presentationContext, PropertyAnimation* propertyAnimation);
468
469    void addScriptCallback(PresentationContext presentationContext, ScriptCallbackType scriptCallbackType, const std::string& functionName);
470
471    void addScriptToNode(ScriptCallbackType scriptCallbackType, const std::string& name, osg::Node* node);
472
473    void addScriptsToNode(const ScriptData& scriptData, osg::Node* node);
474
475    void addToCurrentLayer(osg::Node* subgraph);
476
477    void addBullet(const std::string& bullet, PositionData& positionData, FontData& fontData, const ScriptData& scriptData);
478
479    void addParagraph(const std::string& paragraph, PositionData& positionData, FontData& fontData, const ScriptData& scriptData);
480
481    osg::Image* readImage(const std::string& filename, const ImageData& imageData);
482
483    void addImage(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const ScriptData& scriptData);
484
485    void addStereoImagePair(const std::string& filenameLeft, const ImageData& imageDataLeft, const std::string& filenameRight,const ImageData& imageDataRight, const PositionData& positionData, const ScriptData& scriptData);
486
487    void addGraph(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const ScriptData& scriptData);
488    void addVNC(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const std::string& password, const ScriptData& scriptData);
489    void addBrowser(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const ScriptData& scriptData);
490    void addPDF(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const ScriptData& scriptData);
491    osg::Image* addInteractiveImage(const std::string& filename,const PositionData& positionData, const ImageData& imageData, const ScriptData& scriptData);
492
493    void addModel(osg::Node* subgraph, const PositionData& positionData, const ModelData& modelData, const ScriptData& scriptData);
494
495    void addModel(const std::string& filename, const PositionData& positionData, const ModelData& modelData, const ScriptData& scriptData);
496
497    void setUpVolumeScalarProperty(osgVolume::VolumeTile* tile, osgVolume::ScalarProperty* property, const std::string& source);
498
499    void addVolume(const std::string& filename, const PositionData& positionData, const VolumeData& volumeData, const ScriptData& scriptData);
500
501    osg::Group* takePresentation() { return _root.release(); }
502
503    osg::Group* getPresentation() { return _root.get(); }
504
505    osg::Switch* getPresentationSwitch() { return _presentationSwitch.get(); }
506
507    osg::Switch* getCurrentSlide() { return _slide.get(); }
508
509    void pushCurrentLayer(osg::Group* newLayerGroup);
510    void popCurrentLayer();
511
512    osg::Group* getCurrentLayer() { return _currentLayer.get(); }
513
514    void setLoopPresentation(bool loop) { _loopPresentation = loop; }
515    bool getLoopPresentation() const { return _loopPresentation; }
516
517    void setAutoSteppingActive(bool flag = true) { _autoSteppingActive = flag; }
518    bool getAutoSteppingActive() const { return _autoSteppingActive; }
519
520    void setHUDSettings(HUDSettings* hudSettings) { _hudSettings = hudSettings; }
521    HUDSettings* getHUDSettings() { return _hudSettings.get(); }
522    const HUDSettings* getHUDSettings() const { return _hudSettings.get(); }
523
524    osg::ScriptEngine* getOrCreateScriptEngine(const std::string& language);
525
526protected:
527
528    void findImageStreamsAndAddCallbacks(osg::Node* node);
529
530    osg::Geometry* createTexturedQuadGeometry(const osg::Vec3& pos, const osg::Vec4& rotation, float width,float height, osg::Image* image, bool& usedTextureRectangle);
531    void setUpMovieVolume(osg::Node* subgraph, osg::ImageStream* imageStream, const ImageData& imageData);
532
533    osg::Vec3 computePositionInModelCoords(const PositionData& positionData) const;
534    void updatePositionFromInModelCoords(const osg::Vec3& vertex, PositionData& positionData) const;
535
536    osg::Vec3 convertSlideToModel(const osg::Vec3& position) const;
537    osg::Vec3 convertModelToSlide(const osg::Vec3& position) const;
538
539    osg::AnimationPathCallback* getAnimationPathCallback(const PositionData& positionData);
540
541    osg::Node* attachMaterialAnimation(osg::Node* model, const PositionData& positionData);
542    bool attachTexMat(osg::StateSet* stateset, const ImageData& imageData, float s, float t, bool textureRectangle);
543
544    osg::StateSet* createTransformStateSet()
545    {
546        osg::StateSet* stateset = new osg::StateSet;
547        #if !defined(OSG_GLES2_AVAILABLE)
548            stateset->setMode(GL_NORMALIZE,osg::StateAttribute::ON);
549        #endif
550        return stateset;
551    }
552
553    osg::Node* decorateSubgraphForPosition(osg::Node* node, PositionData& positionData);
554    osg::Node* decorateSubgraphForPositionAndAnimation(osg::Node* node, const PositionData& positionData);
555
556    osg::ref_ptr<osgDB::Options> _options;
557
558    osg::Vec3   _slideOrigin;
559    osg::Vec3   _eyeOrigin;
560    double      _slideWidth;
561    double      _slideHeight;
562    double      _slideDistance;
563    unsigned int _leftEyeMask;
564    unsigned int _rightEyeMask;
565
566    osg::ref_ptr<HUDSettings> _hudSettings;
567
568    // title settings
569    FontData        _titleFontData;
570    FontData        _titleFontDataDefault;
571
572    PositionData    _titlePositionData;
573    PositionData    _titlePositionDataDefault;
574
575    // text settings
576    FontData        _textFontData;
577    FontData        _textFontDataDefault;
578
579    PositionData    _textPositionData;
580    PositionData    _textPositionDataDefault;
581
582    // image settings
583    PositionData    _imagePositionData;
584    PositionData    _imagePositionDataDefault;
585
586    // model settings
587    PositionData    _modelPositionData;
588    PositionData    _modelPositionDataDefault;
589
590
591    bool        _loopPresentation;
592    bool        _autoSteppingActive;
593    osg::Vec4   _backgroundColor;
594    std::string _presentationName;
595    double      _presentationDuration;
596
597    osg::ref_ptr<osgPresentation::PropertyManager> _propertyManager;
598    osg::ref_ptr<osgPresentation::PropertyEventCallback> _propertyEventCallback;
599
600    osg::ref_ptr<osg::Group>        _root;
601    osg::ref_ptr<osg::Switch>       _presentationSwitch;
602
603    typedef std::map< std::string, osg::ref_ptr<osg::ScriptEngine> > ScriptEngineMap;
604    ScriptEngineMap _scriptEngines;
605
606    typedef std::map< std::string, osg::ref_ptr<osg::Script> > ScriptMap;
607    ScriptMap                        _scripts;
608
609    osg::ref_ptr<osg::ClearNode>    _slideClearNode;
610    osg::ref_ptr<osg::Switch>       _slide;
611    std::string                     _slideTitle;
612    std::string                     _slideBackgroundImageFileName;
613    bool                            _slideBackgroundAsHUD;
614
615    osg::ref_ptr<osg::Group>        _previousLayer;
616    osg::ref_ptr<osg::Group>        _currentLayer;
617    typedef std::vector< osg::ref_ptr<osg::Group> > LayerStack;
618    LayerStack                      _layerStack;
619
620    osg::ref_ptr<FilePathData>      _filePathData;
621
622    osg::ref_ptr<osg::Group>                _layerToApplyEventCallbackTo;
623
624    typedef std::list< osg::ref_ptr<osgGA::GUIEventHandler> > EventHandlerList;
625    EventHandlerList _currentEventCallbacksToApply;
626
627
628    std::string findFileAndRecordPath(const std::string& filename);
629
630    void recordOptionsFilePath(const osgDB::Options* options);
631
632};
633
634}
635
636#endif
637