123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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.
- */
- // Code by: Jeremy Moles (cubicool) 2007-2008
- #ifndef OSGWIDGET_WINDOW_MANAGER
- #define OSGWIDGET_WINDOW_MANAGER
- #include <osg/Switch>
- #include <osg/Uniform>
- #include <osg/Drawable>
- #include <osgGA/GUIEventAdapter>
- #include <osgUtil/LineSegmentIntersector>
- #include <osgViewer/View>
- #include <osgWidget/ScriptEngine>
- #include <osgWidget/StyleManager>
- #include <osgWidget/Window>
- namespace osgWidget {
- // TODO: It should be possible to use something other than osgWidget/ViewerEventHandlers
- // to handle all of these events. In fact, I need to create an SDL example showing this.
- // A private typedef that we use for pickAtXY() below.
- typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
- // A WindowManager performs pointer interaction with the topmost (highest Z) Widget,
- // and performs keyboard input on the currently focused Window->Widget.
- class OSGWIDGET_EXPORT WindowManager: public osg::Switch, public UIObjectParent<Window> {
- public:
- enum WmFlags {
- WM_USE_LUA = 0x00000001,
- WM_USE_PYTHON = 0x00000002,
- WM_USE_RENDERBINS = 0x00000004,
- WM_PICK_DEBUG = 0x00000008
- };
- enum PointerDirection {
- PD_NONE = 0x00000000,
- PD_LEFT = 0x00000001,
- PD_RIGHT = 0x00000002,
- PD_UP = 0x00000004,
- PD_DOWN = 0x00000008
- };
- enum PointerFocusMode {
- PFM_FOCUS = 0x00000000,
- PFM_UNFOCUS = 0x00000001,
- PFM_SLOPPY = 0x00000002
- };
- public:
- META_Object(osgWidget, WindowManager);
- WindowManager(
- osgViewer::View* = 0,
- point_type = 0.0f,
- point_type = 0.0f,
- unsigned int = 0,
- unsigned int = 0
- );
- WindowManager(const WindowManager&, const osg::CopyOp&);
- virtual ~WindowManager();
- // A static method that will set both the _widget and _window data of an Event
- // reference from a passed-in Interface.
- static void setEventFromInterface(Event&, EventInterface*);
- // A static template method that will iterate over a container and return a
- // properly formed EventInterface*.
- template<typename T>
- static EventInterface* getFirstEventInterface(T&, Event&);
- bool pickAtXY (float, float, WidgetList&);
- bool setFocused (Window*);
- void setPointerXY (float, float);
- void setStyleManager (StyleManager*);
- void resizeAllWindows (bool = true);
- XYCoord windowXY (double, double) const;
- XYCoord localXY (double, double) const;
- // Methods all called by the ViewerEventHandlers::MouseHandler object, or
- // by some customer caller of your own. Examples of this to come...
- bool pointerMove (float, float);
- bool pointerDrag (float, float);
- bool mouseScroll (float, float);
- osg::Camera* createParentOrthoCamera();
- unsigned int getNodeMask() const {
- return _nodeMask;
- }
- point_type getWidth() const {
- return _width;
- }
- point_type getHeight() const {
- return _height;
- }
- bool isUsingLua() const {
- return (_flags & WM_USE_LUA) != 0;
- }
- bool isUsingPython() const {
- return (_flags & WM_USE_PYTHON) != 0;
- }
- bool isUsingRenderBins() const {
- return (_flags & WM_USE_RENDERBINS) != 0;
- }
- int getMouseKeysDown() const {
- int flag = 0;
- flag |= _leftDown ? osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON : 0;
- flag |= _middleDown ? osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON: 0;
- flag |= _rightDown ? osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON : 0;
- return flag;
- }
- ScriptEngine* getLuaEngine() {
- return _lua.get();
- }
- const ScriptEngine* getLuaEngine() const {
- return _lua.get();
- }
- ScriptEngine* getPythonEngine() {
- return _python.get();
- }
- const ScriptEngine* getPythonEngine() const {
- return _python.get();
- }
- StyleManager* getStyleManager() {
- return _styleManager.get();
- }
- const StyleManager* getStyleManager() const {
- return _styleManager.get();
- }
- PointerDirection getPointerVerticalDirection() const {
- return _lastVertical;
- }
- PointerDirection getPointerHorizontalDirection() const {
- return _lastHorizontal;
- }
- PointerFocusMode getPointerFocusMode() const {
- return _focusMode;
- }
- int getPointerDirectionVector() const {
- return _lastVertical | _lastHorizontal;
- }
- bool isPointerMovingUp() const {
- return _lastVertical == PD_UP;
- }
- bool isPointerMovingDown() const {
- return _lastVertical == PD_DOWN;
- }
- bool isPointerMovingLeft() const {
- return _lastHorizontal == PD_LEFT;
- }
- bool isPointerMovingRight() const {
- return _lastHorizontal == PD_RIGHT;
- }
- bool isPointerMovingVertically() const {
- return _lastVertical != PD_NONE;
- }
- bool isPointerMovingHorizontally() const {
- return _lastHorizontal != PD_NONE;
- }
- bool isLeftMouseButtonDown() const {
- return _leftDown;
- }
- bool isMiddleMouseButtonDown() const {
- return _middleDown;
- }
- bool isRightMouseButtonDown() const {
- return _rightDown;
- }
- bool isMouseScrollingUp() const {
- return _scrolling == osgGA::GUIEventAdapter::SCROLL_UP;
- }
- bool isMouseScrollingDown() const {
- return _scrolling == osgGA::GUIEventAdapter::SCROLL_DOWN;
- }
- bool setFocusedByName(const std::string& name) {
- return setFocused(getByName(name));
- }
- void setScrollingMotion(osgGA::GUIEventAdapter::ScrollingMotion sm) {
- _scrolling = sm;
- }
- void setPointerFocusMode(PointerFocusMode pfm) {
- _focusMode = pfm;
- }
- void setWidth(point_type w) {
- _width = w;
- }
- void setHeight(point_type h) {
- _height = h;
- }
- void setSize(point_type w, point_type h) {
- _width = w;
- _height = h;
- }
- void setWindowSize(point_type w, point_type h) {
- _windowWidth = w;
- _windowHeight = h;
- }
- // Wrappers around the real calls. These only pertains to mouse buttons,
- // particularly 3-button mice, although there are other more generic
- // "pointer" API methods.
- bool mousePushedLeft(float x, float y) {
- return _handleMousePushed(x, y, _leftDown);
- }
- bool mousePushedMiddle(float x, float y) {
- return _handleMousePushed(x, y, _middleDown);
- }
- bool mousePushedRight(float x, float y) {
- return _handleMousePushed(x, y, _rightDown);
- }
- bool mouseReleasedLeft(float x, float y) {
- return _handleMouseReleased(x, y, _leftDown);
- }
- bool mouseReleasedMiddle(float x, float y) {
- return _handleMouseReleased(x, y, _middleDown);
- }
- bool mouseReleasedRight(float x, float y) {
- return _handleMouseReleased(x, y, _rightDown);
- }
- // Keyboards wrappers, as above; takes the key and key's mask code, which
- // can be compared to osgGA::GUIEventAdapter::{KeySymbol,KeyModMask}.
- bool keyDown (int, int);
- bool keyUp (int, int);
- osgViewer::View* getView() { return _view; }
- const osgViewer::View* getView() const { return _view; }
- private:
- // A functor used to sort the Windows by their Z component in descending order.
- struct WindowZCompare
- {
- bool operator()(const ptr_type& x, const ptr_type& y) {
- return x.get()->getZ() > y.get()->getZ();
- }
- };
- // A functor used to sort the Windows by their BinNum component in descending order.
- struct WindowBinNumberCompare
- {
- bool operator()(const ptr_type& x, const ptr_type& y) {
- return
- x.get()->getOrCreateStateSet()->getBinNumber() >
- y.get()->getOrCreateStateSet()->getBinNumber()
- ;
- }
- };
- point_type _width;
- point_type _height;
- point_type _windowWidth;
- point_type _windowHeight;
- unsigned int _flags;
- unsigned int _nodeMask;
- osgViewer::View* _view;
- float _lastX;
- float _lastY;
- EventInterface* _lastEvent;
- EventInterface* _lastPush;
- PointerDirection _lastVertical;
- PointerDirection _lastHorizontal;
- PointerFocusMode _focusMode;
- bool _leftDown;
- bool _middleDown;
- bool _rightDown;
- osgGA::GUIEventAdapter::ScrollingMotion _scrolling;
- osg::ref_ptr<ScriptEngine> _lua;
- osg::ref_ptr<ScriptEngine> _python;
- osg::ref_ptr<StyleManager> _styleManager;
- osg::observer_ptr<Widget> _widget;
- osg::observer_ptr<Window> _focused;
- osg::observer_ptr<Window> _pickWindow;
- void childInserted (unsigned int);
- void childRemoved (unsigned int, unsigned int);
- bool _handleMousePushed (float, float, bool&);
- bool _handleMouseReleased (float, float, bool&);
- bool _handleMouseScrolled (float, float, bool = false);
- void _getPointerXYDiff (float&, float&);
- void _updatePickWindow (const WidgetList*, point_type, point_type);
- };
- // We use a template here because the container could be a list or a vector; or something
- // else that supports iteration!
- template<typename T>
- EventInterface* WindowManager::getFirstEventInterface(T& container, Event& ev) {
- if(!container.size()) return 0;
- // See if we can find a Widget that responds to this event...
- for(typename T::iterator i = container.begin(); i != container.end(); i++) {
- Widget* widget = i->get();
- // If so, set the _widget/_window members and return it.
- if(widget->getEventMask() & ev.type) {
- ev._window = widget->getParent();
- ev._widget = widget;
- return widget;
- }
- }
- // If we can't find a Widget that will accept this event, try and recurse all
- // of the parent Windows and find one that can.
- WindowList windowList;
- Window* parent = container.back()->getParent();
- if(parent) {
- parent->getParentList(windowList);
- // A WindowList from getParentList includes the Window the method was called
- // on, and the entire tree of parentage.
- for(WindowList::iterator i = windowList.begin(); i != windowList.end(); i++) {
- Window* window = i->get();
- if(window->getEventMask() & ev.type) {
- ev._window = window;
- return window;
- }
- }
- }
- return 0;
- }
- }
- #endif
|