[dasher: 15/21] iPhone: Landscape Tilting!



commit 58bbd2050956f1910bf4afe93e517b7274bdb7cb
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Tue Jul 12 17:10:07 2011 +0100

    iPhone: Landscape Tilting!
    
    (All) settings pages can be used in any orientation; tilt calibration preserves
    orientation whilst "setting" a vector/tilt; DasherCanvas while tilt in use (but
    reorients if settings displayed).
    
    TODO "Custom" tilting doesn't work very well atm. Abandon and just use vertical?

 Src/iPhone/Classes/CDasherInterfaceBridge.mm |    2 +-
 Src/iPhone/Classes/CalibrationController.h   |    3 +
 Src/iPhone/Classes/CalibrationController.mm  |   66 ++++++++++++++-----------
 Src/iPhone/Classes/DasherAppDelegate.mm      |   22 +++++----
 Src/iPhone/Classes/EAGLView.h                |    3 +-
 Src/iPhone/Classes/EAGLView.mm               |   28 ++++++------
 Src/iPhone/Classes/IPhoneInputs.h            |    2 +-
 Src/iPhone/Classes/IPhoneInputs.mm           |   56 +++++++++++++++-------
 Src/iPhone/Classes/ParametersController.mm   |    4 ++
 9 files changed, 111 insertions(+), 75 deletions(-)
---
diff --git a/Src/iPhone/Classes/CDasherInterfaceBridge.mm b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
index 49f7f06..960d4bb 100644
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.mm
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
@@ -125,7 +125,7 @@ void CDasherInterfaceBridge::Realize() {
   //don't call HandleEvent, would call superclass and reconstruct the NCManager!
   //TODO maybe better to make ChangeAlphabet virtual and override that?  
 
-  [[dasherApp glView] startAnimation];
+  [dasherApp glView].animating=YES;
 }
 
 void CDasherInterfaceBridge::SetupPaths() {
diff --git a/Src/iPhone/Classes/CalibrationController.h b/Src/iPhone/Classes/CalibrationController.h
index 54e137d..2e246bf 100644
--- a/Src/iPhone/Classes/CalibrationController.h
+++ b/Src/iPhone/Classes/CalibrationController.h
@@ -31,6 +31,9 @@ enum settableParam {
   //custom mode
   UIButton *custMin, *custMax, *custX;
 	
+  ///If tilt sensor active, prevent autorotation away from this orientation
+  UIInterfaceOrientation m_fixOrientation;
+  
   settableParam settingParam;
   UILabel *settingLabel; //if SETTING_CUST_X, is the label in the UIActionSheet.
   Vec3 setVec; //the vector of which settingLabel displays a text representation
diff --git a/Src/iPhone/Classes/CalibrationController.mm b/Src/iPhone/Classes/CalibrationController.mm
index 5c836a7..47bd8a3 100644
--- a/Src/iPhone/Classes/CalibrationController.mm
+++ b/Src/iPhone/Classes/CalibrationController.mm
@@ -125,6 +125,11 @@ void setVerticalTiltAxes(float minY, float maxY, float minX, float maxX, BOOL in
   return self;
 }
 
+-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
+  if ([UIAccelerometer sharedAccelerometer].delegate == self)
+    return toInterfaceOrientation == m_fixOrientation;
+  return toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
+}
 
 /*
  // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
@@ -254,37 +259,32 @@ void setVerticalTiltAxes(float minY, float maxY, float minX, float maxX, BOOL in
 - (void)set:(id)sender {
   NSString *title;
   oldDeleg = [UIAccelerometer sharedAccelerometer].delegate;
-  if (sender == setRange)
-  {
+  if (sender == setRange) {
     minX = 1.0; minY = 1.0; maxX = -1.0; maxY = -1.0;
     settingParam = SETTING_VERT;
-	title=@"Set Range";
-	  settingLabel = nil;
-  }
-  else
-  {
-	  if (sender == custX)
-	  {
-		  title=@"Set Minor Axis";
-		  settingParam = SETTING_CUST_X;
-	  }
-	  else
-	  {
-		  title=@"Set Endpoint";
-		  settingParam = (sender == custMin) ? SETTING_CUST_MIN : SETTING_CUST_MAX;
-	  }
-	  settingLabel = [[[UILabel alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
-	  [settingLabel setFont:[UIFont systemFontOfSize:16.0]];
+    title=@"Set Range";
+    settingLabel = nil;
+  } else {
+    if (sender == custX) {
+      title=@"Set Minor Axis";
+      settingParam = SETTING_CUST_X;
+    } else {
+      title=@"Set Endpoint";
+      settingParam = (sender == custMin) ? SETTING_CUST_MIN : SETTING_CUST_MAX;
+    }
+    settingLabel = [[[UILabel alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
+    [settingLabel setFont:[UIFont systemFontOfSize:16.0]];
   }
   UIActionSheet *act = [[[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Set" otherButtonTitles:nil] autorelease];
   if (settingLabel) {
-	UIViewController *viewCon = [[UIViewController alloc] autorelease];
-	viewCon.view = settingLabel;
-	[self presentModalViewController:viewCon animated:NO];
-	[act showInView:settingLabel];
+    UIViewController *viewCon = [[UIViewController alloc] autorelease];
+    viewCon.view = settingLabel;
+    [self presentModalViewController:viewCon animated:NO];
+    [act showInView:settingLabel];
   }
 //	[act addSubview:settingLabel];
   else [act showInView:self.view];
+  m_fixOrientation = self.interfaceOrientation;
   [UIAccelerometer sharedAccelerometer].delegate = self;
 }
 
@@ -337,22 +337,30 @@ void setVerticalTiltAxes(float minY, float maxY, float minX, float maxX, BOOL in
 }
 
 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
-	if (settingParam == SETTING_VERT)
-	{
-		float y = acceleration.y;
+  float x,y;
+  switch(m_fixOrientation) {
+    case UIInterfaceOrientationLandscapeLeft:
+      x = acceleration.y; y=-acceleration.x; break;
+    case UIInterfaceOrientationLandscapeRight:
+      x = -acceleration.y; y=acceleration.x; break;
+    default:
+      DASHER_ASSERT(false);
+    case UIInterfaceOrientationPortrait:
+      x=acceleration.x; y=acceleration.y; break;
+  }
+  if (settingParam == SETTING_VERT) {
 		minY = std::min(minY, y);
 		maxY = std::max(maxY, y);
 		vertMin.text = [NSString stringWithFormat:@"%1.3f",minY];
 		vertMax.text = [NSString stringWithFormat:@"%1.3f",maxY];
-		float x = acceleration.x;
 		minX = std::min(minX, x);
 		maxX = std::max(maxX, x);
 		vertX.text = [NSString stringWithFormat:@"%1.3f - %1.3f", minX, maxX];
 	}
 	else
 		settingLabel.text = [NSString stringWithFormat:@"(%1.3f,%1.3f,%1.3f)",
-							 setVec.x=acceleration.x,
-							 setVec.y=acceleration.y,
+							 setVec.x=x,
+							 setVec.y=y,
 							 setVec.z=acceleration.z];
 }
 
diff --git a/Src/iPhone/Classes/DasherAppDelegate.mm b/Src/iPhone/Classes/DasherAppDelegate.mm
index 416703e..31eae7a 100644
--- a/Src/iPhone/Classes/DasherAppDelegate.mm
+++ b/Src/iPhone/Classes/DasherAppDelegate.mm
@@ -32,11 +32,14 @@
 }
 @end
 
- interface UINavigationController (MultiOrient)
+
+//Most of the view controllers we use, are TableViewControllers. This makes them default
+// to rotating to any orientation other than upside-down.
+ interface UITableViewController (MultiOrient)
 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
 @end
 
- implementation UINavigationController (MultiOrient)
+ implementation UITableViewController (MultiOrient)
 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
   return toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
 }
@@ -96,9 +99,8 @@ using namespace Dasher;
 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
     return NO;
-  if (m_bAllowsRotation) return YES;
-  UIInterfaceOrientation current = self.interfaceOrientation;
-  return interfaceOrientation == current;
+  if (m_bAllowsRotation || !glView.animating) return YES;
+  return interfaceOrientation == self.interfaceOrientation;
 }
 
 -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
@@ -337,14 +339,14 @@ using namespace Dasher;
 }
 
 -(void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated {
-  [glView stopAnimation];
+  glView.animating=NO;
   [[[UIApplication sharedApplication] keyWindow] setRootViewController:modalViewController];
   [super presentModalViewController:modalViewController animated:animated];
 }
 
 - (void)settingsDone {
 	[self dismissModalViewControllerAnimated:YES];
-	[glView startAnimation];
+	glView.animating=YES;
 }
 
 - (void)outputCallback:(NSString *)s {
@@ -390,12 +392,12 @@ using namespace Dasher;
 }
 
 - (void)applicationWillResignActive:(UIApplication *)application {
-	[glView stopAnimation];//.animationInterval = 1.0 / 5.0;
+	glView.animating=NO;
 }
 
 
 - (void)applicationDidBecomeActive:(UIApplication *)application {
-  if (doneSetup) [glView startAnimation];//glView.animationInterval = 1.0 / 60.0;
+  if (doneSetup) glView.animating=YES;//glView.animationInterval = 1.0 / 60.0;
 }
 
 -(void)applicationDidEnterBackground:(UIApplication *)application {
@@ -403,7 +405,7 @@ using namespace Dasher;
 }
 
 -(void)applicationWillTerminate:(UIApplication *)application {
-  [glView stopAnimation];
+  glView.animating=NO;
   self.dasherInterface->WriteTrainFileFull();
 }
 
diff --git a/Src/iPhone/Classes/EAGLView.h b/Src/iPhone/Classes/EAGLView.h
index 68570b5..71f7f4a 100644
--- a/Src/iPhone/Classes/EAGLView.h
+++ b/Src/iPhone/Classes/EAGLView.h
@@ -67,8 +67,7 @@ Note that setting the view non-opaque will only work if the EAGL surface has an
 //OpenGL context (needed to do any OGL operation) is only current per-thread, so must call this
 // if doing anything on any thread other than the main thread.
 -(void)makeContextCurrent;
-- (void)startAnimation;
-- (void)stopAnimation;
 - (void)drawView;
 - (id)initWithFrame:(CGRect)frame Delegate:(DasherAppDelegate *)_dasherApp;
+ property BOOL animating;
 @end
diff --git a/Src/iPhone/Classes/EAGLView.mm b/Src/iPhone/Classes/EAGLView.mm
index 8c09bd9..ad116f7 100644
--- a/Src/iPhone/Classes/EAGLView.mm
+++ b/Src/iPhone/Classes/EAGLView.mm
@@ -77,6 +77,8 @@ bool operator==(CGPoint p,CGPoint q) {
 
 @implementation EAGLView
 
+ synthesize animating;
+
 -(CGPoint)lastTouchCoords {
   return fingerPosns.empty() ? CGPointMake(-1,-1) : fingerPosns.begin()->second;
 }
@@ -256,24 +258,22 @@ bool operator==(CGPoint p,CGPoint q) {
     viewRenderbuffer = 0;
 }
 
-- (void)startAnimation {
-  if (animating) return;
-  animating = YES;
-  if (doneLayout)
-    [self performSelector:@selector(drawView) withObject:nil afterDelay:animationInterval];
-  else
-    [self setNeedsDisplay];
-}
-
-- (void)stopAnimation {
-  //stop for now at least - shutdown, settings dialog, etc.
-  // (causes drawView not to enqueue another repaint)
-  animating = NO;
+-(void)setAnimating:(BOOL)bNewValue {
+  if (animating==bNewValue) return;
+  animating = bNewValue;
+  if (animating) {
+    if (doneLayout)
+      [self performSelector:@selector(drawView) withObject:nil afterDelay:animationInterval];
+    else
+      [self setNeedsDisplay];
+  }
+  //setting to false, e.g. for shutdown / settings dialog / etc.,
+  // causes drawView not to enqueue another repaint.
 }
 
 - (void)dealloc {
     
-    [self stopAnimation];
+  self.animating=NO;
 
   glDeleteFramebuffersOES(2, buffers);
   glDeleteTextures(2,textures);
diff --git a/Src/iPhone/Classes/IPhoneInputs.h b/Src/iPhone/Classes/IPhoneInputs.h
index 254b766..b2c8a69 100644
--- a/Src/iPhone/Classes/IPhoneInputs.h
+++ b/Src/iPhone/Classes/IPhoneInputs.h
@@ -58,7 +58,7 @@ private:
 	Vec3 main, slow;
 	float offset, slow_off;
 	SBTree *xTilts, *yTilts;
-	std::deque<int> *xHist, *yHist;
+	std::deque<int> xHist, yHist;
 	id<UIAccelerometerDelegate> deleg;
 };
 
diff --git a/Src/iPhone/Classes/IPhoneInputs.mm b/Src/iPhone/Classes/IPhoneInputs.mm
index c03a910..48ef83d 100644
--- a/Src/iPhone/Classes/IPhoneInputs.mm
+++ b/Src/iPhone/Classes/IPhoneInputs.mm
@@ -62,20 +62,42 @@ IPhonePrefsObserver::~IPhonePrefsObserver() {
 
 @interface Accel : NSObject<UIAccelerometerDelegate> {
   CIPhoneTiltInput *tilt;
+  UIInterfaceOrientation m_orient;
 }
 -(id)initWithInput:(CIPhoneTiltInput *)_tilt;
+-(void)orientationDidChange:(NSNotification *)note;
 @end
 
 @implementation Accel
 -(id)initWithInput:(CIPhoneTiltInput *)_tilt {
   if (self = [super init]) {
     tilt=_tilt;
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:[UIApplication sharedApplication]];
+    [self orientationDidChange:nil];
   }
   return self;
 }
--(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
-{
-	tilt->NotifyTilt(acceleration.x, acceleration.y, acceleration.z);
+-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
+  float x,y;
+  switch(m_orient) {
+    case UIInterfaceOrientationLandscapeLeft:
+      x = acceleration.y; y=-acceleration.x; break;
+    case UIInterfaceOrientationLandscapeRight:
+      x = -acceleration.y; y=acceleration.x; break;
+    default:
+      DASHER_ASSERT(false);
+    case UIInterfaceOrientationPortrait:
+      x=acceleration.x; y=acceleration.y; break;
+  }
+  tilt->NotifyTilt(x, y, acceleration.z);
+}
+
+-(void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:[UIApplication sharedApplication]];
+  [super dealloc];
+}
+-(void)orientationDidChange:(NSNotification *)note {
+  m_orient = [UIApplication sharedApplication].statusBarOrientation;
 }
 @end
 
@@ -97,27 +119,21 @@ void CIPhoneTiltInput::NotifyTilt(float fx, float fy, float fz) {
 	const screenint iX(x * (double)maxX);
 		
 	//apply median filter
-	if (xTilts)
-	{
+	if (xTilts) {
 		xTilts->Add(iX);
 		yTilts->Add(iY);
-		if (xTilts->GetCount() > 20)
-		{
-			xTilts = xTilts->Delete(xHist->front());
-			xHist->pop_front();
-			yTilts = yTilts->Delete(yHist->front());
-			yHist->pop_front();
+		if (xTilts->GetCount() > 20) {
+			xTilts = xTilts->Delete(xHist.front());
+			xHist.pop_front();
+			yTilts = yTilts->Delete(yHist.front());
+			yHist.pop_front();
 		}
-	}
-	else
-	{
+	} else {
 		xTilts = new SBTree(iX);
 		yTilts = new SBTree(iY);
-		xHist = new deque<int>();
-		yHist = new deque<int>();
 	}
-	xHist->push_back(iX);
-	yHist->push_back(iY);
+	xHist.push_back(iX);
+	yHist.push_back(iY);
 	const int median(xTilts->GetCount()/2);
 	m_iX = xTilts->GetOffset(median);
 	m_iY = yTilts->GetOffset(median);
@@ -129,9 +145,13 @@ void CIPhoneTiltInput::Activate() {
   theAccelerometer.updateInterval = 0.01; //in secs
   theAccelerometer.delegate = deleg;
 }
+
 void CIPhoneTiltInput::Deactivate() {
   [DasherAppDelegate theApp].allowsRotation=YES;
   [UIAccelerometer sharedAccelerometer].delegate = nil;
+  delete xTilts; xTilts=NULL;
+  delete yTilts; yTilts=NULL;
+  xHist.clear(); yHist.clear();
 }
 
 bool CIPhoneTiltInput::GetScreenCoords(screenint &iX, screenint &iY, CDasherView *pView) {
diff --git a/Src/iPhone/Classes/ParametersController.mm b/Src/iPhone/Classes/ParametersController.mm
index c221245..ec973c6 100644
--- a/Src/iPhone/Classes/ParametersController.mm
+++ b/Src/iPhone/Classes/ParametersController.mm
@@ -31,6 +31,10 @@ using Dasher::Settings::GetParameterName;
   return self;
 }
 
+-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
+  return toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
+}
+
 -(void)setTarget:(id)_target Selector:(SEL)_selector {
   UIBarButtonItem *item = (UIBarButtonItem *)self.navigationItem.leftBarButtonItem;
   item.target = _target;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]