WindowManager 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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. // Code by: Jeremy Moles (cubicool) 2007-2008
  14. #ifndef OSGWIDGET_WINDOW_MANAGER
  15. #define OSGWIDGET_WINDOW_MANAGER
  16. #include <osg/Switch>
  17. #include <osg/Uniform>
  18. #include <osg/Drawable>
  19. #include <osgGA/GUIEventAdapter>
  20. #include <osgUtil/LineSegmentIntersector>
  21. #include <osgViewer/View>
  22. #include <osgWidget/ScriptEngine>
  23. #include <osgWidget/StyleManager>
  24. #include <osgWidget/Window>
  25. namespace osgWidget {
  26. // TODO: It should be possible to use something other than osgWidget/ViewerEventHandlers
  27. // to handle all of these events. In fact, I need to create an SDL example showing this.
  28. // A private typedef that we use for pickAtXY() below.
  29. typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
  30. // A WindowManager performs pointer interaction with the topmost (highest Z) Widget,
  31. // and performs keyboard input on the currently focused Window->Widget.
  32. class OSGWIDGET_EXPORT WindowManager: public osg::Switch, public UIObjectParent<Window> {
  33. public:
  34. enum WmFlags {
  35. WM_USE_LUA = 0x00000001,
  36. WM_USE_PYTHON = 0x00000002,
  37. WM_USE_RENDERBINS = 0x00000004,
  38. WM_PICK_DEBUG = 0x00000008
  39. };
  40. enum PointerDirection {
  41. PD_NONE = 0x00000000,
  42. PD_LEFT = 0x00000001,
  43. PD_RIGHT = 0x00000002,
  44. PD_UP = 0x00000004,
  45. PD_DOWN = 0x00000008
  46. };
  47. enum PointerFocusMode {
  48. PFM_FOCUS = 0x00000000,
  49. PFM_UNFOCUS = 0x00000001,
  50. PFM_SLOPPY = 0x00000002
  51. };
  52. public:
  53. META_Object(osgWidget, WindowManager);
  54. WindowManager(
  55. osgViewer::View* = 0,
  56. point_type = 0.0f,
  57. point_type = 0.0f,
  58. unsigned int = 0,
  59. unsigned int = 0
  60. );
  61. WindowManager(const WindowManager&, const osg::CopyOp&);
  62. virtual ~WindowManager();
  63. // A static method that will set both the _widget and _window data of an Event
  64. // reference from a passed-in Interface.
  65. static void setEventFromInterface(Event&, EventInterface*);
  66. // A static template method that will iterate over a container and return a
  67. // properly formed EventInterface*.
  68. template<typename T>
  69. static EventInterface* getFirstEventInterface(T&, Event&);
  70. bool pickAtXY (float, float, WidgetList&);
  71. bool setFocused (Window*);
  72. void setPointerXY (float, float);
  73. void setStyleManager (StyleManager*);
  74. void resizeAllWindows (bool = true);
  75. XYCoord windowXY (double, double) const;
  76. XYCoord localXY (double, double) const;
  77. // Methods all called by the ViewerEventHandlers::MouseHandler object, or
  78. // by some customer caller of your own. Examples of this to come...
  79. bool pointerMove (float, float);
  80. bool pointerDrag (float, float);
  81. bool mouseScroll (float, float);
  82. osg::Camera* createParentOrthoCamera();
  83. unsigned int getNodeMask() const {
  84. return _nodeMask;
  85. }
  86. point_type getWidth() const {
  87. return _width;
  88. }
  89. point_type getHeight() const {
  90. return _height;
  91. }
  92. bool isUsingLua() const {
  93. return (_flags & WM_USE_LUA) != 0;
  94. }
  95. bool isUsingPython() const {
  96. return (_flags & WM_USE_PYTHON) != 0;
  97. }
  98. bool isUsingRenderBins() const {
  99. return (_flags & WM_USE_RENDERBINS) != 0;
  100. }
  101. int getMouseKeysDown() const {
  102. int flag = 0;
  103. flag |= _leftDown ? osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON : 0;
  104. flag |= _middleDown ? osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON: 0;
  105. flag |= _rightDown ? osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON : 0;
  106. return flag;
  107. }
  108. ScriptEngine* getLuaEngine() {
  109. return _lua.get();
  110. }
  111. const ScriptEngine* getLuaEngine() const {
  112. return _lua.get();
  113. }
  114. ScriptEngine* getPythonEngine() {
  115. return _python.get();
  116. }
  117. const ScriptEngine* getPythonEngine() const {
  118. return _python.get();
  119. }
  120. StyleManager* getStyleManager() {
  121. return _styleManager.get();
  122. }
  123. const StyleManager* getStyleManager() const {
  124. return _styleManager.get();
  125. }
  126. PointerDirection getPointerVerticalDirection() const {
  127. return _lastVertical;
  128. }
  129. PointerDirection getPointerHorizontalDirection() const {
  130. return _lastHorizontal;
  131. }
  132. PointerFocusMode getPointerFocusMode() const {
  133. return _focusMode;
  134. }
  135. int getPointerDirectionVector() const {
  136. return _lastVertical | _lastHorizontal;
  137. }
  138. bool isPointerMovingUp() const {
  139. return _lastVertical == PD_UP;
  140. }
  141. bool isPointerMovingDown() const {
  142. return _lastVertical == PD_DOWN;
  143. }
  144. bool isPointerMovingLeft() const {
  145. return _lastHorizontal == PD_LEFT;
  146. }
  147. bool isPointerMovingRight() const {
  148. return _lastHorizontal == PD_RIGHT;
  149. }
  150. bool isPointerMovingVertically() const {
  151. return _lastVertical != PD_NONE;
  152. }
  153. bool isPointerMovingHorizontally() const {
  154. return _lastHorizontal != PD_NONE;
  155. }
  156. bool isLeftMouseButtonDown() const {
  157. return _leftDown;
  158. }
  159. bool isMiddleMouseButtonDown() const {
  160. return _middleDown;
  161. }
  162. bool isRightMouseButtonDown() const {
  163. return _rightDown;
  164. }
  165. bool isMouseScrollingUp() const {
  166. return _scrolling == osgGA::GUIEventAdapter::SCROLL_UP;
  167. }
  168. bool isMouseScrollingDown() const {
  169. return _scrolling == osgGA::GUIEventAdapter::SCROLL_DOWN;
  170. }
  171. bool setFocusedByName(const std::string& name) {
  172. return setFocused(getByName(name));
  173. }
  174. void setScrollingMotion(osgGA::GUIEventAdapter::ScrollingMotion sm) {
  175. _scrolling = sm;
  176. }
  177. void setPointerFocusMode(PointerFocusMode pfm) {
  178. _focusMode = pfm;
  179. }
  180. void setWidth(point_type w) {
  181. _width = w;
  182. }
  183. void setHeight(point_type h) {
  184. _height = h;
  185. }
  186. void setSize(point_type w, point_type h) {
  187. _width = w;
  188. _height = h;
  189. }
  190. void setWindowSize(point_type w, point_type h) {
  191. _windowWidth = w;
  192. _windowHeight = h;
  193. }
  194. // Wrappers around the real calls. These only pertains to mouse buttons,
  195. // particularly 3-button mice, although there are other more generic
  196. // "pointer" API methods.
  197. bool mousePushedLeft(float x, float y) {
  198. return _handleMousePushed(x, y, _leftDown);
  199. }
  200. bool mousePushedMiddle(float x, float y) {
  201. return _handleMousePushed(x, y, _middleDown);
  202. }
  203. bool mousePushedRight(float x, float y) {
  204. return _handleMousePushed(x, y, _rightDown);
  205. }
  206. bool mouseReleasedLeft(float x, float y) {
  207. return _handleMouseReleased(x, y, _leftDown);
  208. }
  209. bool mouseReleasedMiddle(float x, float y) {
  210. return _handleMouseReleased(x, y, _middleDown);
  211. }
  212. bool mouseReleasedRight(float x, float y) {
  213. return _handleMouseReleased(x, y, _rightDown);
  214. }
  215. // Keyboards wrappers, as above; takes the key and key's mask code, which
  216. // can be compared to osgGA::GUIEventAdapter::{KeySymbol,KeyModMask}.
  217. bool keyDown (int, int);
  218. bool keyUp (int, int);
  219. osgViewer::View* getView() { return _view; }
  220. const osgViewer::View* getView() const { return _view; }
  221. private:
  222. // A functor used to sort the Windows by their Z component in descending order.
  223. struct WindowZCompare
  224. {
  225. bool operator()(const ptr_type& x, const ptr_type& y) {
  226. return x.get()->getZ() > y.get()->getZ();
  227. }
  228. };
  229. // A functor used to sort the Windows by their BinNum component in descending order.
  230. struct WindowBinNumberCompare
  231. {
  232. bool operator()(const ptr_type& x, const ptr_type& y) {
  233. return
  234. x.get()->getOrCreateStateSet()->getBinNumber() >
  235. y.get()->getOrCreateStateSet()->getBinNumber()
  236. ;
  237. }
  238. };
  239. point_type _width;
  240. point_type _height;
  241. point_type _windowWidth;
  242. point_type _windowHeight;
  243. unsigned int _flags;
  244. unsigned int _nodeMask;
  245. osgViewer::View* _view;
  246. float _lastX;
  247. float _lastY;
  248. EventInterface* _lastEvent;
  249. EventInterface* _lastPush;
  250. PointerDirection _lastVertical;
  251. PointerDirection _lastHorizontal;
  252. PointerFocusMode _focusMode;
  253. bool _leftDown;
  254. bool _middleDown;
  255. bool _rightDown;
  256. osgGA::GUIEventAdapter::ScrollingMotion _scrolling;
  257. osg::ref_ptr<ScriptEngine> _lua;
  258. osg::ref_ptr<ScriptEngine> _python;
  259. osg::ref_ptr<StyleManager> _styleManager;
  260. osg::observer_ptr<Widget> _widget;
  261. osg::observer_ptr<Window> _focused;
  262. osg::observer_ptr<Window> _pickWindow;
  263. void childInserted (unsigned int);
  264. void childRemoved (unsigned int, unsigned int);
  265. bool _handleMousePushed (float, float, bool&);
  266. bool _handleMouseReleased (float, float, bool&);
  267. bool _handleMouseScrolled (float, float, bool = false);
  268. void _getPointerXYDiff (float&, float&);
  269. void _updatePickWindow (const WidgetList*, point_type, point_type);
  270. };
  271. // We use a template here because the container could be a list or a vector; or something
  272. // else that supports iteration!
  273. template<typename T>
  274. EventInterface* WindowManager::getFirstEventInterface(T& container, Event& ev) {
  275. if(!container.size()) return 0;
  276. // See if we can find a Widget that responds to this event...
  277. for(typename T::iterator i = container.begin(); i != container.end(); i++) {
  278. Widget* widget = i->get();
  279. // If so, set the _widget/_window members and return it.
  280. if(widget->getEventMask() & ev.type) {
  281. ev._window = widget->getParent();
  282. ev._widget = widget;
  283. return widget;
  284. }
  285. }
  286. // If we can't find a Widget that will accept this event, try and recurse all
  287. // of the parent Windows and find one that can.
  288. WindowList windowList;
  289. Window* parent = container.back()->getParent();
  290. if(parent) {
  291. parent->getParentList(windowList);
  292. // A WindowList from getParentList includes the Window the method was called
  293. // on, and the entire tree of parentage.
  294. for(WindowList::iterator i = windowList.begin(); i != windowList.end(); i++) {
  295. Window* window = i->get();
  296. if(window->getEventMask() & ev.type) {
  297. ev._window = window;
  298. return window;
  299. }
  300. }
  301. }
  302. return 0;
  303. }
  304. }
  305. #endif