Added DragCallback class to help dialog dragging support.
Introduced a new Widget::computeExtentsPositionInLocalCoordinates() method that intersects with a ray through mouse pointer and the extents of the widget. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14429 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
@@ -17,6 +17,7 @@ SET(TARGET_H
|
||||
${HEADER_PATH}/Popup
|
||||
${HEADER_PATH}/PushButton
|
||||
${HEADER_PATH}/ComboBox
|
||||
${HEADER_PATH}/Callbacks
|
||||
${HEADER_PATH}/Style
|
||||
${HEADER_PATH}/AlignmentSettings
|
||||
${HEADER_PATH}/FrameSettings
|
||||
@@ -33,6 +34,7 @@ SET(TARGET_SRC
|
||||
Popup.cpp
|
||||
PushButton.cpp
|
||||
ComboBox.cpp
|
||||
Callbacks.cpp
|
||||
Style.cpp
|
||||
AlignmentSettings.cpp
|
||||
FrameSettings.cpp
|
||||
@@ -46,6 +48,7 @@ SET(TARGET_LIBRARIES
|
||||
osgGA
|
||||
osgUtil
|
||||
osgText
|
||||
osgViewer
|
||||
osg
|
||||
OpenThreads
|
||||
)
|
||||
|
||||
132
src/osgUI/Callbacks.cpp
Normal file
132
src/osgUI/Callbacks.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 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.
|
||||
*/
|
||||
|
||||
#include <osgUI/Callbacks>
|
||||
#include <osgUI/Widget>
|
||||
#include <osg/ValueObject>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
using namespace osgUI;
|
||||
|
||||
HandleCallback::HandleCallback()
|
||||
{
|
||||
setName("handle");
|
||||
}
|
||||
|
||||
HandleCallback::HandleCallback(const HandleCallback& hc, const osg::CopyOp& copyop):
|
||||
osg::CallbackObject(hc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
bool HandleCallback::run(osg::Object* object, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const
|
||||
{
|
||||
if (inputParameters.size()>=2)
|
||||
{
|
||||
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(inputParameters[0].get());
|
||||
osgGA::Event* event = dynamic_cast<osgGA::Event*>(inputParameters[1].get());
|
||||
if (ev && event)
|
||||
{
|
||||
outputParameters.push_back(new osg::BoolValueObject("return",handle(ev,event)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleCallback::handle(osgGA::EventVisitor* ev, osgGA::Event* event) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DragCallback::DragCallback():
|
||||
_dragging(false)
|
||||
{
|
||||
}
|
||||
|
||||
DragCallback::DragCallback(const DragCallback& hc, const osg::CopyOp& copyop):
|
||||
HandleCallback(hc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
bool DragCallback::handle(osgGA::EventVisitor* ev, osgGA::Event* event) const
|
||||
{
|
||||
osgGA::GUIEventAdapter* ea = event ? event->asGUIEventAdapter() : 0;
|
||||
if (!ev || !ea) return false;
|
||||
|
||||
osgUI::Widget* widget = dynamic_cast<osgUI::Widget*>(ev->getNodePath().empty() ? 0 : ev->getNodePath().back());
|
||||
if (widget && widget->getHasEventFocus())
|
||||
{
|
||||
DragCallback* dc = const_cast<DragCallback*>(this);
|
||||
switch(ea->getEventType())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::PUSH):
|
||||
{
|
||||
dc->_dragging = (ea->getButtonMask()==osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON);
|
||||
if (dc->_dragging)
|
||||
{
|
||||
osg::Vec3d localPosition;
|
||||
#if 0
|
||||
if (widget->computePositionInLocalCoordinates(ev, ea, localPosition))
|
||||
#else
|
||||
if (widget->computeExtentsPositionInLocalCoordinates(ev, ea, localPosition))
|
||||
#endif
|
||||
{
|
||||
dc->_previousPosition = localPosition;
|
||||
OSG_NOTICE<<"* Move to local"<<_previousPosition<<std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(osgGA::GUIEventAdapter::DRAG):
|
||||
{
|
||||
if (dc->_dragging)
|
||||
{
|
||||
osg::Transform* transform = 0;
|
||||
for(osg::NodePath::reverse_iterator itr = ev->getNodePath().rbegin();
|
||||
itr != ev->getNodePath().rend();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->asTransform())
|
||||
{
|
||||
transform = (*itr)->asTransform();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (transform)
|
||||
{
|
||||
osg::Vec3d position;
|
||||
if (widget->computeExtentsPositionInLocalCoordinates(ev, ea, position, false))
|
||||
{
|
||||
osg::Vec3d delta = position-_previousPosition;
|
||||
osg::MatrixTransform* mt = transform->asMatrixTransform();
|
||||
mt->setMatrix(osg::Matrixd::translate(delta)*mt->getMatrix());
|
||||
// OSG_NOTICE<<"Move to local "<<position<<", "<<position-_previousPosition<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_NOTICE<<"Failed to drag, No Transform to move"<<std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(osgGA::GUIEventAdapter::RELEASE):
|
||||
dc->_dragging = false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -13,6 +13,10 @@
|
||||
|
||||
|
||||
#include <osgUI/Dialog>
|
||||
#include <osgUI/PushButton>
|
||||
#include <osgUI/Label>
|
||||
#include <osgUI/Callbacks>
|
||||
|
||||
#include <osgText/String>
|
||||
#include <osgText/Font>
|
||||
#include <osgText/Text>
|
||||
@@ -62,29 +66,41 @@ void Dialog::createGraphicsImplementation()
|
||||
osg::Vec4 dialogTitleBackgroundColor(0.5,0.5,1.0,1.0);
|
||||
|
||||
_group->addChild( style->createPanel(_extents, dialogBackgroundColor) );
|
||||
|
||||
_group->addChild( style->createPanel(titleBarExents, dialogTitleBackgroundColor) );
|
||||
|
||||
osg::BoundingBox dialogWithTileExtents(_extents);
|
||||
dialogWithTileExtents.expandBy(titleBarExents);
|
||||
osg::BoundingBox dialogWithTitleExtents(_extents);
|
||||
dialogWithTitleExtents.expandBy(titleBarExents);
|
||||
|
||||
bool requiresFrame = (getFrameSettings() && getFrameSettings()->getShape()!=osgUI::FrameSettings::NO_FRAME);
|
||||
if (requiresFrame) { _group->addChild(style->createFrame(dialogWithTileExtents, getFrameSettings(), dialogBackgroundColor)); }
|
||||
if (requiresFrame) { _group->addChild(style->createFrame(dialogWithTitleExtents, getFrameSettings(), dialogBackgroundColor)); }
|
||||
|
||||
OSG_NOTICE<<"Dialog::_extents ("<<_extents.xMin()<<", "<<_extents.yMin()<<", "<<_extents.zMin()<<"), ("<<_extents.xMax()<<", "<<_extents.yMax()<<", "<<_extents.zMax()<<")"<<std::endl;
|
||||
OSG_NOTICE<<"Dialog::titleBarExents ("<<titleBarExents.xMin()<<", "<<titleBarExents.yMin()<<", "<<titleBarExents.zMin()<<"), ("<<titleBarExents.xMax()<<", "<<titleBarExents.yMax()<<", "<<titleBarExents.zMax()<<")"<<std::endl;
|
||||
OSG_NOTICE<<"Dialog::dialogWithTileExtents ("<<dialogWithTileExtents.xMin()<<", "<<dialogWithTileExtents.yMin()<<", "<<dialogWithTileExtents.zMin()<<"), ("<<dialogWithTileExtents.xMax()<<", "<<dialogWithTileExtents.yMax()<<", "<<dialogWithTileExtents.zMax()<<")"<<std::endl;
|
||||
OSG_NOTICE<<"Dialog::dialogWithTitleExtents ("<<dialogWithTitleExtents.xMin()<<", "<<dialogWithTitleExtents.yMin()<<", "<<dialogWithTitleExtents.zMin()<<"), ("<<dialogWithTitleExtents.xMax()<<", "<<dialogWithTitleExtents.yMax()<<", "<<dialogWithTitleExtents.zMax()<<")"<<std::endl;
|
||||
|
||||
#if 0
|
||||
osg::ref_ptr<Node> node = style->createText(titleBarExents, getAlignmentSettings(), getTextSettings(), _title);
|
||||
_titleDrawable = dynamic_cast<osgText::Text*>(node.get());
|
||||
_titleDrawable->setDataVariance(osg::Object::DYNAMIC);
|
||||
_group->addChild(_titleDrawable.get());
|
||||
#endif
|
||||
|
||||
osg::ref_ptr<Label> titleLabel = new osgUI::Label;
|
||||
titleLabel->setExtents(titleBarExents);
|
||||
titleLabel->setText(_title);
|
||||
titleLabel->setAlignmentSettings(getAlignmentSettings());
|
||||
titleLabel->setTextSettings(getTextSettings());
|
||||
titleLabel->setFrameSettings(getFrameSettings());
|
||||
titleLabel->getOrCreateUserDataContainer()->addUserObject(new osgUI::DragCallback);
|
||||
addChild(titleLabel.get());
|
||||
|
||||
style->setupDialogStateSet(getOrCreateStateSet(), 5);
|
||||
style->setupClipStateSet(dialogWithTileExtents, getOrCreateStateSet());
|
||||
style->setupClipStateSet(dialogWithTitleExtents, getOrCreateStateSet());
|
||||
|
||||
// render before the subgraph
|
||||
setGraphicsSubgraph(-1, _group.get());
|
||||
|
||||
// render after the subgraph
|
||||
setGraphicsSubgraph(1, style->createDepthSetPanel(dialogWithTileExtents));
|
||||
setGraphicsSubgraph(1, style->createDepthSetPanel(dialogWithTitleExtents));
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ void LineEdit::createGraphicsImplementation()
|
||||
// clear background of edit region
|
||||
_backgroundSwitch = new osg::Switch;
|
||||
_backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(unFocused, unFocused,unFocused, 1.0)));
|
||||
_backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(withFocus,withFocus,withFocus,1.0)));
|
||||
_backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(withFocus, withFocus, withFocus,1.0)));
|
||||
_backgroundSwitch->setSingleChildOn(0);
|
||||
group->addChild(_backgroundSwitch.get());
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <osgUI/Widget>
|
||||
#include <osgGA/EventVisitor>
|
||||
#include <osgGA/GUIActionAdapter>
|
||||
#include <osgViewer/View>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -31,6 +32,7 @@ Widget::Widget():
|
||||
_focusBehaviour(FOCUS_FOLLOWS_POINTER),
|
||||
_hasEventFocus(false),
|
||||
_graphicsInitialized(false),
|
||||
_autoFillBackground(false),
|
||||
_visible(true),
|
||||
_enabled(true)
|
||||
{
|
||||
@@ -45,6 +47,7 @@ Widget::Widget(const Widget& widget, const osg::CopyOp& copyop):
|
||||
_alignmentSettings(osg::clone(widget._alignmentSettings.get(), copyop)),
|
||||
_frameSettings(osg::clone(widget._frameSettings.get(), copyop)),
|
||||
_textSettings(osg::clone(widget._textSettings.get(), copyop)),
|
||||
_autoFillBackground(widget._autoFillBackground),
|
||||
_visible(widget._visible),
|
||||
_enabled(widget._enabled)
|
||||
{
|
||||
@@ -72,20 +75,24 @@ void Widget::updateFocus(osg::NodeVisitor& nv)
|
||||
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
|
||||
if (ea)
|
||||
{
|
||||
int numButtonsPressed = 0;
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::PUSH)
|
||||
{
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
}
|
||||
|
||||
bool previousFocus = _hasEventFocus;
|
||||
if (_focusBehaviour==CLICK_TO_FOCUS)
|
||||
{
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::PUSH)
|
||||
{
|
||||
int numButtonsPressed = 0;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
|
||||
if (numButtonsPressed==1)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
osg::Vec3d intersection;
|
||||
bool withinWidget = computeExtentsPositionInLocalCoordinates(ev, ea, intersection);
|
||||
|
||||
if (withinWidget) _hasEventFocus = true;
|
||||
else _hasEventFocus = false;
|
||||
}
|
||||
@@ -114,30 +121,30 @@ void Widget::updateFocus(osg::NodeVisitor& nv)
|
||||
|
||||
if (checkWithinWidget)
|
||||
{
|
||||
#if 0
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
#else
|
||||
Intersections intersections;
|
||||
bool withinWidget = computeIntersections( ev, ea, intersections);
|
||||
#endif
|
||||
osg::Vec3d intersection;
|
||||
bool withinWidget = computeExtentsPositionInLocalCoordinates(ev, ea, intersection);
|
||||
|
||||
_hasEventFocus = withinWidget;
|
||||
}
|
||||
}
|
||||
|
||||
if (numButtonsPressed!=0)
|
||||
{
|
||||
osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa);
|
||||
if (view && view->getCameraManipulator())
|
||||
{
|
||||
view->getCameraManipulator()->finishAnimation();
|
||||
view->requestContinuousUpdate( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (previousFocus != _hasEventFocus)
|
||||
{
|
||||
if (_hasEventFocus)
|
||||
{
|
||||
enter();
|
||||
#if 0
|
||||
if (view->getCameraManipulator())
|
||||
{
|
||||
view->getCameraManipulator()->finishAnimation();
|
||||
view->requestContinuousUpdate( false );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -328,7 +335,7 @@ void Widget::releaseGLObjects(osg::State* state) const
|
||||
|
||||
}
|
||||
|
||||
bool Widget::computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3& localPosition) const
|
||||
bool Widget::computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3d& localPosition) const
|
||||
{
|
||||
osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0;
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
@@ -440,3 +447,63 @@ bool Widget::computeIntersections(osgGA::EventVisitor* ev, osgGA::GUIEventAdapte
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Widget::computeExtentsPositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3d& localPosition, bool withinExtents) const
|
||||
{
|
||||
//OSG_NOTICE<<"Widget::computeExtentsPositionInLocalCoordinates(()"<<std::endl;
|
||||
const osg::Camera* camera = 0;
|
||||
double x=0.0, y=0.0;
|
||||
if (event->getNumPointerData()>=1)
|
||||
{
|
||||
const osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
|
||||
camera = dynamic_cast<const osg::Camera*>(pd->object.get());
|
||||
if (camera)
|
||||
{
|
||||
x = pd->getXnormalized();
|
||||
y = pd->getYnormalized();
|
||||
}
|
||||
}
|
||||
//OSG_NOTICE<<" camera = "<<camera<<", x = "<<x<<", y="<<y<<std::endl;
|
||||
if (!camera) return false;
|
||||
|
||||
const osg::NodePath& nodePath = ev->getNodePath();
|
||||
|
||||
osg::Matrixd matrix;
|
||||
if (nodePath.size()>1)
|
||||
{
|
||||
osg::NodePath prunedNodePath(nodePath.begin(),nodePath.end()-1);
|
||||
matrix = osg::computeLocalToWorld(prunedNodePath);
|
||||
}
|
||||
|
||||
matrix.postMult(camera->getViewMatrix());
|
||||
matrix.postMult(camera->getProjectionMatrix());
|
||||
|
||||
double zNear = -1.0;
|
||||
double zFar = 1.0;
|
||||
|
||||
osg::Matrixd inverse;
|
||||
inverse.invert(matrix);
|
||||
|
||||
osg::Vec3d startVertex = osg::Vec3d(x,y,zNear) * inverse;
|
||||
osg::Vec3d endVertex = osg::Vec3d(x,y,zFar) * inverse;
|
||||
|
||||
//OSG_NOTICE<<" startVertex("<<startVertex<<"(, endVertex("<<endVertex<<")"<<std::endl;
|
||||
|
||||
|
||||
osg::Plane plane(0.0, 0.0, 1.0, _extents.zMax());
|
||||
|
||||
//OSG_NOTICE<<" plane("<<plane<<")"<<std::endl;
|
||||
double ds = plane.distance(startVertex);
|
||||
double de = plane.distance(endVertex);
|
||||
if (ds*de>0.0) return false;
|
||||
|
||||
double r = ds/(ds-de);
|
||||
//OSG_NOTICE<<" r = "<<r<<std::endl;
|
||||
|
||||
osg::Vec3d intersection = startVertex + (endVertex-startVertex)*r;
|
||||
//OSG_NOTICE<<" intersection = "<<intersection<<std::endl;
|
||||
localPosition = intersection;
|
||||
|
||||
return withinExtents ? _extents.contains(localPosition, 1e-6) : true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user