Manejar iOS táctil para emular el mouse para la biblioteca de input C ++

Tengo un código C ++ multiplataforma existente para manejar la input del mouse, con methods como:

onMouseDown(x,y,button) onMouseUp(x,y,button) onMouseMove(x,y,buttons) 

Estoy portando funcionalidad en una aplicación C ++ para iOS … utilizando el objective mínimo C según sea necesario. Me gustaría manejar los gestos de un solo toque para emular la funcionalidad del mouse, así puedo pasar parameters a los methods existentes (además de agregar multitáctil).

¿Qué aspecto tendría el código para hacer esto, idealmente como una aplicación de muestra mínima? ¿Es principalmente la interacción OBJ-C / C ++ lo que realmente me confunde?

A continuación, le explicamos cómo paso el código multi-touch a C ++ para un progtwig OpenGL (con 1 o 2 dedos):

 // Set this in your ViewController's init code [self setMultipleTouchEnabled:YES]; // Implement these in ViewController int touchCount = 0; UITouch* touch[2]; - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{ NSArray* array = [touches allObjects]; UITouch* touchTemp; int t; int touchedPixel[2]; for(int i = 0; i < [array count]; ++i){ touchTemp = [array objectAtIndex:i]; if(touchCount >= 2) return; if(touch[0] == NULL) t = 0; else t = 1; touch[t] = touchTemp; CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view]; ++touchCount; touchedPixel[X] = touchLoc.x; touchedPixel[Y] = touchLoc.y; mainScreen->push(t, touchedPixel); // mainScreen is a C++ object for GL drawing. } } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event{ NSArray* array = [touches allObjects]; UITouch* touchTemp; int t; int touchedPixel[2]; for(int i = 0; i < [array count]; ++i){ touchTemp = [array objectAtIndex:i]; for(t = 0; t < 2; ++t){ // Find the matching touch in the array if(touchTemp == touch[t]) break; } if(t == 2) // Return if touch was not found continue; CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view]; touchedPixel[X] = touchLoc.x; touchedPixel[Y] = touchLoc.y; mainScreen->move(t, touchedPixel); } } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{ NSArray* array = [touches allObjects]; UITouch* touchTemp; int t; int touchedPixel[2]; for(int i = 0; i < [array count]; ++i){ touchTemp = [array objectAtIndex:i]; for(t = 0; t < 2; ++t){ // Find the matching touch in the array if(touchTemp == touch[t]) break; } if(t == 2) // Return if touch was not found continue; CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view]; touch[t] = NULL; --touchCount; touchedPixel[X] = touchLoc.x; touchedPixel[Y] = touchLoc.y; mainScreen->release(t, touchedPixel); } } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event{ printf("Touch cancelled\n"); [self touchesEnded:touches withEvent: event]; } 

para esta situación, implementaría touchesBegan, movido y enviado y reenvía la llamada al código c ++ mouseDown / Moved / Up

Muestra de lo que haría: ¡asume que el código está en el viewController de la aplicación!

 static UITouch *_trackedTouch = nil; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { assert(!_trackedTouch && "no multitouch"); _trackedTouch = [touches anyObject]; CGPoint pt = [_trackedTouch locationInView:self.view]; mouseDown(pt.x,pt.y,0); } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { assert(_trackedTouch && "no touch began"); if(![touches containsObject:_trackedTouch]) return; CGPoint pt = [_trackedTouch locationInView:self.view]; mouseMoved(pt.x,pt.y,0); } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { assert(_trackedTouch && "no touch began"); if(![touches containsObject:_trackedTouch]) return; CGPoint pt = [_trackedTouch locationInView:self.view]; mouseUp(pt.x,pt.y,0); } 

sobre libros mhm … tal vez: https://stackoverflow.com/questions/5308106/book-recommendations-for-objective-c-for-ios-development (pero el arent C ++ sesgado … objC se basa en C. C ++ es algo que puede usar además de ObjC pero … saber que C ++ solo proporciona ayuda limitada para aprender ObjC)

Esto funciona con los casos de uso singletouch y multitouch. He escrito un trozo c ++ lib llamado oldlib que estoy usando en los files obj-c a continuación.

Puedes pasar lo que necesites como button . Mi código pasa la identificación táctil. Supongo que necesitará verificar lo que su biblioteca espera allí y cambiar eso en consecuencia.

Aquí está mi código:

oldlib.h

 #ifndef Quick_oldlib_h #define Quick_oldlib_h void onMouseDown(int x,int y,int button); void onMouseUp(int x,int y,int button); void onMouseMove(int x,int y,int buttons); #endif 

oldlib.cpp

 #include "oldlib.h" #include <stdio.h> void onMouseDown(int x,int y,int button) { printf("onMouseDown:%d,%d button:%d\n", x, y, button); } void onMouseUp(int x,int y,int button) { printf("onMouseUp:%d,%d button:%d\n", x, y, button); } void onMouseMove(int x,int y,int button) { printf("onMouseMove:%d,%d button:%d\n", x, y, button); } 

QViewController.h

 #import <UIKit/UIKit.h> @interface QViewController : UIViewController @end 

QViewController.mm <- tenga en count la extensión MM que permite comstackr esto junto con los encabezados de C ++

 #import "QViewController.h" #include "oldlib.h" @interface QViewController () @property (nonatomic, retain) NSMutableSet* active_touches; @end @implementation QViewController - (void)viewDidLoad { [super viewDidLoad]; self.active_touches = [[NSMutableSet alloc] init]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch* touch in touches) { [self.active_touches addObject:touch]; onMouseDown([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch); } } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch* touch in touches) { if ([self.active_touches containsObject:touch]) { onMouseUp([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch); [self.active_touches removeObject:touch]; } } } - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch* touch in touches) { if ([self.active_touches containsObject:touch]) { onMouseMove([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch); } } } - (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch* touch in touches) { [self.active_touches removeObject:touch]; NSLog(@"cancelled: %@", touch); } } @end 

Para hacer esto, deberá implementar el reenvío táctil y asegurarse de que el toque que acaba de detectar lo consume su código C ++, en lugar de cualquier object Cocoa Touch en la cadena de respuesta. Por ejemplo, dentro de los touchesBegan:withEvent: una vista de touchesBegan:withEvent: selector, includeía una llamada a su onMouseDown(int, int, void*) . touchesMoved:withEvent: y touchesEnded:withEvent: tendrá una lógica similar.

Sin embargo, hay algunas dificultades. De acuerdo con la HIG, touchesCancelled:withEvent: siempre debe implementarse cuando la otra touches*:withEvent: selectores están implementados, y tendrás que include lógica para manejarlo.

El otro problema que puede encontrar es con UIGestureRecognizer subclasss UIGestureRecognizer . Mencioné antes que tienes que asegurarte de que tu código C ++ consume el toque. Sin embargo, si usa reconocedores de gestos, toda su cadena de respuestas puede verse desbaratada si TAMBIÉN está implementando los touches*:WithEvent: selectores. Hay algunos videos excelentes de WWDC que explican esto. En resumen, si tu reconocimiento de gestos consume el toque, nunca se enviará a tus methods de C ++. La solución simple sería simplemente no utilizar reconocedores de gestos, pero son, con mucho, la forma más fácil de manejar bien multitouch.

Lo que nos lleva a una posibilidad final (si desea utilizar reconocedores de gestos). En lugar de implementar únicamente los touches*:withEvent: selectores, puede configurar la acción de los reconocedores de gestos como un selector de Objective-C que simplemente envuelve una llamada a su código de C ++. Por ejemplo, una acción UITapGestureRecogniser podría ser un método llamado onTap que simplemente llama a onMouseDown(...) . Si decides seguir este path, mira definitivamente los videos WWDC ('11 y '12) donde se explica con más detalle el manejo táctil y la cadena de respuesta.

Sobre el tema de los libros que manejan Objective-C ++, Apple ha eliminado la página que solía explicar lo que se hace y lo que no se hace de ObjC ++ … Sin embargo, está disponible aquí, afortunadamente . La forma más fácil de manejar el cruce es implementar los elementos básicos de la capa de aplicación en Objective-C y reenviar todas las llamadas apropiadas a su motor C ++. Personalmente progtwigría el delegado de la aplicación en Pure Objective-C, pero una vez que esté dentro de su ViewController , ViewController libre.