From a96ad565c766dd248faf035116725c38135f4074 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 23 Jan 2014 15:37:48 +0000 Subject: [PATCH] From Stephan Huber, "attached are some fixes to the osc-plugin and the touch-implementations for iOS and os x and other small bugfixes. These fixes will normalize the orientation of the touch points, and transmitting the touch points over osc via the TUIO-protocol works now more robustly between two osg-applications. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I added a new tag to p3d called forward_touch_event_to_device and renamed the existing forward_event_to_device to forward_mouse_event_to_device. This new tag will transmit touches to the virtual trackpad as touch events. I added the MultitouchTrackball to the p3d-app so zooming and moving a model remotely should now work, if you use forward_touch_event_to_device. I kept (and fixed) forward_mouse_event_to_device for background compatibility, so old presentations works as in previous versions, without the ability to zoom + scale. of course. forward_touch_event_to_device needs some more testing, (e.g. with image-streams and keystone, afaik there’s no support for touch-events...) but for a first version it works nice. " --- .../present3D/deprecated/present3D.cpp | 58 ++++++++- .../iphoneViewerAppDelegate.mm | 111 +++++++++++------- include/osgGA/GUIEventAdapter | 5 +- .../deprecated/SlideEventHandler | 3 +- src/osgGA/GUIEventAdapter.cpp | 7 +- src/osgGA/MultiTouchTrackballManipulator.cpp | 2 +- src/osgPlugins/osc/OscReceivingDevice.cpp | 95 ++++++++------- src/osgPlugins/osc/OscSendingDevice.cpp | 71 +++++++---- src/osgPlugins/osc/OscSendingDevice.hpp | 4 +- src/osgPlugins/p3d/ReaderWriterP3D.cpp | 13 +- .../deprecated/KeyEventHandler.cpp | 3 +- .../deprecated/PickEventHandler.cpp | 55 ++++++++- src/osgViewer/GraphicsWindowCocoa.mm | 51 +++++--- src/osgViewer/GraphicsWindowIOS.mm | 30 ++++- src/osgViewer/Viewer.cpp | 5 + 15 files changed, 368 insertions(+), 145 deletions(-) diff --git a/applications/present3D/deprecated/present3D.cpp b/applications/present3D/deprecated/present3D.cpp index 12fb2c3f1..7e730d739 100644 --- a/applications/present3D/deprecated/present3D.cpp +++ b/applications/present3D/deprecated/present3D.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ #include #include + #include #ifdef USE_SDL @@ -174,6 +176,58 @@ private: }; +class DumpEventHandler : public osgGA::GUIEventHandler { +public: + DumpEventHandler() : osgGA::GUIEventHandler() {} + + virtual bool handle (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa, osg::Object *, osg::NodeVisitor *) + { + switch (ea.getEventType()) + { + case osgGA::GUIEventAdapter::FRAME: + return false; + break; + case osgGA::GUIEventAdapter::PUSH: + std::cout << "PUSH: "; + break; + case osgGA::GUIEventAdapter::RELEASE: + std::cout << "RELEASE: "; + break; + case osgGA::GUIEventAdapter::MOVE: + std::cout << "MOVE: "; + break; + case osgGA::GUIEventAdapter::DRAG: + std::cout << "DRAG: "; + break; + case osgGA::GUIEventAdapter::SCROLL: + std::cout << "SCROLL: "; + break; + break; + + default: + std::cout << ea.getEventType() << " "; + break; + } + std::cout << ea.getX() << "/" << ea.getY() << " " << ea.isMultiTouchEvent() << std::endl; + return false; + } + + + bool handle(osgGA::Event* event, osg::Object* object, osg::NodeVisitor* nv) + { + if (event->asGUIEventAdapter()) + return osgGA::GUIEventHandler::handle(event, object, nv); + else + { + return false; + } + } + + +private: +}; + + enum P3DApplicationType { @@ -423,7 +477,7 @@ int main( int argc, char **argv ) { osg::ref_ptr keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator; - keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() ); + keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::MultiTouchTrackballManipulator() ); keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() ); keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() ); keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() ); @@ -444,6 +498,8 @@ int main( int argc, char **argv ) viewer.setCameraManipulator( keyswitchManipulator.get() ); } + + //viewer.getEventHandlers().push_front(new DumpEventHandler()); // add the state manipulator osg::ref_ptr ssManipulator = new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()); diff --git a/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm index 7b24eff0c..439fe60ee 100644 --- a/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm +++ b/examples/osgviewerIPhone/iphoneViewerAppDelegate.mm @@ -13,6 +13,22 @@ #include +@interface MyViewController : UIViewController + +- (BOOL)shouldAutorotate; + + +@end + +@implementation MyViewController + +- (BOOL)shouldAutorotate +{ + return YES; +} +@end + + @implementation iphoneViewerAppDelegate @synthesize _window; @@ -148,7 +164,11 @@ private: for(osgGA::GUIEventAdapter::TouchData::iterator i = ea.getTouchData()->begin(); i != ea.getTouchData()->end(); ++i, ++j) { const osgGA::GUIEventAdapter::TouchData::TouchPoint& tp = (*i); - _mats[j]->setMatrix(osg::Matrix::translate(tp.x, ea.getWindowHeight() - tp.y, 0)); + if (ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) + _mats[j]->setMatrix(osg::Matrix::translate(tp.x, ea.getWindowHeight() - tp.y, 0)); + else + _mats[j]->setMatrix(osg::Matrix::translate(tp.x, tp.y, 0)); + _mats[j]->setNodeMask(0xffff); std::ostringstream ss; @@ -227,55 +247,62 @@ private: //get the screen size CGRect lFrame = [[UIScreen mainScreen] bounds]; - unsigned int w = lFrame.size.width; - unsigned int h = lFrame.size.height; + unsigned int w = lFrame.size.width * [[UIScreen mainScreen] scale]; + unsigned int h = lFrame.size.height * [[UIScreen mainScreen] scale]; //create the viewer _viewer = new osgViewer::Viewer(); - /* + if(1) { - // If you want full control over the graphics context / window creation, please uncomment this section - - // create the main window at screen size - self._window = [[UIWindow alloc] initWithFrame: lFrame]; - - //show window - [_window makeKeyAndVisible]; + // If you want full control over the graphics context / window creation, please uncomment this section + + // create the main window at screen size + self._window = [[UIWindow alloc] initWithFrame: lFrame]; + + //show window + [_window makeKeyAndVisible]; + + UIView* parent_view = [[UIView alloc] initWithFrame: CGRectMake(0,0, w, h)]; + parent_view.backgroundColor = [UIColor redColor]; + [self._window addSubview: parent_view]; + MyViewController* view_controller = [[MyViewController alloc] init]; + view_controller.view = parent_view; + self._window.rootViewController = view_controller; + + + //create our graphics context directly so we can pass our own window + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + + // Init the Windata Variable that holds the handle for the Window to display OSG in. + osg::ref_ptr windata = new osgViewer::GraphicsWindowIOS::WindowData(parent_view); + + // Setup the traits parameters + traits->x = 50; + traits->y = 50; + traits->width = w-100; + traits->height = h-100; + traits->depth = 16; //keep memory down, default is currently 24 + traits->windowDecoration = false; + traits->doubleBuffer = true; + traits->sharedContext = 0; + traits->setInheritedWindowPixelFormat = true; + traits->samples = 4; + traits->sampleBuffers = 1; + + traits->inheritedWindowData = windata; - - //create our graphics context directly so we can pass our own window - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - - // Init the Windata Variable that holds the handle for the Window to display OSG in. - osg::ref_ptr windata = new osgViewer::GraphicsWindowIOS::WindowData(_window); - - // Setup the traits parameters - traits->x = 0; - traits->y = 0; - traits->width = w; - traits->height = h; - traits->depth = 16; //keep memory down, default is currently 24 - traits->windowDecoration = false; - traits->doubleBuffer = true; - traits->sharedContext = 0; - traits->setInheritedWindowPixelFormat = true; - traits->samples = 4; - traits->sampleBuffers = 1; - - traits->inheritedWindowData = windata; - - // Create the Graphics Context - osg::ref_ptr graphicsContext = osg::GraphicsContext::createGraphicsContext(traits.get()); - - // if the context was created then attach to our viewer - if(graphicsContext) - { - _viewer->getCamera()->setGraphicsContext(graphicsContext); - _viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); + // Create the Graphics Context + osg::ref_ptr graphicsContext = osg::GraphicsContext::createGraphicsContext(traits.get()); + + // if the context was created then attach to our viewer + if(graphicsContext) + { + _viewer->getCamera()->setGraphicsContext(graphicsContext); + _viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); + } } - */ //create root diff --git a/include/osgGA/GUIEventAdapter b/include/osgGA/GUIEventAdapter index def0d1684..af5c3f353 100644 --- a/include/osgGA/GUIEventAdapter +++ b/include/osgGA/GUIEventAdapter @@ -675,13 +675,14 @@ public: void addTouchPoint(unsigned int id, TouchPhase phase, float x, float y, unsigned int tapCount = 0); + void setTouchData(TouchData* td) { _touchData = td; } TouchData* getTouchData() const { return _touchData.get(); } bool isMultiTouchEvent() const { return (_touchData.valid()); } - + inline float getTouchPointNormalizedX(unsigned int ndx) const { return (getTouchData()->get(ndx).x-_Xmin)/(_Xmax-_Xmin)*2.0f-1.0f; } - + inline float getTouchPointNormalizedY(unsigned int ndx) const { if (_mouseYOrientation==Y_INCREASING_UPWARDS) return (getTouchData()->get(ndx).y-_Ymin)/(_Ymax-_Ymin)*2.0f-1.0f; diff --git a/include/osgPresentation/deprecated/SlideEventHandler b/include/osgPresentation/deprecated/SlideEventHandler index 5b6e3afb7..2cf96e414 100644 --- a/include/osgPresentation/deprecated/SlideEventHandler +++ b/include/osgPresentation/deprecated/SlideEventHandler @@ -37,7 +37,8 @@ enum Operation LOAD, EVENT, JUMP, - FORWARD_EVENT + FORWARD_MOUSE_EVENT, + FORWARD_TOUCH_EVENT }; struct JumpData diff --git a/src/osgGA/GUIEventAdapter.cpp b/src/osgGA/GUIEventAdapter.cpp index eff04cbc3..80c50d7fa 100644 --- a/src/osgGA/GUIEventAdapter.cpp +++ b/src/osgGA/GUIEventAdapter.cpp @@ -67,8 +67,11 @@ GUIEventAdapter::GUIEventAdapter(const GUIEventAdapter& rhs,const osg::CopyOp& c _mouseYOrientation(rhs._mouseYOrientation), _scrolling(rhs._scrolling), _tabletPen(rhs._tabletPen), - _touchData(rhs._touchData) -{} + _touchData(NULL) +{ + if(TouchData* td = rhs.getTouchData()) + setTouchData(osg::clone(td, copyop)); +} GUIEventAdapter::~GUIEventAdapter() { diff --git a/src/osgGA/MultiTouchTrackballManipulator.cpp b/src/osgGA/MultiTouchTrackballManipulator.cpp index ad5510eaa..5d224008d 100644 --- a/src/osgGA/MultiTouchTrackballManipulator.cpp +++ b/src/osgGA/MultiTouchTrackballManipulator.cpp @@ -58,7 +58,7 @@ void MultiTouchTrackballManipulator::handleMultiTouchDrag(const GUIEventAdapter* osg::Vec2 delta = ((pt_1_last - pt_1_now) + (pt_2_last - pt_2_now)) / 2.0f; float scale = _distance / 3.0f; - + // osg::notify(osg::ALWAYS) << "drag: " << delta << " scale: " << scale << std::endl; panModel( delta.x() * scale, delta.y() * scale); diff --git a/src/osgPlugins/osc/OscReceivingDevice.cpp b/src/osgPlugins/osc/OscReceivingDevice.cpp index 92a8a57cf..dea76c741 100644 --- a/src/osgPlugins/osc/OscReceivingDevice.cpp +++ b/src/osgPlugins/osc/OscReceivingDevice.cpp @@ -715,13 +715,13 @@ class TUIO2DCursorRequestHandler : public OscReceivingDevice::RequestHandler { public: struct Cursor { - std::string source; + std::string end_point; unsigned int id, frameId; osg::Vec2f pos, vel; float accel; osgGA::GUIEventAdapter::TouchPhase phase; - Cursor() : source(), id(0), frameId(0), pos(), vel(), accel(), phase(osgGA::GUIEventAdapter::TOUCH_UNKNOWN) {} + Cursor() : end_point(), id(0), frameId(0), pos(), vel(), accel(), phase(osgGA::GUIEventAdapter::TOUCH_UNKNOWN) {} }; struct EndpointData { @@ -764,9 +764,12 @@ public: if (what == "source") { - args >> str; - _endpointData[end_point].source = std::string(str); - updateSourceIdMap(_endpointData[end_point].source); + args >> str; + _endpointData[end_point].source = std::string(str); + updateSourceIdMap(_endpointData[end_point].source); + + _endpointData[end_point].unhandled.clear(); + _endpointData[end_point].mayClearUnhandledPointer = true; return true; } @@ -786,10 +789,8 @@ public: { osc::int32 id; args >> id; - _endpointData[source].unhandled.insert(id); + _endpointData[end_point].unhandled.insert(id); } - _endpointData[source].mayClearUnhandledPointer = true; - return true; } else if (what == "set") @@ -803,9 +804,9 @@ public: Cursor& c(_alive[source][id]); args >> c.pos.x() >> c.pos.y() >> c.vel.x() >> c.vel.y() >> c.accel >> osc::EndMessage; - c.source = source; c.frameId = frame_id; - _endpointData[source].unhandled.insert(id); + c.end_point = end_point; + _endpointData[end_point].unhandled.insert(id); return true; } @@ -840,51 +841,50 @@ public: // remove all touchpoints which are not transmitted via alive-message, dispatching TOUCH_ENDED - EndpointData& endpoint_data(_endpointData[source]); - if (endpoint_data.mayClearUnhandledPointer) + unsigned int source_id = getSourceId(source); + + std::vector to_delete; + + for(CursorMap::iterator k = i->second.begin(); k != i->second.end(); ++k) { - unsigned int source_id = getSourceId(source); - - std::vector to_delete; - - for(CursorMap::iterator k = i->second.begin(); k != i->second.end(); ++k) + EndpointData& endpoint_data(_endpointData[k->second.end_point]); + /*if (!endpoint_data.mayClearUnhandledPointer) { - //create a unique touchpoint-id - unsigned int touch_id = (source_id << 16) + k->first; - - std::set& unhandled(endpoint_data.unhandled); - if ((unhandled.find(k->first) == unhandled.end())) - { - std::cout << "deleting: " << k->first << std::endl; - to_delete.push_back(k->first); - - float win_x = k->second.pos.x(); - float win_y = k->second.pos.y(); - - if (!event) - event = queue->touchEnded(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1); - else - event->addTouchPoint(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1); - } - } - // remove "dead" cursors - for(std::vector::iterator k = to_delete.begin(); k != to_delete.end(); ++k) - { - _alive[source].erase(i->second.find(*k)); - } + continue; + }*/ + + //create a unique touchpoint-id + unsigned int touch_id = (source_id << 16) + k->first; - endpoint_data.mayClearUnhandledPointer = false; - endpoint_data.unhandled.clear(); + std::set& unhandled(endpoint_data.unhandled); + if ((unhandled.find(k->first) == unhandled.end())) + { + // std::cout << "deleting: " << k->first << " from " << k->second.end_point << std::endl; + to_delete.push_back(k->first); + + float win_x = k->second.pos.x(); + float win_y = k->second.pos.y(); + + if (!event) + event = queue->touchEnded(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1); + else + event->addTouchPoint(touch_id, osgGA::GUIEventAdapter::TOUCH_ENDED, win_x, win_y, 1); + } } - + // remove "dead" cursors + for(std::vector::iterator k = to_delete.begin(); k != to_delete.end(); ++k) + { + _alive[source].erase(i->second.find(*k)); + } + if (i->second.size() == 0) { // std::cout << "removing endpoint" << source << std::endl; - _endpointData.erase(_endpointData.find(source)); - _alive.erase(_alive.find(source)); + // _alive.erase(_alive.find(source)); } } + // send all alive touchpoints for(ApplicationCursorMap::iterator i = _alive.begin(); i != _alive.end(); ++i) { @@ -912,6 +912,7 @@ public: { event->addTouchPoint(touch_id, down ? osgGA::GUIEventAdapter::TOUCH_BEGAN : osgGA::GUIEventAdapter::TOUCH_MOVED, win_x, win_y); } + c.phase = osgGA::GUIEventAdapter::TOUCH_MOVED; } } @@ -921,6 +922,7 @@ public: { event->setInputRange(0, 0, 1.0, 1.0); event->setTime(queue->getTime()); + event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); } } @@ -997,6 +999,9 @@ OscReceivingDevice::OscReceivingDevice(const std::string& server_address, int li addRequestHandler(new OscDevice::StandardRequestHandler("/osg/set_user_value", true)); addRequestHandler(new OscDevice::StandardRequestHandler("", false)); + + // getEventQueue()->setFirstTouchEmulatesMouse(false); + setSchedulePriority(OpenThreads::Thread::THREAD_PRIORITY_LOW); start(); } diff --git a/src/osgPlugins/osc/OscSendingDevice.cpp b/src/osgPlugins/osc/OscSendingDevice.cpp index 59896cb6c..dcdfbb234 100644 --- a/src/osgPlugins/osc/OscSendingDevice.cpp +++ b/src/osgPlugins/osc/OscSendingDevice.cpp @@ -31,12 +31,10 @@ OscSendingDevice::OscSendingDevice(const std::string& address, int port, unsigne , _delayBetweenSendsInMilliSecs( (_numMessagesPerEvent > 1) ? delay_between_sends_in_millisecs : 0) , _msgId(0) , _lastEvent(NULL) + , _finishMultiTouchSequence(false) { setCapabilities(SEND_EVENTS); - - - - + OSG_NOTICE << "OscDevice :: sending events to " << address << ":" << port << " "; #ifdef OSC_HOST_LITTLE_ENDIAN OSG_NOTICE << "(little endian)"; @@ -164,23 +162,24 @@ bool OscSendingDevice::sendUIEventImpl(const osgGA::GUIEventAdapter &ea, MsgIdTy case osgGA::GUIEventAdapter::PUSH: beginSendInputRange(ea, msg_id); - sendMultiTouchData(ea); - _oscStream << osc::BeginMessage("/osgga/mouse/press") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; + if (!sendMultiTouchData(ea)) + _oscStream << osc::BeginMessage("/osgga/mouse/press") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; _oscStream << osc::EndBundle; do_send = true; break; case osgGA::GUIEventAdapter::RELEASE: beginSendInputRange(ea, msg_id); - sendMultiTouchData(ea); - _oscStream << osc::BeginMessage("/osgga/mouse/release") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; + if (!sendMultiTouchData(ea)) + _oscStream << osc::BeginMessage("/osgga/mouse/release") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; _oscStream << osc::EndBundle; do_send = true; break; case osgGA::GUIEventAdapter::DOUBLECLICK: beginSendInputRange(ea, msg_id); - _oscStream << osc::BeginMessage("/osgga/mouse/doublepress") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; + if (!sendMultiTouchData(ea)) + _oscStream << osc::BeginMessage("/osgga/mouse/doublepress") << ea.getX() << ea.getY() << getButtonNum(ea) << osc::EndMessage; _oscStream << osc::EndBundle; do_send = true; break; @@ -188,8 +187,8 @@ bool OscSendingDevice::sendUIEventImpl(const osgGA::GUIEventAdapter &ea, MsgIdTy case osgGA::GUIEventAdapter::MOVE: case osgGA::GUIEventAdapter::DRAG: beginSendInputRange(ea, msg_id); - sendMultiTouchData(ea); - _oscStream << osc::BeginMessage("/osgga/mouse/motion") << ea.getX() << ea.getY() << osc::EndMessage; + if (!sendMultiTouchData(ea)) + _oscStream << osc::BeginMessage("/osgga/mouse/motion") << ea.getX() << ea.getY() << osc::EndMessage; _oscStream << osc::EndBundle; do_send = true; break; @@ -227,10 +226,21 @@ bool OscSendingDevice::sendUIEventImpl(const osgGA::GUIEventAdapter &ea, MsgIdTy if (do_send) { - OSG_INFO << "OscDevice :: sending ui-event per OSC " << std::endl; + // OSG_INFO << "OscDevice :: sending ui-event per OSC " << std::endl; _transmitSocket.Send( _oscStream.Data(), _oscStream.Size() ); _oscStream.Clear(); + + if (_finishMultiTouchSequence) + { + // if the last touch-point ended we'll need to send an empty tuio-bundle, so the receiver gets a chance to clean up + beginBundle(msg_id); + beginMultiTouchSequence(); + _oscStream << osc::EndBundle; + _transmitSocket.Send( _oscStream.Data(), _oscStream.Size() ); + _oscStream.Clear(); + _finishMultiTouchSequence = false; + } } return do_send; @@ -273,21 +283,28 @@ void OscSendingDevice::beginSendInputRange(const osgGA::GUIEventAdapter &ea, Msg } +void OscSendingDevice::beginMultiTouchSequence() { -void OscSendingDevice::sendMultiTouchData(const osgGA::GUIEventAdapter &ea) -{ - if(!ea.isMultiTouchEvent()) - return; - std::string application_name; getUserValue("tuio_application_name", application_name); if (application_name.empty()) application_name = std::string("OpenSceneGraph ") + osgGetVersion() + "@127.0.0.1"; - osgGA::GUIEventAdapter::TouchData* touch_data = ea.getTouchData(); - _oscStream << osc::BeginMessage("/tuio/2Dcur") << "source" << application_name.c_str() << osc::EndMessage; + _oscStream << osc::BeginMessage("/tuio/2Dcur") << "fseq" << static_cast(_msgId) << osc::EndMessage; + +} + + +bool OscSendingDevice::sendMultiTouchData(const osgGA::GUIEventAdapter &ea) +{ + if(!ea.isMultiTouchEvent()) + return false; + + beginMultiTouchSequence(); + + osgGA::GUIEventAdapter::TouchData* touch_data = ea.getTouchData(); _oscStream << osc::BeginMessage("/tuio/2Dcur") << "alive"; for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i) @@ -295,23 +312,33 @@ void OscSendingDevice::sendMultiTouchData(const osgGA::GUIEventAdapter &ea) _oscStream << osc::EndMessage; unsigned int j(0); + unsigned int num_ended(0); for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i, ++j) { float x = (ea.getTouchPointNormalizedX(j) + 1.0) / 2.0; float y =(ea.getTouchPointNormalizedY(j) + 1.0) / 2.0; + // flip y if origin is not top/left + if(ea.getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS) + y *= -1; + float vel_x(0), vel_y(0), accel(0); if (_lastEvent.valid()) { - + // TODO: add velocity + acceleration } _oscStream << osc::BeginMessage("/tuio/2Dcur") << "set" << static_cast(i->id) << x << y << vel_x << vel_y << accel << osc::EndMessage; + if(i->phase == osgGA::GUIEventAdapter::TOUCH_ENDED) + num_ended++; } - _oscStream << osc::BeginMessage("/tuio/2Dcur") << "fseq" << static_cast(_msgId) << osc::EndMessage; - _lastEvent = new osgGA::GUIEventAdapter(ea); + + _finishMultiTouchSequence = (num_ended == touch_data->getNumTouchPoints()); + + + return true; } diff --git a/src/osgPlugins/osc/OscSendingDevice.hpp b/src/osgPlugins/osc/OscSendingDevice.hpp index 9d41a65be..0ba922249 100644 --- a/src/osgPlugins/osc/OscSendingDevice.hpp +++ b/src/osgPlugins/osc/OscSendingDevice.hpp @@ -65,7 +65,8 @@ private: bool sendUIEventImpl(const osgGA::GUIEventAdapter &ea,MsgIdType msg_id); void beginBundle(MsgIdType msg_id); void beginSendInputRange(const osgGA::GUIEventAdapter& ea, MsgIdType msg_id); - void sendMultiTouchData(const osgGA::GUIEventAdapter& ea); + void beginMultiTouchSequence(); + bool sendMultiTouchData(const osgGA::GUIEventAdapter& ea); int getButtonNum(const osgGA::GUIEventAdapter& ea); void sendUserDataContainer(const std::string& key, const osg::UserDataContainer* udc, bool asBundle, MsgIdType msg_id); std::string transliterateKey(const std::string& key) const; @@ -76,6 +77,7 @@ private: unsigned int _numMessagesPerEvent, _delayBetweenSendsInMilliSecs; osc::int64 _msgId; osg::ref_ptr _lastEvent; + bool _finishMultiTouchSequence; }; diff --git a/src/osgPlugins/p3d/ReaderWriterP3D.cpp b/src/osgPlugins/p3d/ReaderWriterP3D.cpp index 4af33274f..f62d3a24c 100644 --- a/src/osgPlugins/p3d/ReaderWriterP3D.cpp +++ b/src/osgPlugins/p3d/ReaderWriterP3D.cpp @@ -2020,12 +2020,19 @@ void ReaderWriterP3DXML::parseLayer(osgPresentation::SlideShowConstructor& const OSG_INFO<<"click_to_run ["<contents<<"]"<contents,osgPresentation::RUN, jumpData); } - else if (match(cur->name, "forward_mouse_event_to_device")) + else if (match(cur->name,"forward_mouse_event_to_device") || match(cur->name,"forward_event_to_device")) { osgPresentation::JumpData jumpData; - OSG_ALWAYS<<"forward_mouse_event_to_device ["<contents<<"]"<contents,osgPresentation::FORWARD_EVENT, jumpData); + OSG_INFO<<"forward_mouse_event_to_device ["<contents<<"]"<contents,osgPresentation::FORWARD_MOUSE_EVENT, jumpData); + } + else if (match(cur->name,"forward_touch_event_to_device")) + { + osgPresentation::JumpData jumpData; + + OSG_INFO<<"forward_touch_event_to_device ["<contents<<"]"<contents,osgPresentation::FORWARD_TOUCH_EVENT, jumpData); } else if (match(cur->name, "click_to_load")) { diff --git a/src/osgPresentation/deprecated/KeyEventHandler.cpp b/src/osgPresentation/deprecated/KeyEventHandler.cpp index 24cb90923..904275c5b 100644 --- a/src/osgPresentation/deprecated/KeyEventHandler.cpp +++ b/src/osgPresentation/deprecated/KeyEventHandler.cpp @@ -149,7 +149,8 @@ void KeyEventHandler::doOperation() OSG_NOTICE<<"Requires jump "< cloned_ea = osg::clone(&ea); + + // clear touch-data as this prevents sending the event as mouse-event + cloned_ea->setTouchData(NULL); + + // reproject mouse-coord const osg::BoundingBox bb(hitr->drawable->getBound()); const osg::Vec3& p(hitr->localIntersectionPoint); @@ -85,8 +90,53 @@ bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionA cloned_ea->setY(ea.getYmin() + transformed_y * (ea.getYmax() - ea.getYmin())); cloned_ea->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + + // std::cout << transformed_x << "/" << transformed_x << " -> " << cloned_ea->getX() << "/" <getY() << std::endl; + SlideEventHandler::instance()->forwardEventToDevices(cloned_ea.get()); + } + else if ((_operation == FORWARD_TOUCH_EVENT) && ea.isMultiTouchEvent()) + { + osg::ref_ptr cloned_ea = osg::clone(&ea); + osgGA::GUIEventAdapter::TouchData* touch_data = cloned_ea->getTouchData(); + + + + // reproject touch-points + const osg::BoundingBox bb(hitr->drawable->getBound()); + + osg::Camera* camera = viewer->getCamera(); + osg::Matrix matrix = osg::computeLocalToWorld(hitr->nodePath, false) * camera->getViewMatrix() * camera->getProjectionMatrix(); + matrix.postMult(camera->getViewport()->computeWindowMatrix()); + + osg::Matrixd inverse; + inverse.invert(matrix); + + // transform touch-points into local coord-system + unsigned int j(0); + for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i, ++j) + { + osg::Vec3 local = osg::Vec3(i->x, i->y, 0) * inverse; + + // std::cout << local << " hit: " << hitr->localIntersectionPoint << std::endl; + + local.x() = (local.x() - bb.xMin()) / (bb.xMax() - bb.xMin()); + local.z() = (local.z() - bb.zMin()) / (bb.zMax() - bb.zMin()); + + local.x() = (ea.getXmin() + local.x() * (ea.getXmax() - ea.getXmin())); + local.z() = (ea.getYmin() + local.z() * (ea.getYmax() - ea.getYmin())); + + // std::cout << ea.getX() << "/" << ea.getY() << " -- " << i->x << " " << i->y << " -> " << local.x() <<"/" << local.z() << std::endl; + + i->x = local.x(); + i->y = local.z(); + } + + + // std::cout << transformed_x << "/" << transformed_x << " -> " << cloned_ea->getX() << "/" <getY() << std::endl; + + SlideEventHandler::instance()->forwardEventToDevices(cloned_ea.get()); } else @@ -206,7 +256,8 @@ void PickEventHandler::doOperation() OSG_INFO<<"Requires jump "< osg_event(NULL); - NSRect bounds = [self bounds]; + for(unsigned int i=0; i<[allTouches count]; i++) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; - osg::Vec2 pixelPos(pos.x * bounds.size.width, (pos.y) * bounds.size.height); + pos.x *= bounds.size.width; + pos.y *= bounds.size.height; unsigned int touch_id = [self computeTouchId: touch mayCleanup:FALSE]; - if (!osg_event) { - osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); - } else { - osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + if (!osg_event) + { + osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y); + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + osg_event->setInputRange(0, 0, bounds.size.width, bounds.size.height); + } + else + { + osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y); } } } @@ -897,12 +903,18 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; - osg::Vec2 pixelPos(pos.x * bounds.size.width, (pos.y) * bounds.size.height); + pos.x *= bounds.size.width; + pos.y *= bounds.size.height; unsigned int touch_id = [self computeTouchId: touch mayCleanup:FALSE]; - if (!osg_event) { - osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); - } else { - osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); + if (!osg_event) + { + osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y); + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + osg_event->setInputRange(0, 0, bounds.size.width, bounds.size.height); + } + else + { + osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y); } } } @@ -914,17 +926,24 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect) osg::ref_ptr osg_event(NULL); NSRect bounds = [self bounds]; + for(unsigned int i=0; i<[allTouches count]; i++) { NSTouch *touch = [[allTouches allObjects] objectAtIndex:i]; NSPoint pos = [touch normalizedPosition]; - osg::Vec2 pixelPos(pos.x * bounds.size.width, (pos.y) * bounds.size.height); + pos.x *= bounds.size.width; + pos.y *= bounds.size.height; unsigned int touch_id = [self computeTouchId: touch mayCleanup: TRUE]; - if (!osg_event) { - osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), 1); - } else { - osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), 1); + if (!osg_event) + { + osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y, 1); + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + osg_event->setInputRange(0, 0, bounds.size.width, bounds.size.height); + } + else + { + osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pos.x, pos.y, 1); } } diff --git a/src/osgViewer/GraphicsWindowIOS.mm b/src/osgViewer/GraphicsWindowIOS.mm index 535b2dc85..d81b20e7f 100644 --- a/src/osgViewer/GraphicsWindowIOS.mm +++ b/src/osgViewer/GraphicsWindowIOS.mm @@ -580,11 +580,17 @@ typedef std::map TouchPointsIdMapping; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: FALSE]; - if (!osg_event) { + if (!osg_event) + { osg_event = _win->getEventQueue()->touchBegan(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); - } else { + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); + + } + else + { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } + } [super touchesBegan:touches withEvent:event]; @@ -603,11 +609,17 @@ typedef std::map TouchPointsIdMapping; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: FALSE]; - if (!osg_event) { + if (!osg_event) + { osg_event = _win->getEventQueue()->touchMoved(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); - } else { + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); + + } + else + { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y()); } + } [super touchesMoved:touches withEvent:event]; @@ -626,11 +638,17 @@ typedef std::map TouchPointsIdMapping; CGPoint pos = [touch locationInView:self]; osg::Vec2 pixelPos = [self convertPointToPixel: osg::Vec2(pos.x,pos.y)]; unsigned int touch_id = [self computeTouchId: touch mayCleanup: TRUE]; - if (!osg_event) { + if (!osg_event) + { osg_event = _win->getEventQueue()->touchEnded(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); - } else { + osg_event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); + + } + else + { osg_event->addTouchPoint(touch_id, [self convertTouchPhase: [touch phase]], pixelPos.x(), pixelPos.y(), [touch tapCount]); } + } [super touchesEnded:touches withEvent:event]; diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index cb66e3e3c..4a94389cd 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -927,6 +927,11 @@ void Viewer::eventTraversal() { event->setY((event->getYmax()-event->getY())+event->getYmin()); event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); + if(event->isMultiTouchEvent()) { + for(osgGA::GUIEventAdapter::TouchData::iterator itr = event->getTouchData()->begin(); itr != event->getTouchData()->end(); itr++) { + itr->y = event->getYmax() - itr->y + event->getYmin(); + } + } } #endif