From 09f8d67a8a06229bec6413a02d0801debc416475 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sun, 26 Apr 2009 01:11:49 +0000 Subject: [PATCH] iphone touches --- panda/src/iphone/eaglView.mm | 37 +++ panda/src/iphone/iPhoneGraphicsWindow.h | 14 +- panda/src/iphone/iPhoneGraphicsWindow.mm | 298 +++++++++++++++++------ panda/src/tform/trackball.cxx | 10 +- panda/src/tform/trackball.h | 2 +- 5 files changed, 276 insertions(+), 85 deletions(-) diff --git a/panda/src/iphone/eaglView.mm b/panda/src/iphone/eaglView.mm index f90e6d0a3a..fad49aa1de 100644 --- a/panda/src/iphone/eaglView.mm +++ b/panda/src/iphone/eaglView.mm @@ -64,6 +64,8 @@ viewFramebuffer = 0; viewRenderbuffer = 0; depthRenderbuffer = 0; + + self.multipleTouchEnabled = YES; } return self; } @@ -73,6 +75,41 @@ [context presentRenderbuffer:GL_RENDERBUFFER_OES]; } +- (void)touchesBegan: (NSSet *)touches + withEvent: (UIEvent *)event +{ + // Pass the multi-touch input to the _window for processing. + _window->touches_began(touches, event); + [super touchesBegan: touches withEvent: event]; +} + +- (void)touchesMoved: (NSSet *)touches + withEvent: (UIEvent *)event +{ + _window->touches_moved(touches, event); + [super touchesMoved: touches withEvent: event]; +} + +- (void)touchesEnded: (NSSet *)touches + withEvent: (UIEvent *)event +{ + _window->touches_ended(touches, event); + [super touchesEnded: touches withEvent: event]; +} + +- (void)touchesCancelled: (NSSet *)touches + withEvent: (UIEvent *)event +{ + _window->touches_cancelled(touches, event); + [super touchesCancelled: touches withEvent: event]; +} + +/* +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; +*/ + - (void)layoutSubviews { [EAGLContext setCurrentContext:context]; diff --git a/panda/src/iphone/iPhoneGraphicsWindow.h b/panda/src/iphone/iPhoneGraphicsWindow.h index 90a744687f..4dde1572ce 100644 --- a/panda/src/iphone/iPhoneGraphicsWindow.h +++ b/panda/src/iphone/iPhoneGraphicsWindow.h @@ -21,6 +21,8 @@ #include "glesgsg.h" #import "eaglView.h" +#import + //////////////////////////////////////////////////////////////////// // Class : IPhoneGraphicsWindow // Description : An interface to the osx/ system for managing GL @@ -47,20 +49,26 @@ public: virtual void clear_pipe(); void rotate_window(); + void touches_began(NSSet *touches, UIEvent *event); + void touches_moved(NSSet *touches, UIEvent *event); + void touches_ended(NSSet *touches, UIEvent *event); + void touches_cancelled(NSSet *touches, UIEvent *event); + + CGPoint get_average_location(NSSet *touches); + protected: virtual void close_window(); virtual bool open_window(); private: - void system_close_window(); - void system_set_window_foreground(bool foreground); - void set_pointer_in_window(int x, int y); void set_pointer_out_of_window(); + void handle_button_delta(int num_touches); private: EAGLView *_gl_view; + int _last_buttons; public: static TypeHandle get_class_type() { diff --git a/panda/src/iphone/iPhoneGraphicsWindow.mm b/panda/src/iphone/iPhoneGraphicsWindow.mm index 2abbbf8985..6582febb4f 100644 --- a/panda/src/iphone/iPhoneGraphicsWindow.mm +++ b/panda/src/iphone/iPhoneGraphicsWindow.mm @@ -57,6 +57,7 @@ IPhoneGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, DCAST_INTO_V(ipipe, _pipe); ipipe->_graphics_windows.insert(this); _gl_view = nil; + _last_buttons = 0; GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse"); @@ -75,29 +76,6 @@ IPhoneGraphicsWindow:: } } -//////////////////////////////////////////////////////////////////// -// Function: IPhoneGraphicsWindow::set_pointer_in_window -// Access: Private -// Description: Indicates the mouse pointer is seen within the -// window. -//////////////////////////////////////////////////////////////////// -void IPhoneGraphicsWindow:: -set_pointer_in_window(int x, int y) { - _input_devices[0].set_pointer_in_window(x, y); -} - -//////////////////////////////////////////////////////////////////// -// Function: IPhoneGraphicsWindow::set_pointer_out_of_window -// Access: Private -// Description: Indicates the mouse pointer is no longer within the -// window. -//////////////////////////////////////////////////////////////////// -void IPhoneGraphicsWindow:: -set_pointer_out_of_window() { - _input_devices[0].set_pointer_out_of_window(); -} - - //////////////////////////////////////////////////////////////////// // Function: IPhoneGraphicsWindow::begin_frame // Access: Public, Virtual @@ -170,61 +148,6 @@ void IPhoneGraphicsWindow:: begin_flip() { } -//////////////////////////////////////////////////////////////////// -// Function: IPhoneGraphicsWindow::close_window -// Access: Protected, Virtual -// Description: Closes the window right now. Called from the window -// thread. -//////////////////////////////////////////////////////////////////// -void IPhoneGraphicsWindow:: -close_window() { - // system_close_window(); - - WindowProperties properties; - properties.set_open(false); - system_changed_properties(properties); - -// release_system_resources(false); - _gsg.clear(); - _active = false; - GraphicsWindow::close_window(); -} - -//////////////////////////////////////////////////////////////////// -// Function: IPhoneGraphicsWindow::open_window -// Access: Protected, Virtual -// Description: Opens the window right now. Called from the window -// thread. Returns true if the window is successfully -// opened, or false if there was a problem. -//////////////////////////////////////////////////////////////////// -bool IPhoneGraphicsWindow:: -open_window() { - nassertr(_gsg == (GraphicsStateGuardian *)NULL, false); - - _gl_view = [ [ EAGLView alloc ] initWithFrame: - [ [ UIScreen mainScreen ] applicationFrame ] - ]; - _gl_view->_window = this; - - IPhoneGraphicsPipe *iphonepipe = DCAST(IPhoneGraphicsPipe, _pipe); - nassertr(iphonepipe != NULL, false); - - iphonepipe->_view_controller.view = _gl_view; - [ _gl_view layoutSubviews ]; - - _gsg = new IPhoneGraphicsStateGuardian(_engine, _pipe, NULL); - - CGRect bounds = [_gl_view bounds]; - - _properties.set_size(bounds.size.width, bounds.size.height); - _properties.set_foreground(true); - _properties.set_minimized(false); - _properties.set_open(true); - _is_valid = true; - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: IPhoneGraphicsWindow::process_events // Access: Protected, Virtual @@ -285,7 +208,7 @@ clear_pipe() { //////////////////////////////////////////////////////////////////// // Function: IPhoneGraphicsWindow::rotate_window -// Access: Public, Virtual +// Access: Public // Description: Called in response to an orientation change event, // this tells the window to resize itself according to // the new orientation. @@ -298,3 +221,220 @@ rotate_window() { properties.set_size(bounds.size.width, bounds.size.height); system_changed_properties(properties); } + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::touches_began +// Access: Public +// Description: Beginning a single- or multi-touch gesture. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +touches_began(NSSet *touches, UIEvent *event) { + // Average the position of all of the touches. + CGPoint location = get_average_location(touches); + + set_pointer_in_window(location.x, location.y); + handle_button_delta([touches count]); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::touches_moved +// Access: Public +// Description: Continuing a single- or multi-touch gesture. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +touches_moved(NSSet *touches, UIEvent *event) { + // Average the position of all of the touches. + CGPoint location = get_average_location(touches); + + set_pointer_in_window(location.x, location.y); + handle_button_delta([touches count]); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::touches_ended +// Access: Public +// Description: Finishing a single- or multi-touch gesture. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +touches_ended(NSSet *touches, UIEvent *event) { + set_pointer_out_of_window(); + handle_button_delta(0); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::touches_cancelled +// Access: Public +// Description: Cancelling a single- or multi-touch gesture. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +touches_cancelled(NSSet *touches, UIEvent *event) { + set_pointer_out_of_window(); + handle_button_delta(0); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::get_average_location +// Access: Public +// Description: Returns the average location of all of the indicated +// touches. +//////////////////////////////////////////////////////////////////// +CGPoint IPhoneGraphicsWindow:: +get_average_location(NSSet *touches) { + NSEnumerator *enumerator = [ touches objectEnumerator ]; + CGPoint sum; + sum.x = 0.0; + sum.y = 0.0; + + UITouch *touch; + while ((touch = [ enumerator nextObject ])) { + CGPoint location = [ touch locationInView: _gl_view ]; + sum.x += location.x; + sum.y += location.y; + } + + int count = [touches count]; + sum.x /= count; + sum.y /= count; + return sum; +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::close_window +// Access: Protected, Virtual +// Description: Closes the window right now. Called from the window +// thread. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +close_window() { + // system_close_window(); + + WindowProperties properties; + properties.set_open(false); + system_changed_properties(properties); + +// release_system_resources(false); + _gsg.clear(); + _active = false; + GraphicsWindow::close_window(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::open_window +// Access: Protected, Virtual +// Description: Opens the window right now. Called from the window +// thread. Returns true if the window is successfully +// opened, or false if there was a problem. +//////////////////////////////////////////////////////////////////// +bool IPhoneGraphicsWindow:: +open_window() { + nassertr(_gsg == (GraphicsStateGuardian *)NULL, false); + + _gl_view = [ [ EAGLView alloc ] initWithFrame: + [ [ UIScreen mainScreen ] applicationFrame ] + ]; + _gl_view->_window = this; + + IPhoneGraphicsPipe *iphonepipe = DCAST(IPhoneGraphicsPipe, _pipe); + nassertr(iphonepipe != NULL, false); + + iphonepipe->_view_controller.view = _gl_view; + [ _gl_view layoutSubviews ]; + + _gsg = new IPhoneGraphicsStateGuardian(_engine, _pipe, NULL); + + CGRect bounds = [_gl_view bounds]; + + _properties.set_size(bounds.size.width, bounds.size.height); + _properties.set_foreground(true); + _properties.set_minimized(false); + _properties.set_open(true); + _is_valid = true; + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::set_pointer_in_window +// Access: Private +// Description: Indicates the mouse pointer is seen within the +// window. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +set_pointer_in_window(int x, int y) { + _input_devices[0].set_pointer_in_window(x, y); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::set_pointer_out_of_window +// Access: Private +// Description: Indicates the mouse pointer is no longer within the +// window. +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +set_pointer_out_of_window() { + _input_devices[0].set_pointer_out_of_window(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IPhoneGraphicsWindow::handle_button_delta +// Access: Private +// Description: Used to emulate button events +//////////////////////////////////////////////////////////////////// +void IPhoneGraphicsWindow:: +handle_button_delta(int num_touches) { + // For now, we'll just map the number of touches to the mouse button + // number. 1 touch is button 1, 2 touches is button 3 (because this + // is the normal secondary button), and 3 touches is button 2. + + // This is just a cheesy remapping that will assist migrating + // applications from standard PC's to iPhone. It also works well + // enough within the existing Panda mouse-input framework. We + // should expose the full multitouch functionality eventually, but + // really, the whole mouse-input framework needs a bit of a + // redesign. + + int new_buttons; + switch (num_touches) { + case 0: + new_buttons = 0x00; + break; + case 1: + new_buttons = 0x01; + break; + case 2: + new_buttons = 0x04; + break; + case 3: + default: + new_buttons = 0x02; + break; + } + + int changed = _last_buttons ^ new_buttons; + + if (changed & 0x01) { + if (new_buttons & 0x01) { + _input_devices[0].button_down(MouseButton::one()); + } else { + _input_devices[0].button_up(MouseButton::one()); + } + } + + if (changed & 0x04) { + if (new_buttons & 0x04) { + _input_devices[0].button_down(MouseButton::two()); + } else { + _input_devices[0].button_up(MouseButton::two()); + } + } + + if (changed & 0x02) { + if (new_buttons & 0x02) { + _input_devices[0].button_down(MouseButton::three()); + } else { + _input_devices[0].button_up(MouseButton::three()); + } + } + + _last_buttons = new_buttons; +} diff --git a/panda/src/tform/trackball.cxx b/panda/src/tform/trackball.cxx index db31fb2e6d..9fb1ce170d 100644 --- a/panda/src/tform/trackball.cxx +++ b/panda/src/tform/trackball.cxx @@ -48,6 +48,7 @@ Trackball(const string &name) : _rotscale = 0.3f; _fwdscale = 0.3f; + _last_button = 0; _lastx = _lasty = 0.5f; _rotation = LMatrix4f::ident_mat(); @@ -582,11 +583,16 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input, float x = this_x - _lastx; float y = this_y - _lasty; + + if (this_button == _last_button) { + apply(x, y, this_button); + } - apply(x, y, this_button); - + _last_button = this_button; _lastx = this_x; _lasty = this_y; + } else { + _last_button = 0; } // Now send our matrix down the pipe. diff --git a/panda/src/tform/trackball.h b/panda/src/tform/trackball.h index 91b2f20902..74c9b9efa0 100644 --- a/panda/src/tform/trackball.h +++ b/panda/src/tform/trackball.h @@ -101,7 +101,7 @@ private: void reextract(); void recompute(); - + int _last_button; float _lastx, _lasty; float _rotscale;