GraphicsWindow 12.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGVIEWER_GRAPHICWINDOW
#define OSGVIEWER_GRAPHICWINDOW 1

#include <osg/GraphicsContext>
#include <osg/Notify>

#include <osgGA/EventQueue>
#include <osgGA/GUIActionAdapter>

#include <osgViewer/Export>


extern "C"
{
    typedef void (* CGraphicsWindowFunction) (void);
}

namespace osgViewer {

class View;


/** Base class for providing Windowing API agnostic access to creating and managing graphics window and events.
  * Note, the GraphicsWindow is subclassed from osg::GraphicsContext, and to provide an implemention you'll need to implement its
  * range of pure virtual functions, you'll find these all have naming convention methodNameImplemention(..).
  * GraphicsWindow adds the event queue on top of the GraphicsContext, thereby adding a mechanism for adapting Windowing events
  * as well as basics graphics context work, you should wire up custom GraphicsWindowImplementation to push their events through
  * into the EventQueue. */
class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgGA::GUIActionAdapter
{
    public:

        GraphicsWindow() { _eventQueue = new osgGA::EventQueue; _eventQueue->setGraphicsContext(this); }

        virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsWindow*>(object)!=0; }
        virtual const char* libraryName() const { return "osgViewer"; }
        virtual const char* className() const { return "GraphicsWindow"; }

        void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; }
        osgGA::EventQueue* getEventQueue() { return _eventQueue.get(); }
        const osgGA::EventQueue* getEventQueue() const { return _eventQueue.get(); }

        virtual void checkEvents() {}

        /** Set the window's position and size.*/
        void setWindowRectangle(int x, int y, int width, int height)
        {
            if (setWindowRectangleImplementation(x ,y ,width, height) && _traits.valid())
            {
                resized(x,y,width,height);
            }
        }

        /** implementation of setWindowRectangle, should be implemented by derived classes */
        virtual bool setWindowRectangleImplementation(int /*x*/, int /*y*/, int /*width*/, int /*height*/) { osg::notify(osg::NOTICE)<<"GraphicsWindow::setWindowRectangleImplementation(..) not implemented."<<std::endl; return false; }

        /** Get the window's position and size.*/
        virtual void getWindowRectangle(int& x, int& y, int& width, int& height) { if (_traits.valid()) { x = _traits->x; y = _traits->y; width = _traits->width; height = _traits->height; }  }

        /** Set Window decoration.*/
        void setWindowDecoration(bool flag)
        {
            if (setWindowDecorationImplementation(flag) && _traits.valid())
            {
                _traits->windowDecoration = flag;
            }
        }

        /** implementation of setWindowDecoration, should be implemented by derived classes */
        virtual bool setWindowDecorationImplementation(bool /*flag*/) {  osg::notify(osg::NOTICE)<<"GraphicsWindow::setWindowDecorationImplementation(..) not implemented."<<std::endl; return false; }


        /** Set Window decoration.*/
        virtual bool getWindowDecoration() const { return _traits.valid() ? _traits->windowDecoration : false; }

        /** Get focus.*/
        virtual void grabFocus() { osg::notify(osg::NOTICE)<<"GraphicsWindow::grabFocus(..) not implemented."<<std::endl; }

        /** Get focus on if the pointer is in this window.*/
        virtual void grabFocusIfPointerInWindow() { osg::notify(osg::NOTICE)<<"GraphicsWindow::grabFocusIfPointerInWindow(..) not implemented."<<std::endl; }

        /** Raise the window to the top.*/
        virtual void raiseWindow() { osg::notify(osg::NOTICE)<<"GraphicsWindow::raiseWindow(..) not implemented."<<std::endl; }

        /** Mouse cursor types, the same ones already present with ancient glut ... */
        enum MouseCursor {
            InheritCursor,
            NoCursor,
            RightArrowCursor,
            LeftArrowCursor,
            InfoCursor,
            DestroyCursor,
            HelpCursor,
            CycleCursor,
            SprayCursor,
            WaitCursor,
            TextCursor,
            CrosshairCursor,
            HandCursor,
            UpDownCursor,
            LeftRightCursor,
            TopSideCursor,
            BottomSideCursor,
            LeftSideCursor,
            RightSideCursor,
            TopLeftCorner,
            TopRightCorner,
            BottomRightCorner,
            BottomLeftCorner
        };

        /** Set the name of the window */
        virtual void setWindowName(const std::string& /*name*/) { osg::notify(osg::NOTICE)<<"GraphicsWindow::setWindowName(..) not implemented."<<std::endl; }

        /** Return the name of the window */
        virtual std::string getWindowName() { return _traits.valid() ? _traits->windowName : ""; }

        /** Switch on/off the cursor.*/
        virtual void useCursor(bool cursorOn) { setCursor(cursorOn ? InheritCursor : NoCursor); }

        /** Set mouse cursor to a specific shape.*/
        virtual void setCursor(MouseCursor /*mouseCursor*/) { osg::notify(osg::NOTICE)<<"GraphicsWindow::setCursor(..) not implemented."<<std::endl; }

        /** Create a new mouse cursor from the usual bitmap data.*/
        //virtual MouseCursor createCursor(const char *data, const char *mask, unsigned w, unsigned h, unsigned hotx, unsigned hoty) { osg::notify(osg::NOTICE)<<"GraphicsWindow::createCursor(..) not implemented."<<std::endl; }

        /** Set sync-to-vblank. */
        virtual void setSyncToVBlank(bool on)
        {
            osg::notify(osg::NOTICE) << "GraphicsWindow::setSyncToVBlank(" << on << ") not implemented." << std::endl;
        }

        bool getSyncToVBlank() const { return _traits.valid() ? _traits->vsync : true; }

        /** Set swap group. */
        virtual void setSwapGroup(bool on, GLuint group, GLuint barrier)
        {
            osg::notify(osg::NOTICE) << "GraphicsWindow::setSwapGroup(" << on << " " << group << " " << barrier << ") not implemented." << std::endl;
        }

        void getSwapGroup(bool& on, GLuint& group, GLuint& barrier) const { on = _traits->swapGroupEnabled; group = _traits->swapGroup; barrier = _traits->swapBarrier; }

    public:

        /** Return whether a valid and usable GraphicsContext has been created.*/
        virtual bool valid() const { osg::notify(osg::NOTICE)<<"GraphicsWindow::valid() not implemented."<<std::endl; return false; }

        /** Realize the GraphicsContext implementation,
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual bool realizeImplementation() { osg::notify(osg::NOTICE)<<"GraphicsWindow::realizeImplementation() not implemented."<<std::endl; return false; }

        /** Return true if the graphics context has been realized, and is ready to use, implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual bool isRealizedImplementation() const  { osg::notify(osg::NOTICE)<<"GraphicsWindow::isRealizedImplementation() not implemented."<<std::endl; return false; }

        /** Close the graphics context implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual void closeImplementation()  { osg::notify(osg::NOTICE)<<"GraphicsWindow::closeImplementation() not implemented."<<std::endl; }

        /** Make this graphics context current implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual bool makeCurrentImplementation()  { osg::notify(osg::NOTICE)<<"GraphicsWindow::makeCurrentImplementation() not implemented."<<std::endl; return false;}

        /** Make this graphics context current with specified read context implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual bool makeContextCurrentImplementation(GraphicsContext* /*readContext*/)  { osg::notify(osg::NOTICE)<<"GraphicsWindow::makeContextCurrentImplementation(..) not implemented."<<std::endl; return false;}

        /** Release the graphics context.*/
        virtual bool releaseContextImplementation() {  osg::notify(osg::NOTICE)<<"GraphicsWindow::releaseContextImplementation(..) not implemented."<<std::endl; return false; }

        /** Pure virtual, Bind the graphics context to associated texture implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual void bindPBufferToTextureImplementation(GLenum /*buffer*/)  { osg::notify(osg::NOTICE)<<"GraphicsWindow::bindPBufferToTextureImplementation(..) not implemented."<<std::endl; }

        /** Swap the front and back buffers implementation.
          * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
        virtual void swapBuffersImplementation()  { osg::notify(osg::NOTICE)<<"GraphicsWindow:: swapBuffersImplementation() not implemented."<<std::endl; }

    public:

        typedef std::list<osgViewer::View*> Views;
        /** Returns the list of views (osgViewer::View) attached to this GraphicsWindow.
         *  Internally, the method walks through all the cameras and collects all the views attached to the cameras.*/
        void getViews(Views& views);

        // Override from GUIActionAdapter
        virtual void requestRedraw();

        // Override from GUIActionAdapter
        virtual void requestContinuousUpdate(bool /*needed*/=true) {}

        // Override from GUIActionAdapter
        virtual void requestWarpPointer(float /*x*/,float /*y*/) {}


    protected:

        osg::ref_ptr<osgGA::EventQueue> _eventQueue;

};


class GraphicsWindowEmbedded : public GraphicsWindow
{
    public:

        GraphicsWindowEmbedded(osg::GraphicsContext::Traits* traits=0)
        {
            _traits = traits;

            init();

        }

        GraphicsWindowEmbedded(int x, int y, int width, int height)
        {
            _traits = new GraphicsContext::Traits;
            _traits->x = x;
            _traits->y = y;
            _traits->width = width;
            _traits->height = height;

            init();
        }

        virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsWindowEmbedded*>(object)!=0; }
        virtual const char* libraryName() const { return "osgViewer"; }
        virtual const char* className() const { return "GraphicsWindowEmbedded"; }

        void init()
        {
            if (valid())
            {
                setState( new osg::State );
                getState()->setGraphicsContext(this);

                if (_traits.valid() && _traits->sharedContext)
                {
                    getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
                    incrementContextIDUsageCount( getState()->getContextID() );
                }
                else
                {
                    getState()->setContextID( osg::GraphicsContext::createNewContextID() );
                }
            }
        }

        // dummy implementations, assume that graphics context is *always* current and valid.
        virtual bool valid() const { return true; }
        virtual bool realizeImplementation() { return true; }
        virtual bool isRealizedImplementation() const  { return true; }
        virtual void closeImplementation() {}
        virtual bool makeCurrentImplementation() { return true; }
        virtual bool releaseContextImplementation() { return true; }
        virtual void swapBuffersImplementation() {}
        virtual void grabFocus() {}
        virtual void grabFocusIfPointerInWindow() {}
        virtual void raiseWindow() {}
};

struct GraphicsWindowFunctionProxy
{
    GraphicsWindowFunctionProxy(CGraphicsWindowFunction function) { (function)(); }
};

#define USE_GRAPICSWINDOW_IMPLEMENTATION(ext) \
    extern "C" void graphicswindow_##ext(void); \
    static osgViewer::GraphicsWindowFunctionProxy graphicswindowproxy_##ext(graphicswindow_##ext);

#if defined(_WIN32)
    #define USE_GRAPHICSWINDOW()  USE_GRAPICSWINDOW_IMPLEMENTATION(Win32)
#elif defined(__APPLE__)
    #define USE_GRAPHICSWINDOW()  USE_GRAPICSWINDOW_IMPLEMENTATION(Carbon)
#else
    #define USE_GRAPHICSWINDOW()  USE_GRAPICSWINDOW_IMPLEMENTATION(X11)
#endif

}

#endif