root/OpenSceneGraph/trunk/src/osgGA/EventQueue.cpp @ 11934

Revision 11934, 16.3 kB (checked in by robert, 3 years ago)

From Stephan Huber, "attached you'll find a proposal for handling multi-touch-events with
osgGA. My approach is to bundle all touchpoints into one custom data
structure which is attached to an GUIEventAdapter.

The current approach simulates a moving mouse for the first touch-point,
so basic manipulators do work, sort of.

I created a MultiTouchTrackballManipulator?-class, one touch-point does
rotate the view, two touch-points pan and zoom the view as known from
the iphone or other similar multi-touch-devices. A double-tap (similar
to a double-click) resets the manipulator to its home-position.

The multi-touch-trackball-implementation is not the best, see it as a
first starting point. (there's a demo-video at http://vimeo.com/15017377 )"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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
14#include <osgGA/EventQueue>
15#include <osg/Notify>
16
17using namespace osgGA;
18
19EventQueue::EventQueue(GUIEventAdapter::MouseYOrientation mouseYOrientation)
20{
21    _useFixedMouseInputRange = false;
22
23    _startTick = osg::Timer::instance()->getStartTick();
24
25    _accumulateEventState = new GUIEventAdapter();
26    _accumulateEventState->setMouseYOrientation(mouseYOrientation);
27}
28
29EventQueue::~EventQueue()
30{
31}
32
33void EventQueue::setEvents(Events& events)
34{
35    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
36    _eventQueue = events;
37}
38
39void EventQueue::appendEvents(Events& events)
40{
41    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
42    _eventQueue.insert(_eventQueue.end(), events.begin(), events.end());
43}
44
45void EventQueue::addEvent(GUIEventAdapter* event)
46{
47    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
48    _eventQueue.push_back(event);
49}
50
51bool EventQueue::takeEvents(Events& events)
52{
53    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
54    if (!_eventQueue.empty())
55    {
56        events.splice(events.end(), _eventQueue);
57        return true;
58    }
59    else
60    {
61        return false;
62    }
63}
64
65bool EventQueue::copyEvents(Events& events) const
66{
67    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_eventQueueMutex);
68    if (!_eventQueue.empty())
69    {
70        events.insert(events.end(),_eventQueue.begin(),_eventQueue.end());
71        return true;
72    }
73    else
74    {
75        return false;
76    }
77}
78
79
80void EventQueue::windowResize(int x, int y, int width, int height, double time)
81{
82    _accumulateEventState->setWindowRectangle(x, y, width, height, !_useFixedMouseInputRange);
83
84    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
85    event->setEventType(GUIEventAdapter::RESIZE);
86    event->setTime(time);
87
88    addEvent(event);
89}
90
91void EventQueue::penPressure(float pressure, double time)
92{
93    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
94    event->setEventType(GUIEventAdapter::PEN_PRESSURE);
95    event->setPenPressure(pressure);
96    event->setTime(time);
97   
98    addEvent(event);
99}
100
101void EventQueue::penOrientation(float tiltX, float tiltY, float rotation, double time)
102{
103    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
104    event->setEventType(GUIEventAdapter::PEN_ORIENTATION);
105    event->setPenTiltX(tiltX);
106    event->setPenTiltY(tiltY);
107    event->setPenRotation(rotation);
108    event->setTime(time);
109   
110    addEvent(event);
111}
112
113void EventQueue::penProximity(GUIEventAdapter::TabletPointerType pt, bool isEntering, double time)
114{
115    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
116    event->setEventType( (isEntering) ? GUIEventAdapter::PEN_PROXIMITY_ENTER : GUIEventAdapter::PEN_PROXIMITY_LEAVE);
117    event->setTabletPointerType(pt);
118    event->setTime(time);
119   
120    addEvent(event);
121}
122
123void EventQueue::mouseScroll(GUIEventAdapter::ScrollingMotion sm, double time)
124{
125    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
126    event->setEventType(GUIEventAdapter::SCROLL);
127    event->setScrollingMotion(sm);
128    event->setTime(time);
129   
130    addEvent(event);
131}
132
133void EventQueue::mouseScroll2D(float x, float y, double time)
134{
135    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
136    event->setEventType(GUIEventAdapter::SCROLL);
137    event->setScrollingMotionDelta(x,y);
138    event->setTime(time);
139   
140    addEvent(event);
141}
142
143
144void EventQueue::mouseWarped(float x, float y)
145{
146    _accumulateEventState->setX(x);
147    _accumulateEventState->setY(y);
148}
149
150
151void EventQueue::mouseMotion(float x, float y, double time)
152{
153    _accumulateEventState->setX(x);
154    _accumulateEventState->setY(y);
155
156    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
157    event->setEventType(event->getButtonMask() ? GUIEventAdapter::DRAG : GUIEventAdapter::MOVE);
158    event->setTime(time);
159   
160    addEvent(event);
161}
162
163void EventQueue::mouseButtonPress(float x, float y, unsigned int button, double time)
164{
165    _accumulateEventState->setX(x);
166    _accumulateEventState->setY(y);
167
168    switch(button)
169    {
170        case(1):
171            _accumulateEventState->setButtonMask(GUIEventAdapter::LEFT_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
172            break;
173        case(2):
174            _accumulateEventState->setButtonMask(GUIEventAdapter::MIDDLE_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
175            break;
176        case(3):
177            _accumulateEventState->setButtonMask(GUIEventAdapter::RIGHT_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
178            break;
179    }
180
181    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
182    event->setEventType(GUIEventAdapter::PUSH);
183    event->setTime(time);
184
185    switch(button)
186    {
187        case(1):
188            event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON);
189            break;
190        case(2):
191            event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON);
192            break;
193        case(3):
194            event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON);
195            break;
196    }
197   
198    addEvent(event);
199}
200
201void EventQueue::mouseDoubleButtonPress(float x, float y, unsigned int button, double time)
202{
203    _accumulateEventState->setX(x);
204    _accumulateEventState->setY(y);
205
206    switch(button)
207    {
208        case(1):
209            _accumulateEventState->setButtonMask(GUIEventAdapter::LEFT_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
210            break;
211        case(2):
212            _accumulateEventState->setButtonMask(GUIEventAdapter::MIDDLE_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
213            break;
214        case(3):
215            _accumulateEventState->setButtonMask(GUIEventAdapter::RIGHT_MOUSE_BUTTON | _accumulateEventState->getButtonMask());
216            break;
217    }
218
219    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
220    event->setEventType(GUIEventAdapter::DOUBLECLICK);
221    event->setTime(time);
222
223    switch(button)
224    {
225        case(1):
226            event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON);
227            break;
228        case(2):
229            event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON);
230            break;
231        case(3):
232            event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON);
233            break;
234    }
235   
236    addEvent(event);
237}
238
239void EventQueue::mouseButtonRelease(float x, float y, unsigned int button, double time)
240{
241    _accumulateEventState->setX(x);
242    _accumulateEventState->setY(y);
243
244    switch(button)
245    {
246        case(1):
247            _accumulateEventState->setButtonMask(~GUIEventAdapter::LEFT_MOUSE_BUTTON & _accumulateEventState->getButtonMask());
248            break;
249        case(2):
250            _accumulateEventState->setButtonMask(~GUIEventAdapter::MIDDLE_MOUSE_BUTTON & _accumulateEventState->getButtonMask());
251            break;
252        case(3):
253            _accumulateEventState->setButtonMask(~GUIEventAdapter::RIGHT_MOUSE_BUTTON & _accumulateEventState->getButtonMask());
254            break;
255    }
256
257    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
258    event->setEventType(GUIEventAdapter::RELEASE);
259    event->setTime(time);
260
261    switch(button)
262    {
263        case(1):
264            event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON);
265            break;
266        case(2):
267            event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON);
268            break;
269        case(3):
270            event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON);
271            break;
272    }
273   
274    addEvent(event);
275}
276
277void EventQueue::keyPress(int key, double time)
278{
279    switch(key)
280    {
281        case(GUIEventAdapter::KEY_Shift_L):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_SHIFT | _accumulateEventState->getModKeyMask()); break;
282        case(GUIEventAdapter::KEY_Shift_R):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_SHIFT | _accumulateEventState->getModKeyMask()); break;
283        case(GUIEventAdapter::KEY_Control_L):    _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_CTRL | _accumulateEventState->getModKeyMask()); break;
284        case(GUIEventAdapter::KEY_Control_R):    _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_CTRL | _accumulateEventState->getModKeyMask()); break;
285        case(GUIEventAdapter::KEY_Meta_L):       _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_META | _accumulateEventState->getModKeyMask()); break;
286        case(GUIEventAdapter::KEY_Meta_R):       _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_META | _accumulateEventState->getModKeyMask()); break;
287        case(GUIEventAdapter::KEY_Alt_L):        _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_ALT | _accumulateEventState->getModKeyMask()); break;
288        case(GUIEventAdapter::KEY_Alt_R):        _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_ALT | _accumulateEventState->getModKeyMask()); break;
289        case(GUIEventAdapter::KEY_Super_L):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_SUPER | _accumulateEventState->getModKeyMask()); break;
290        case(GUIEventAdapter::KEY_Super_R):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_SUPER | _accumulateEventState->getModKeyMask()); break;
291        case(GUIEventAdapter::KEY_Hyper_L):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_LEFT_HYPER | _accumulateEventState->getModKeyMask()); break;
292        case(GUIEventAdapter::KEY_Hyper_R):      _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_RIGHT_HYPER | _accumulateEventState->getModKeyMask()); break;
293        case(GUIEventAdapter::KEY_Caps_Lock):
294        {
295            if ((_accumulateEventState->getModKeyMask() & GUIEventAdapter::MODKEY_CAPS_LOCK)!=0)
296                _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_CAPS_LOCK & _accumulateEventState->getModKeyMask());
297            else 
298                _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_CAPS_LOCK | _accumulateEventState->getModKeyMask());
299            break;
300        }
301        case(GUIEventAdapter::KEY_Num_Lock):
302        {
303            if ((_accumulateEventState->getModKeyMask() & GUIEventAdapter::MODKEY_NUM_LOCK)!=0)
304                 _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_NUM_LOCK & _accumulateEventState->getModKeyMask());
305            else
306                 _accumulateEventState->setModKeyMask(GUIEventAdapter::MODKEY_NUM_LOCK | _accumulateEventState->getModKeyMask());
307            break;
308        }
309        default: break;
310    }       
311
312    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
313    event->setEventType(GUIEventAdapter::KEYDOWN);
314    event->setKey(key);
315    event->setTime(time);
316   
317    addEvent(event);
318}
319
320void EventQueue::keyRelease(int key, double time)
321{
322    switch(key)
323    {
324        case(GUIEventAdapter::KEY_Shift_L):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_SHIFT & _accumulateEventState->getModKeyMask()); break;
325        case(GUIEventAdapter::KEY_Shift_R):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_SHIFT & _accumulateEventState->getModKeyMask()); break;
326        case(GUIEventAdapter::KEY_Control_L):    _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_CTRL & _accumulateEventState->getModKeyMask()); break;
327        case(GUIEventAdapter::KEY_Control_R):    _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_CTRL & _accumulateEventState->getModKeyMask()); break;
328        case(GUIEventAdapter::KEY_Meta_L):       _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_META & _accumulateEventState->getModKeyMask()); break;
329        case(GUIEventAdapter::KEY_Meta_R):       _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_META & _accumulateEventState->getModKeyMask()); break;
330        case(GUIEventAdapter::KEY_Alt_L):        _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_ALT & _accumulateEventState->getModKeyMask()); break;
331        case(GUIEventAdapter::KEY_Alt_R):        _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_ALT & _accumulateEventState->getModKeyMask()); break;
332        case(GUIEventAdapter::KEY_Super_L):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_SUPER & _accumulateEventState->getModKeyMask()); break;
333        case(GUIEventAdapter::KEY_Super_R):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_SUPER & _accumulateEventState->getModKeyMask()); break;
334        case(GUIEventAdapter::KEY_Hyper_L):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_LEFT_HYPER & _accumulateEventState->getModKeyMask()); break;
335        case(GUIEventAdapter::KEY_Hyper_R):      _accumulateEventState->setModKeyMask(~GUIEventAdapter::MODKEY_RIGHT_HYPER & _accumulateEventState->getModKeyMask()); break;
336        default: break;
337    }       
338
339    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
340    event->setEventType(GUIEventAdapter::KEYUP);
341    event->setKey(key);
342    event->setTime(time);
343   
344    addEvent(event);
345}
346
347
348GUIEventAdapter*  EventQueue::touchBegan(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, double time)
349{
350    // emulate left mouse button press
351   
352    _accumulateEventState->setButtonMask((1) | _accumulateEventState->getButtonMask());
353    _accumulateEventState->setX(x);
354    _accumulateEventState->setY(y);
355   
356    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
357    event->setEventType(GUIEventAdapter::PUSH);
358    event->setTime(time);
359    event->addTouchPoint(id, phase, x, y, 0);
360 
361    addEvent(event);
362   
363    return event;
364}
365       
366       
367GUIEventAdapter*  EventQueue::touchMoved(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, double time)
368{
369    _accumulateEventState->setX(x);
370    _accumulateEventState->setY(y);
371
372   
373    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
374    event->setEventType(GUIEventAdapter::DRAG);
375    event->setTime(time);
376    event->addTouchPoint(id, phase, x, y, 0);
377    addEvent(event);
378   
379    return event;
380}
381
382GUIEventAdapter*  EventQueue::touchEnded(unsigned int id, GUIEventAdapter::TouchPhase phase, float x, float y, unsigned int tap_count, double time)
383{
384    _accumulateEventState->setButtonMask(~(1) & _accumulateEventState->getButtonMask());
385    _accumulateEventState->setX(x);
386    _accumulateEventState->setY(y);
387   
388    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
389    event->setEventType(GUIEventAdapter::RELEASE);
390    event->setTime(time);
391    event->addTouchPoint(id, phase, x, y, tap_count);
392    addEvent(event);
393   
394    return event;
395}
396       
397
398void EventQueue::closeWindow(double time)
399{
400    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
401    event->setEventType(GUIEventAdapter::CLOSE_WINDOW);
402    event->setTime(time);
403 
404    addEvent(event);
405}
406
407void EventQueue::quitApplication(double time)
408{
409    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
410    event->setEventType(GUIEventAdapter::QUIT_APPLICATION);
411    event->setTime(time);
412 
413    addEvent(event);
414}
415
416
417void EventQueue::frame(double time)
418{
419    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
420    event->setEventType(GUIEventAdapter::FRAME);
421    event->setTime(time);
422   
423    addEvent(event);
424}
425
426GUIEventAdapter* EventQueue::createEvent()
427{
428    if (_accumulateEventState.valid()) return new GUIEventAdapter(*_accumulateEventState.get());
429    else return new GUIEventAdapter();   
430}
431
432void EventQueue::userEvent(osg::Referenced* userEventData, double time)
433{
434    GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
435    event->setEventType(GUIEventAdapter::USER);
436    event->setUserData(userEventData);
437    event->setTime(time);
438   
439    addEvent(event);
440}
441
Note: See TracBrowser for help on using the browser.