Thanks Mario, fix merged and submitted to SVN
On Tue, Jul 22, 2008 at 6:36 AM, Mario Valle <[EMAIL PROTECTED]> wrote: > The attached osgWidget source solves three compilation warnings on VC 7.1 on > WindowsXP (OSG 2.5.5). > BTW the construct is absolutely legal C++, but VC 7.1 has a different > idea... > Hope it helps > mario > > -- > Ing. Mario Valle > Data Analysis and Visualization Services | > http://www.cscs.ch/~mvalle > Swiss National Supercomputing Centre (CSCS) | Tel: +41 (91) 610.82.60 > v. Cantonale Galleria 2, 6928 Manno, Switzerland | Fax: +41 (91) 610.82.82 > > > // -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008 > // $Id: WindowManager.cpp 66 2008-07-14 21:54:09Z cubicool $ > > #include <iostream> > #include <algorithm> > #include <osg/io_utils> > #include <osgWidget/Types> > #include <osgWidget/Util> > #include <osgWidget/WindowManager> > #include <osgWidget/Lua> > #include <osgWidget/Python> > #include <osgWidget/Box> > #include <osgWidget/Label> > > namespace osgWidget { > > WindowManager::WindowManager( > osgViewer::View* view, > point_type width, > point_type height, > unsigned int nodeMask, > unsigned int flags > ): > _width (width), > _height (height), > _zNear (0.0f), > _zFar (-1.0f), > _numForeground (0.0f), > _numBackground (0.0f), > _flags (flags), > _nodeMask (nodeMask), > _view (view), > _lastX (0.0f), > _lastY (0.0f), > _lastEvent (0), > _lastPush (0), > _lastVertical (PD_NONE), > _lastHorizontal (PD_NONE), > _focusMode (PFM_FOCUS), > _leftDown (false), > _middleDown (false), > _rightDown (false), > _scrolling (osgGA::GUIEventAdapter::SCROLL_NONE), > _styleManager (new StyleManager()) { > _name = generateRandomName("WindowManager"); > > if(_flags & WM_USE_LUA) { > _lua = new LuaEngine(this); > > if(!_lua->initialize()) warn() << "Error creating LuaEngine." > << std::endl; > } > > if(_flags & WM_USE_PYTHON) { > _python = new PythonEngine(this); > > if(!_python->initialize()) warn() << "Error creating > PythonEngine." << std::endl; > } > > // Setup our picking debug (is debug the right word here?) Window... > if(_flags & WM_PICK_DEBUG) { > _pickWindow = new Box("PickWindow", Box::VERTICAL); > > Label* label = new Label("PickLabel"); > > label->setFontSize(13); > label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f); > label->setFont("fonts/VeraMono.ttf"); > label->setPadding(5.0f); > label->setCanFill(true); > > _pickWindow->getBackground()->setColor(0.0f, 0.0f, 0.0f, > 0.85f); > _pickWindow->addWidget(label); > _pickWindow->setNodeMask(~_nodeMask); > _pickWindow->removeEventMask(EVENT_MASK_FOCUS); > _pickWindow->setStrata(Window::STRATA_FOREGROUND); > > addChild(_pickWindow.get()); > > _updatePickWindow(0, 0, 0); > } > > if(!(_flags & WM_NO_BETA_WARN)) { > Box* box = new Box("BetaWarningBox", Box::VERTICAL); > Label* label = new Label("BetaWarning"); > > label->setFontSize(15); > label->setFontColor(0.0f, 0.0f, 1.0f, 1.0f); > label->setFont("fonts/arial.ttf"); > label->setPadding(5.0f); > label->setCanFill(true); > label->setLabel("This is BETA software! Please see: > http://osgwidget.googlecode.com"); > > box->getBackground()->setColor(1.0f, 0.7f, 0.0f, 1.0f); > box->addWidget(label); > box->setNodeMask(~_nodeMask); > box->removeEventMask(EVENT_MASK_FOCUS); > box->setStrata(Window::STRATA_BACKGROUND); > box->setOrigin(0.0f, 0.0f); > > addChild(box); > > box->resizePercent(100.0f, 0.0f); > } > } > > WindowManager::WindowManager(const WindowManager& wm, const osg::CopyOp& > co): > osg::Switch(wm, co) { > } > > WindowManager::~WindowManager() { > if(_flags & WM_USE_LUA) _lua->close(); > > if(_flags & WM_USE_PYTHON) _python->close(); > } > > void WindowManager::setEventFromInterface(Event& ev, EventInterface* ei) { > Widget* widget = dynamic_cast<Widget*>(ei); > Window* window = dynamic_cast<Window*>(ei); > > if(widget) { > ev._window = widget->getParent(); > ev._widget = widget; > } > > else if(window) ev._window = window; > } > > bool WindowManager::_handleMousePushed(float x, float y, bool& down) { > down = true; > > Event ev(this, EVENT_MOUSE_PUSH); > > WidgetList widgetList; > > if(!pickAtXY(x, y, widgetList)) return false; > > ev.makeMouse(x, y); > > _lastPush = getFirstEventInterface(widgetList, ev); > > if(!_lastPush) return false; > > bool handled = _lastPush->callMethodAndCallbacks(ev); > > if(_focusMode != PFM_SLOPPY) { > if(ev._window) { > Window* topmostWindow = > ev._window->getTopmostParent(); > > setFocused(topmostWindow); > > if(ev._widget) topmostWindow->setFocused(ev._widget); > } > > // If the user wants to be able to "unfocus" the last Window. > else if(_focusMode == PFM_UNFOCUS) setFocused(0); > } > > return handled; > } > > bool WindowManager::_handleMouseReleased(float x, float y, bool& down) { > down = false; > > // If were were in a drag state, reset our boolean flag. > // if(_lastDrag) _lastDrag = 0; > > if(!_lastPush) return false; > > // By design, we can only release an EventInterface we previously > pressed. > // Whether or not we're ON the EventInterface when the release occurs > isn't important. > Event ev(this, EVENT_MOUSE_RELEASE); > > setEventFromInterface(ev, _lastPush); > > bool handled = _lastPush->callMethodAndCallbacks(ev); > > _lastPush = 0; > > return handled; > } > > void WindowManager::_getPointerXYDiff(float& x, float& y) { > x -= _lastX; > > if(isInvertedY()) y = -(y - _lastY); > > else y -= _lastY; > } > > void WindowManager::_updatePickWindow(const WidgetList* wl, point_type x, > point_type y) { > Label* label = > dynamic_cast<Label*>(_pickWindow->getByName("PickLabel")); > > if(!wl) { > setValue(0, false); > > return; > } > > setValue(0, true); > > std::stringstream ss; > > point_type xdiff = x; > point_type ydiff = y; > > _getPointerXYDiff(xdiff, ydiff); > > ss > << "At XY Coords: " << x << ", " << _height - y > << " ( diff " << xdiff << ", " << ydiff << " )" > << std::endl > ; > > const Window* parent = wl->back()->getParent(); > > ss > << "Window: " << parent->getName() > << " ( xyz " << parent->getPosition() << " )" > << " { zRange " << parent->getZRange() << " }" > << " < size " << parent->getSize() << " >" > << " EventMask: " << std::hex << parent->getEventMask() > << std::endl > ; > > for(WidgetList::const_iterator i = wl->begin(); i != wl->end(); i++) > { > Widget* widget = i->get(); > > ss > << " - " << widget->getName() > << " ( xyz " << widget->getPosition() << " )" > << " [ XYZ " << widget->getPosition() * > parent->getMatrix() > << " ] < size " << widget->getSize() << " >" > << " EventMask: " << std::hex << > widget->getEventMask() > << std::endl > ; > } > > label->setLabel(ss.str()); > > XYCoord size = label->getTextSize(); > > _pickWindow->resize(size.x() + 10.0f, size.y() + 10.0f); > _pickWindow->setOrigin(5.0f, _height - _pickWindow->getHeight() - > 5.0f); > _pickWindow->update(); > } > > void WindowManager::childInserted(unsigned int i) { > Window* window = dynamic_cast<Window*>(getChild(i)); > > if(!window) return; > > _objects.push_back(window); > > window->_index = i; > > setFocused(window); > > window->setNodeMask(_nodeMask); > window->managed(this); > > for(Window::Iterator w = window->begin(); w != window->end(); w++) > if(w->valid()) { > _styleManager->applyStyles(w->get()); > } > > _styleManager->applyStyles(window); > } > > void WindowManager::childRemoved(unsigned int start, unsigned int end) { > while(start < end) { > Window* window = getByIndex(start); > > if(!window) continue; > > if(_remove(window)) { > window->_index = -1; > > window->unmanaged(this); > } > > start++; > } > } > > // This method performs intersection testing at the given XY coords, and > returns true if > // any intersections were found. It will break after processing the first > pickable Window > // it finds. > bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) { > Intersections intr; > > if(_view->computeIntersections(x, y, intr, _nodeMask)) { > // Get the first Window at the XY coordinates; if you want a > Window to be > // non-pickable, set the NodeMask to something else. > Window* activeWin = 0; > > // Iterate over every picked result and create a list of > Widgets that belong > // to that Window. > for(Intersections::iterator i = intr.begin(); i != > intr.end(); i++) { > Window* win = > dynamic_cast<Window*>(i->nodePath.back()->getParent(0)); > > // Make sure that our window is valid, and that our > pick is within the > // "visible area" of the Window. > if( > (!win || win->getVisibilityMode() == > Window::VM_PARTIAL) && > !win->isPointerXYWithinVisible(x, y) > ) continue; > > // Set our activeWin, so that we know when we've got > all the Widgets > // that belong to it. > if(!activeWin) activeWin = win; > > // If we've found a new Widnow, break out! > else if(activeWin != win) break; > > Widget* widget = > dynamic_cast<Widget*>(i->drawable.get()); > > if(!widget) continue; > > // We need to return a list of every Widget that was > picked, so > // that the handler can operate on it accordingly. > else wl.push_back(widget); > } > > if(wl.size()) { > // Potentially VERY expensive; only to be used for > debugging. :) > if(_flags & WM_PICK_DEBUG) _updatePickWindow(&wl, x, > y); > > return true; > } > } > > if(_flags & WM_PICK_DEBUG) _updatePickWindow(0, x, y); > > return false; > } > > bool WindowManager::setFocused(Window* window) { > Event ev(this); > > ev._window = window; > > // Inform the previously focused Window that it is going to be > unfocused. > if(_focused.valid()) > _focused->callMethodAndCallbacks(ev.makeType(EVENT_UNFOCUS)); > > _focused = window; > > if(!window || !window->canFocus()) return false; > > // Build a vector of every Window that is focusable, in the > foreground, and in the > // background. All these Windows are handled differently. > Vector focusable; > Vector bg; > Vector fg; > > for(ConstIterator it = begin(); it != end(); it++) if(it->valid()) { > Window* w = it->get(); > > if(w->getStrata() == Window::STRATA_FOREGROUND) > fg.push_back(w); > > else if(w->getStrata() == Window::STRATA_BACKGROUND) > bg.push_back(w); > > else focusable.push_back(w); > } > > // After this call to sort, the internal objects will be arranged > such that the > // previously focused window is the first, followed by all other > Windows in > // descending order. > std::sort(focusable.begin(), focusable.end(), WindowZCompare()); > > // This is the depth range for each Window. Each Window object must > be informed of > // the Z space allocated to it so that it can properly arrange it's > children. We > // add 2 additional Windows here for anything that should appear in > the background > // and foreground areas. > matrix_type zRange = (_zNear - _zFar) / (focusable.size() + 2.0f); > > // Our offset for the following for() loop. > unsigned int i = 3; > > // Handle all of our focusable Windows. > for(Iterator w = focusable.begin(); w != focusable.end(); w++) { > Window* win = w->get(); > > // Set our newly focused Window as the topmost element. > if(*w == window) win->_z = -zRange * 2.0f; > > // Set the current Z of the remaining Windows and set their > zRange so that > // they can update their own children. > else { > win->_z = -zRange * i; > > i++; > } > } > > // Handled our special BACKGROUND Windows. > for(Iterator w = bg.begin(); w != bg.end(); w++) w->get()->_z = > -zRange * i; > > // Handle our special FOREGOUND Windows. > for(Iterator w = fg.begin(); w != fg.end(); w++) w->get()->_z = > -zRange; > > // Update every window, regardless. > for(Iterator w = begin(); w != end(); w++) { > Window* win = w->get(); > > win->_zRange = zRange; > > win->update(); > } > > _focused->callMethodAndCallbacks(ev.makeType(EVENT_FOCUS)); > > return true; > } > > void WindowManager::setPointerXY(float x, float y) { > float xdiff = x; > float ydiff = y; > > _getPointerXYDiff(xdiff, ydiff); > > // If ydiff isn't NEAR 0 (floating point booleans aren't 100% > reliable, but that > // doesn't matter in our case), assume we have either up or down > movement. > if(ydiff != 0.0f) _lastVertical = ydiff > 0.0f ? PD_UP : PD_DOWN; > > else _lastVertical = PD_NONE; > > // If xdiff isn't 0, assume we have either left or right movement. > if(xdiff != 0.0f) _lastHorizontal = xdiff > 0.0f ? PD_RIGHT : > PD_LEFT; > > else _lastHorizontal = PD_NONE; > > _lastX = x; > _lastY = y; > } > > void WindowManager::setStyleManager(StyleManager* sm) { > _styleManager = sm; > > for(Iterator i = begin(); i != end(); i++) if(i->valid()) { > Window* window = i->get(); > > for(Window::Iterator w = window->begin(); w != window->end(); > w++) { > if(!w->valid()) continue; > > _styleManager->applyStyles(w->get()); > } > > _styleManager->applyStyles(window); > } > } > > void WindowManager::resizeAllWindows(bool visible) { > for(Iterator i = begin(); i != end(); i++) if(i->valid()) { > if(visible && !getValue(i->get()->_index)) continue; > > i->get()->resize(); > } > } > > // This is called by a ViewerEventHandler/MouseHandler (or whatever) as the > pointer moves > // around and intersects with objects. It also resets our state data > (_widget, _leftDown, > // etc.) The return value of this method is mostly useless. > bool WindowManager::pointerMove(float x, float y) { > WidgetList wl; > Event ev(this); > > if(!pickAtXY(x, y, wl)) { > if(_lastEvent) { > setEventFromInterface(ev.makeMouse(x, y, > EVENT_MOUSE_LEAVE), _lastEvent); > > _lastEvent->callMethodAndCallbacks(ev); > } > > if(_focusMode == PFM_SLOPPY) setFocused(0); > > _lastEvent = 0; > _leftDown = 0; > _middleDown = 0; > _rightDown = 0; > > return false; > } > > EventInterface* ei = getFirstEventInterface(wl, ev.makeMouse(x, y, > EVENT_MOUSE_OVER)); > > if(!ei) return false; > > if(_lastEvent != ei) { > if(_lastEvent) { > Event evLeave(this); > > evLeave.makeMouse(x, y, EVENT_MOUSE_LEAVE); > > setEventFromInterface(evLeave, _lastEvent); > > _lastEvent->callMethodAndCallbacks(evLeave); > } > > _lastEvent = ei; > > if(_focusMode == PFM_SLOPPY && ev._window) > setFocused(ev._window); > > _lastEvent->callMethodAndCallbacks(ev.makeMouse(x, y, > EVENT_MOUSE_ENTER)); > } > > ei->callMethodAndCallbacks(ev.makeMouse(x, y, EVENT_MOUSE_OVER)); > > return true; > } > > bool WindowManager::pointerDrag(float x, float y) { > WidgetList widgetList; > Event ev(this); > > float xdiff = x; > float ydiff = y; > > _getPointerXYDiff(xdiff, ydiff); > > ev.makeMouse(xdiff, ydiff, EVENT_MOUSE_DRAG); > > // If we're still in the drag state... > if(_lastPush) { > setEventFromInterface(ev, _lastPush); > > return _lastPush->callMethodAndCallbacks(ev); > } > > return false; > } > > bool WindowManager::mouseScroll(float x, float y) { > WidgetList wl; > > if(!pickAtXY(x, y, wl)) return false; > > Event ev(this, EVENT_MOUSE_SCROLL); > > EventInterface* ei = getFirstEventInterface(wl, ev); > > if(!ei) return false; > > return ei->callMethodAndCallbacks(ev); > } > > // Keypresses only go the focused Window. > bool WindowManager::keyDown(int key, int mask) { > if(_focused.valid()) { > Event ev(this, EVENT_KEY_DOWN); > > ev.makeKey(key, mask); > > Widget* focusedWidget = _focused->getFocused(); > > ev._window = _focused.get(); > ev._widget = focusedWidget; > > bool handled = false; > > if(focusedWidget) handled = > focusedWidget->callMethodAndCallbacks(ev); > > if(!handled) return _focused->callMethodAndCallbacks(ev); > > else return true; > } > > return false; > } > > bool WindowManager::keyUp(int key, int mask) { > return true; > } > > // A convenience wrapper for creating a proper orthographic camera using the > current > // width and height. > osg::Camera* WindowManager::createParentOrthoCamera() { > osg::Camera* camera = 0; > > if(isInvertedY()) camera = createInvertedYOrthoCamera(_width, > _height); > > else camera = createOrthoCamera(_width, _height); > > camera->addChild(this); > > return camera; > } > > } > > _______________________________________________ > osg-submissions mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org > > _______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
