diff --git a/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.pbxproj b/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.pbxproj index bbc33f22..f76c359c 100644 --- a/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.pbxproj +++ b/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 3076CE0E1809B5C500527E6C /* RESideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 3076CE0A1809B5C500527E6C /* RESideMenu.m */; }; 3076CE0F1809B5C500527E6C /* UIViewController+RESideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 3076CE0C1809B5C500527E6C /* UIViewController+RESideMenu.m */; }; 30DF13B218DE1B0C0018463C /* DEMORightMenuViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DF13B118DE1B0C0018463C /* DEMORightMenuViewController.m */; }; + F8C68E8219D2A60300AB185E /* MCBTransform3DHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = F8C68E8119D2A60300AB185E /* MCBTransform3DHandler.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -69,6 +70,8 @@ 3076CE0C1809B5C500527E6C /* UIViewController+RESideMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+RESideMenu.m"; sourceTree = ""; }; 30DF13B018DE1B0C0018463C /* DEMORightMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DEMORightMenuViewController.h; sourceTree = ""; }; 30DF13B118DE1B0C0018463C /* DEMORightMenuViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DEMORightMenuViewController.m; sourceTree = ""; }; + F8C68E8019D2A60300AB185E /* MCBTransform3DHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCBTransform3DHandler.h; sourceTree = ""; }; + F8C68E8119D2A60300AB185E /* MCBTransform3DHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCBTransform3DHandler.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -171,6 +174,8 @@ children = ( 3076CE071809B5C400527E6C /* RECommonFunctions.h */, 3076CE081809B5C400527E6C /* RECommonFunctions.m */, + F8C68E8019D2A60300AB185E /* MCBTransform3DHandler.h */, + F8C68E8119D2A60300AB185E /* MCBTransform3DHandler.m */, 3076CE091809B5C400527E6C /* RESideMenu.h */, 3076CE0A1809B5C500527E6C /* RESideMenu.m */, 3076CE0B1809B5C500527E6C /* UIViewController+RESideMenu.h */, @@ -228,6 +233,9 @@ LastUpgradeCheck = 0510; ORGANIZATIONNAME = "Roman Efimov"; TargetAttributes = { + 3076CDBD1809B47200527E6C = { + DevelopmentTeam = 8DEWPT2VGB; + }; 3076CDDE1809B47200527E6C = { TestTargetID = 3076CDBD1809B47200527E6C; }; @@ -277,6 +285,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F8C68E8219D2A60300AB185E /* MCBTransform3DHandler.m in Sources */, 3076CE021809B59E00527E6C /* DEMOLeftMenuViewController.m in Sources */, 3076CE011809B59E00527E6C /* DEMOFirstViewController.m in Sources */, 3076CDCE1809B47200527E6C /* main.m in Sources */, @@ -402,11 +411,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "RESideMenuStoryboardsExample/RESideMenuStoryboardsExample-Prefix.pch"; INFOPLIST_FILE = "RESideMenuStoryboardsExample/RESideMenuStoryboardsExample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; }; @@ -417,11 +429,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "RESideMenuStoryboardsExample/RESideMenuStoryboardsExample-Prefix.pch"; INFOPLIST_FILE = "RESideMenuStoryboardsExample/RESideMenuStoryboardsExample-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; }; diff --git a/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.xcworkspace/xcshareddata/RESideMenuStoryboardsExample.xccheckout b/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.xcworkspace/xcshareddata/RESideMenuStoryboardsExample.xccheckout index c94eb4b4..7109e726 100644 --- a/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.xcworkspace/xcshareddata/RESideMenuStoryboardsExample.xccheckout +++ b/Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.xcworkspace/xcshareddata/RESideMenuStoryboardsExample.xccheckout @@ -5,34 +5,34 @@ IDESourceControlProjectFavoriteDictionaryKey IDESourceControlProjectIdentifier - 3879733F-3A95-4277-B781-69031D14BC32 + 89C8A5DD-AD46-44A9-A9D9-45125238F62B IDESourceControlProjectName RESideMenuStoryboardsExample IDESourceControlProjectOriginsDictionary - D8E9CD00-2368-4ABD-BD15-AB69D787B293 - ssh://github.com/romaonthego/RESideMenu.git + 4D9AE519C7D7E765CA7498EFD8B3BB24ACB11215 + https://github.com/r00li/RESideMenu.git IDESourceControlProjectPath Examples/Storyboards/RESideMenuStoryboardsExample.xcodeproj/project.xcworkspace IDESourceControlProjectRelativeInstallPathDictionary - D8E9CD00-2368-4ABD-BD15-AB69D787B293 + 4D9AE519C7D7E765CA7498EFD8B3BB24ACB11215 ../../../.. IDESourceControlProjectURL - ssh://github.com/romaonthego/RESideMenu.git + https://github.com/r00li/RESideMenu.git IDESourceControlProjectVersion - 110 + 111 IDESourceControlProjectWCCIdentifier - D8E9CD00-2368-4ABD-BD15-AB69D787B293 + 4D9AE519C7D7E765CA7498EFD8B3BB24ACB11215 IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - D8E9CD00-2368-4ABD-BD15-AB69D787B293 + 4D9AE519C7D7E765CA7498EFD8B3BB24ACB11215 IDESourceControlWCCName RESideMenu diff --git a/Examples/Storyboards/RESideMenuStoryboardsExample/DEMORootViewController.m b/Examples/Storyboards/RESideMenuStoryboardsExample/DEMORootViewController.m index 4086ab21..9b2b0d02 100644 --- a/Examples/Storyboards/RESideMenuStoryboardsExample/DEMORootViewController.m +++ b/Examples/Storyboards/RESideMenuStoryboardsExample/DEMORootViewController.m @@ -6,6 +6,7 @@ // Copyright (c) 2013 Roman Efimov. All rights reserved. // +#import "MCBTransform3DHandler.h" #import "DEMORootViewController.h" #import "DEMOLeftMenuViewController.h" @@ -24,6 +25,41 @@ - (void)awakeFromNib self.contentViewShadowRadius = 12; self.contentViewShadowEnabled = YES; + self.contentViewScaleValue = 0.6; + self.contentViewInPortraitOffsetCenterX = -220; + + //Enable 3D transformations + self.use3DTransform = YES; + + + // + // 3D transformation + // right menu + // + CATransform3D rotationAndPerspectiveTransformRight = CATransform3DIdentity; + rotationAndPerspectiveTransformRight.m34 = 1.0 / -500; + rotationAndPerspectiveTransformRight = CATransform3DRotate(rotationAndPerspectiveTransformRight, 25 * M_PI / 180.0f, 0.0f, 1.0f, 0.0f); + rotationAndPerspectiveTransformRight = CATransform3DTranslate(rotationAndPerspectiveTransformRight, -200, 0, 50); + rotationAndPerspectiveTransformRight = CATransform3DScale(rotationAndPerspectiveTransformRight, self.contentViewScaleValue, self.contentViewScaleValue, 1); + self.rightMenu3DTransform = rotationAndPerspectiveTransformRight; + + + // + // 3D transformation + // left menu + // + /* + CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; + rotationAndPerspectiveTransform.m34 = 1.0 / -500; + rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, -25 * M_PI / 180.0f, 0.0f, 1.0f, 0.0f); + rotationAndPerspectiveTransform = CATransform3DTranslate(rotationAndPerspectiveTransform, 170, 0, 0); + rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, self.contentViewScaleValue, self.contentViewScaleValue, 1); + self.leftMenu3DTransform = rotationAndPerspectiveTransform; + */ + + MCBTransform3DPerspectiveRotation *transformHandler = [[MCBTransform3DPerspectiveRotation alloc] init]; + self.leftMenu3DTransform = [transformHandler interpolatedTransformWithScale:1.0f]; + self.contentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"contentViewController"]; self.leftMenuViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"leftMenuViewController"]; self.rightMenuViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"rightMenuViewController"]; diff --git a/RESideMenu/MCBTransform3DHandler.h b/RESideMenu/MCBTransform3DHandler.h new file mode 100644 index 00000000..17cf0cb0 --- /dev/null +++ b/RESideMenu/MCBTransform3DHandler.h @@ -0,0 +1,20 @@ +// +// MCBTransform3DHandler.h +// Minicabster +// +// Created by Matic Oblak on 9/23/14. +// Copyright (c) 2014 D·Labs. All rights reserved. +// + +#import + +@interface MCBTransform3DHandler : NSObject +- (CATransform3D)interpolatedTransformWithScale:(CGFloat)scale; +@end + +@interface MCBTransform3DPerspectiveRotation : MCBTransform3DHandler +@property (nonatomic) CGFloat perspectiveStrength; // default -500 +@property (nonatomic) CGFloat rotationY; // default -M_PI/6 +@property (nonatomic) CGFloat translationX; // default 170 +@property (nonatomic) CGFloat scaleXY; // default 0.62f +@end diff --git a/RESideMenu/MCBTransform3DHandler.m b/RESideMenu/MCBTransform3DHandler.m new file mode 100644 index 00000000..c56e5c98 --- /dev/null +++ b/RESideMenu/MCBTransform3DHandler.m @@ -0,0 +1,111 @@ +// +// MCBTransform3DHandler.m +// Minicabster +// +// Created by Matic Oblak on 9/23/14. +// Copyright (c) 2014 D·Labs. All rights reserved. +// + +#import "MCBTransform3DHandler.h" + +@implementation MCBTransform3DHandler + ++ (CATransform3D)interpolateMatrices:(CATransform3D)source to:(CATransform3D)target scale:(CGFloat)scale +{ + CATransform3D result; + + result.m11 = [self interpolateLinear:source.m11 to:target.m11 scale:scale]; + result.m12 = [self interpolateLinear:source.m12 to:target.m12 scale:scale]; + result.m13 = [self interpolateLinear:source.m13 to:target.m13 scale:scale]; + result.m14 = [self interpolateLinear:source.m14 to:target.m14 scale:scale]; + + result.m21 = [self interpolateLinear:source.m21 to:target.m21 scale:scale]; + result.m22 = [self interpolateLinear:source.m22 to:target.m22 scale:scale]; + result.m23 = [self interpolateLinear:source.m23 to:target.m23 scale:scale]; + result.m24 = [self interpolateLinear:source.m24 to:target.m24 scale:scale]; + + result.m31 = [self interpolateLinear:source.m31 to:target.m31 scale:scale]; + result.m32 = [self interpolateLinear:source.m32 to:target.m32 scale:scale]; + result.m33 = [self interpolateLinear:source.m33 to:target.m33 scale:scale]; + result.m34 = [self interpolateLinear:source.m34 to:target.m34 scale:scale]; + + result.m41 = [self interpolateLinear:source.m41 to:target.m41 scale:scale]; + result.m42 = [self interpolateLinear:source.m42 to:target.m42 scale:scale]; + result.m43 = [self interpolateLinear:source.m43 to:target.m43 scale:scale]; + result.m44 = [self interpolateLinear:source.m44 to:target.m44 scale:scale]; + + return result; +} + +- (CATransform3D)interpolatedTransformWithScale:(CGFloat)scale +{ + return CATransform3DIdentity; +} + ++ (CGFloat)interpolateLinear:(CGFloat)a to:(CGFloat)b scale:(CGFloat)scale +{ + return a + (b-a)*scale; +} + + +@end + +@implementation MCBTransform3DPerspectiveRotation + +- (instancetype)init +{ + if((self = [super init])) + { + // set defaults + self.perspectiveStrength = -500.0f; + self.rotationY = (CGFloat)(-M_PI_2/3.0); + self.translationX = 170.0f; + self.scaleXY = .62f; + } + return self; +} + +- (CATransform3D)interpolatedTransformWithScale:(CGFloat)scale +{ + CGFloat interpolatedPerspective = self.perspectiveStrength; + CGFloat interpolatedRotationY = [self interpolate:.0f to:self.rotationY scale:1.0f]; + CGFloat interpolatedTranslation = [self interpolate:.0f to:self.translationX scale:1.0f]; + CGFloat interpolatedScaleXY = [self interpolate:1.0f to:self.scaleXY scale:1.0f]; + + //NSLog(@"Scale: %g, irotation: %g", scale, interpolatedRotationY); + + CATransform3D interpolatedTransformation = CATransform3DIdentity; + interpolatedTransformation.m34 = 1.0f / interpolatedPerspective; + interpolatedTransformation = CATransform3DRotate(interpolatedTransformation, interpolatedRotationY, 0.0f, 1.0f, 0.0f); + interpolatedTransformation = CATransform3DTranslate(interpolatedTransformation, interpolatedTranslation, 0, 0); + interpolatedTransformation = CATransform3DScale(interpolatedTransformation, interpolatedScaleXY, interpolatedScaleXY, 1); + + return [MCBTransform3DPerspectiveRotation interpolateMatrices:CATransform3DIdentity to:interpolatedTransformation scale:scale]; +} + + +//- (CATransform3D)interpolatedTransformWithScale:(CGFloat)scale +//{ +// CGFloat interpolatedPerspective = self.perspectiveStrength; +// CGFloat interpolatedRotationY = [self interpolate:.0f to:self.rotationY scale:scale]; +// CGFloat interpolatedTranslation = [self interpolate:.0f to:self.translationX scale:scale]; +// CGFloat interpolatedScaleXY = [self interpolate:1.0f to:self.scaleXY scale:scale]; +// +// NSLog(@"Scale: %g, irotation: %g", scale, interpolatedRotationY); +// +// CATransform3D interpolatedTransformation = CATransform3DIdentity; +// interpolatedTransformation.m34 = 1.0f / interpolatedPerspective; +// interpolatedTransformation = CATransform3DRotate(interpolatedTransformation, interpolatedRotationY, 0.0f, 1.0f, 0.0f); +// interpolatedTransformation = CATransform3DTranslate(interpolatedTransformation, interpolatedTranslation, 0, 0); +// interpolatedTransformation = CATransform3DScale(interpolatedTransformation, interpolatedScaleXY, interpolatedScaleXY, 1); +// +// return interpolatedTransformation; +//} + +- (CGFloat)interpolate:(CGFloat)a to:(CGFloat)b scale:(CGFloat)scale +{ + return a + (b-a)*scale; +} + + +@end diff --git a/RESideMenu/RESideMenu.h b/RESideMenu/RESideMenu.h index a8907a6c..53c0712f 100644 --- a/RESideMenu/RESideMenu.h +++ b/RESideMenu/RESideMenu.h @@ -63,6 +63,14 @@ @property (assign, readwrite, nonatomic) UIStatusBarStyle menuPreferredStatusBarStyle; @property (assign, readwrite, nonatomic) BOOL menuPrefersStatusBarHidden; +// +// 3D transformations +// +@property (assign, readwrite, nonatomic) BOOL use3DTransform; +@property (assign, readwrite, nonatomic) CATransform3D leftMenu3DTransform; +@property (assign, readwrite, nonatomic) CATransform3D rightMenu3DTransform; + + - (id)initWithContentViewController:(UIViewController *)contentViewController leftMenuViewController:(UIViewController *)leftMenuViewController rightMenuViewController:(UIViewController *)rightMenuViewController; diff --git a/RESideMenu/RESideMenu.m b/RESideMenu/RESideMenu.m index e86cb520..b7ee4d9b 100644 --- a/RESideMenu/RESideMenu.m +++ b/RESideMenu/RESideMenu.m @@ -26,6 +26,7 @@ #import "RESideMenu.h" #import "UIViewController+RESideMenu.h" #import "RECommonFunctions.h" +#import "MCBTransform3DHandler.h" @interface RESideMenu () @@ -39,6 +40,8 @@ @interface RESideMenu () @property (strong, readwrite, nonatomic) UIView *contentViewContainer; @property (assign, readwrite, nonatomic) BOOL didNotifyDelegate; +@property (nonatomic, strong) MCBTransform3DPerspectiveRotation *perspectiveHandler; + @end @implementation RESideMenu @@ -66,12 +69,14 @@ - (id)initWithCoder:(NSCoder *)decoder - (void)__commonInit { + self.perspectiveHandler = [[MCBTransform3DPerspectiveRotation alloc] init]; + _menuViewContainer = [[UIView alloc] init]; _contentViewContainer = [[UIView alloc] init]; _animationDuration = 0.35f; _interactivePopGestureRecognizerEnabled = YES; - + _menuViewControllerTransformation = CGAffineTransformMakeScale(1.5f, 1.5f); _scaleContentView = YES; @@ -152,7 +157,7 @@ - (void)setContentViewController:(UIViewController *)contentViewController anima [self __hideViewController:self.contentViewController]; [contentViewController didMoveToParentViewController:self]; _contentViewController = contentViewController; - + [self __statusBarNeedsAppearanceUpdate]; [self __updateContentViewShadow]; @@ -175,6 +180,7 @@ - (void)viewDidLoad imageView.image = self.backgroundImage; imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + imageView.layer.transform = CATransform3DMakeTranslation(0, 0, -10); // move the layer slightly back so we don't get any overlap when animating views - fixes iphone 6 animation bug imageView; }); self.contentButton = ({ @@ -263,21 +269,37 @@ - (void)__showLeftMenuViewController [self.view.window endEditing:YES]; [self __addContentButton]; [self __updateContentViewShadow]; - [self __resetContentViewScale]; + if (!self.use3DTransform) + { + [self __resetContentViewScale]; + } [UIView animateWithDuration:self.animationDuration animations:^{ - if (self.scaleContentView) { - self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); - } else { - self.contentViewContainer.transform = CGAffineTransformIdentity; + if (!self.use3DTransform) + { + if (self.scaleContentView) + { + self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); + } + else + { + self.contentViewContainer.transform = CGAffineTransformIdentity; + } + + self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetHeight(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); + } + else + { + self.contentViewContainer.layer.transform = self.leftMenu3DTransform; } - self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? self.contentViewInLandscapeOffsetCenterX + CGRectGetHeight(self.view.frame) : self.contentViewInPortraitOffsetCenterX + CGRectGetWidth(self.view.frame)), self.contentViewContainer.center.y); + + self.menuViewContainer.alpha = !self.fadeMenuView ?: 1.0f; self.menuViewContainer.transform = CGAffineTransformIdentity; if (self.scaleBackgroundImageView) self.backgroundImageView.transform = CGAffineTransformIdentity; - + } completion:^(BOOL finished) { [self __addContentViewControllerMotionEffects]; @@ -306,11 +328,22 @@ - (void)__showRightMenuViewController [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; [UIView animateWithDuration:self.animationDuration animations:^{ - if (self.scaleContentView) { - self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); - } else { - self.contentViewContainer.transform = CGAffineTransformIdentity; + if (!self.use3DTransform) + { + if (self.scaleContentView) + { + self.contentViewContainer.transform = CGAffineTransformMakeScale(self.contentViewScaleValue, self.contentViewScaleValue); + } + else + { + self.contentViewContainer.transform = CGAffineTransformIdentity; + } } + else + { + self.contentViewContainer.layer.transform = self.rightMenu3DTransform; + } + self.contentViewContainer.center = CGPointMake((UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? -self.contentViewInLandscapeOffsetCenterX : -self.contentViewInPortraitOffsetCenterX), self.contentViewContainer.center.y); self.menuViewContainer.alpha = !self.fadeMenuView ?: 1.0f; @@ -368,10 +401,10 @@ - (void)__hideMenuViewControllerAnimated:(BOOL)animated } if (strongSelf.parallaxEnabled) { IF_IOS7_OR_GREATER( - for (UIMotionEffect *effect in strongSelf.contentViewContainer.motionEffects) { - [strongSelf.contentViewContainer removeMotionEffect:effect]; - } - ); + for (UIMotionEffect *effect in strongSelf.contentViewContainer.motionEffects) { + [strongSelf.contentViewContainer removeMotionEffect:effect]; + } + ); } }; void (^completionBlock)(void) = ^{ @@ -403,7 +436,7 @@ - (void)__addContentButton { if (self.contentButton.superview) return; - + self.contentButton.autoresizingMask = UIViewAutoresizingNone; self.contentButton.frame = self.contentViewContainer.bounds; self.contentButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; @@ -449,20 +482,20 @@ - (void)__addMenuViewControllerMotionEffects { if (self.parallaxEnabled) { IF_IOS7_OR_GREATER( - for (UIMotionEffect *effect in self.menuViewContainer.motionEffects) { - [self.menuViewContainer removeMotionEffect:effect]; - } - UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - interpolationHorizontal.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); - interpolationHorizontal.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); - - UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - interpolationVertical.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); - interpolationVertical.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); - - [self.menuViewContainer addMotionEffect:interpolationHorizontal]; - [self.menuViewContainer addMotionEffect:interpolationVertical]; - ); + for (UIMotionEffect *effect in self.menuViewContainer.motionEffects) { + [self.menuViewContainer removeMotionEffect:effect]; + } + UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + interpolationHorizontal.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); + interpolationHorizontal.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); + + UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc]initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + interpolationVertical.minimumRelativeValue = @(self.parallaxMenuMinimumRelativeValue); + interpolationVertical.maximumRelativeValue = @(self.parallaxMenuMaximumRelativeValue); + + [self.menuViewContainer addMotionEffect:interpolationHorizontal]; + [self.menuViewContainer addMotionEffect:interpolationVertical]; + ); } } @@ -470,22 +503,22 @@ - (void)__addContentViewControllerMotionEffects { if (self.parallaxEnabled) { IF_IOS7_OR_GREATER( - for (UIMotionEffect *effect in self.contentViewContainer.motionEffects) { - [self.contentViewContainer removeMotionEffect:effect]; - } - [UIView animateWithDuration:0.2 animations:^{ - UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - interpolationHorizontal.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); - interpolationHorizontal.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); - - UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - interpolationVertical.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); - interpolationVertical.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); - - [self.contentViewContainer addMotionEffect:interpolationHorizontal]; - [self.contentViewContainer addMotionEffect:interpolationVertical]; - }]; - ); + for (UIMotionEffect *effect in self.contentViewContainer.motionEffects) { + [self.contentViewContainer removeMotionEffect:effect]; + } + [UIView animateWithDuration:0.2 animations:^{ + UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + interpolationHorizontal.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); + interpolationHorizontal.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); + + UIInterpolatingMotionEffect *interpolationVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + interpolationVertical.minimumRelativeValue = @(self.parallaxContentMinimumRelativeValue); + interpolationVertical.maximumRelativeValue = @(self.parallaxContentMaximumRelativeValue); + + [self.contentViewContainer addMotionEffect:interpolationHorizontal]; + [self.contentViewContainer addMotionEffect:interpolationVertical]; + }]; + ); } } @@ -495,14 +528,14 @@ - (void)__addContentViewControllerMotionEffects - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { IF_IOS7_OR_GREATER( - if (self.interactivePopGestureRecognizerEnabled && [self.contentViewController isKindOfClass:[UINavigationController class]]) { - UINavigationController *navigationController = (UINavigationController *)self.contentViewController; - if (navigationController.viewControllers.count > 1 && navigationController.interactivePopGestureRecognizer.enabled) { - return NO; - } - } - ); - + if (self.interactivePopGestureRecognizerEnabled && [self.contentViewController isKindOfClass:[UINavigationController class]]) { + UINavigationController *navigationController = (UINavigationController *)self.contentViewController; + if (navigationController.viewControllers.count > 1 && navigationController.interactivePopGestureRecognizer.enabled) { + return NO; + } + } + ); + if (self.panFromEdge && [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && !self.visible) { CGPoint point = [touch locationInView:gestureRecognizer.view]; if (point.x < 20.0 || point.x > self.view.frame.size.width - 20.0) { @@ -532,8 +565,16 @@ - (void)__panGestureRecognized:(UIPanGestureRecognizer *)recognizer if (recognizer.state == UIGestureRecognizerStateBegan) { [self __updateContentViewShadow]; - self.originalPoint = CGPointMake(self.contentViewContainer.center.x - CGRectGetWidth(self.contentViewContainer.bounds) / 2.0, + if (self.use3DTransform) + { + self.originalPoint = point; + } + else + { + self.originalPoint = CGPointMake(self.contentViewContainer.center.x - CGRectGetWidth(self.contentViewContainer.bounds) / 2.0, self.contentViewContainer.center.y - CGRectGetHeight(self.contentViewContainer.bounds) / 2.0); + } + self.menuViewContainer.transform = CGAffineTransformIdentity; if (self.scaleBackgroundImageView) { self.backgroundImageView.transform = CGAffineTransformIdentity; @@ -547,18 +588,36 @@ - (void)__panGestureRecognized:(UIPanGestureRecognizer *)recognizer if (recognizer.state == UIGestureRecognizerStateChanged) { CGFloat delta = 0; + CGFloat contentViewDelta = 0; + if (self.visible) { - delta = self.originalPoint.x != 0 ? (point.x + self.originalPoint.x) / self.originalPoint.x : 0; + if (self.use3DTransform) + { + contentViewDelta = 1.0f - ((MAX(self.originalPoint.x-point.x, 0)/self.view.frame.size.width)*2); + } + //delta = self.originalPoint.x != 0 ? (point.x + self.originalPoint.x) / self.originalPoint.x : 0; + delta = point.x / self.view.frame.size.width; + } else { + if (self.use3DTransform) + { + contentViewDelta = - ((MIN(self.originalPoint.x-point.x, 1)/self.view.frame.size.width)*2); + contentViewDelta = MIN(contentViewDelta, 1); + } delta = point.x / self.view.frame.size.width; } + + // delta = MIN(fabs(delta), 1.6); - + contentViewDelta = MAX(contentViewDelta, 0); + delta = contentViewDelta; + + //NSLog(@"delta: %f", delta); CGFloat contentViewScale = self.scaleContentView ? 1 - ((1 - self.contentViewScaleValue) * delta) : 1; CGFloat backgroundViewScale = 1.7f - (0.7f * delta); CGFloat menuViewScale = 1.5f - (0.5f * delta); - + if (!self.bouncesHorizontally) { contentViewScale = MAX(contentViewScale, self.contentViewScaleValue); backgroundViewScale = MAX(backgroundViewScale, 1.0); @@ -581,10 +640,10 @@ - (void)__panGestureRecognized:(UIPanGestureRecognizer *)recognizer } } - if (!self.bouncesHorizontally && self.visible) { - if (self.contentViewContainer.frame.origin.x > self.contentViewContainer.frame.size.width / 2.0) - point.x = MIN(0.0, point.x); - + if (!self.bouncesHorizontally && self.visible) { + if (self.contentViewContainer.frame.origin.x > self.contentViewContainer.frame.size.width / 2.0) + point.x = MIN(0.0, point.x); + if (self.contentViewContainer.frame.origin.x < -(self.contentViewContainer.frame.size.width / 2.0)) point.x = MAX(0.0, point.x); } @@ -613,12 +672,26 @@ - (void)__panGestureRecognized:(UIPanGestureRecognizer *)recognizer } if (contentViewScale > 1) { - CGFloat oppositeScale = (1 - (contentViewScale - 1)); - self.contentViewContainer.transform = CGAffineTransformMakeScale(oppositeScale, oppositeScale); - self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); + CGFloat oppositeScale = (1 - (contentViewScale/self.contentViewScaleValue - 1)); + if (self.use3DTransform) + { + self.contentViewContainer.layer.transform = [self.perspectiveHandler interpolatedTransformWithScale:oppositeScale]; + } + else + { + self.contentViewContainer.transform = CGAffineTransformMakeScale(oppositeScale, oppositeScale); + self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); + } } else { - self.contentViewContainer.transform = CGAffineTransformMakeScale(contentViewScale, contentViewScale); - self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); + if (self.use3DTransform) + { + self.contentViewContainer.layer.transform = [self.perspectiveHandler interpolatedTransformWithScale:contentViewDelta]; + } + else + { + self.contentViewContainer.transform = CGAffineTransformMakeScale(contentViewScale, contentViewScale); + self.contentViewContainer.transform = CGAffineTransformTranslate(self.contentViewContainer.transform, point.x, 0); + } } self.leftMenuViewController.view.hidden = self.contentViewContainer.frame.origin.x < 0; @@ -639,11 +712,19 @@ - (void)__panGestureRecognized:(UIPanGestureRecognizer *)recognizer [self __statusBarNeedsAppearanceUpdate]; } - if (recognizer.state == UIGestureRecognizerStateEnded) { + if (recognizer.state == UIGestureRecognizerStateEnded) { self.didNotifyDelegate = NO; + + if (self.panMinimumOpenThreshold > 0 && self.contentViewContainer.frame.origin.x == 0 && self.use3DTransform && [recognizer velocityInView:self.view].x > 0 && self.leftMenuViewController) + { + // + // Fixes the issue when the menu doesn't open with swipe gesture when using 3Dtransform - ugly hack + // + [self __showLeftMenuViewController]; + } if (self.panMinimumOpenThreshold > 0 && ( - (self.contentViewContainer.frame.origin.x < 0 && self.contentViewContainer.frame.origin.x > -((NSInteger)self.panMinimumOpenThreshold)) || - (self.contentViewContainer.frame.origin.x > 0 && self.contentViewContainer.frame.origin.x < self.panMinimumOpenThreshold)) + (self.contentViewContainer.frame.origin.x < 0 && self.contentViewContainer.frame.origin.x > -((NSInteger)self.panMinimumOpenThreshold)) || + (self.contentViewContainer.frame.origin.x > 0 && self.contentViewContainer.frame.origin.x < self.panMinimumOpenThreshold)) ) { [self hideMenuViewController]; } @@ -711,7 +792,7 @@ - (void)setLeftMenuViewController:(UIViewController *)leftMenuViewController } [self __hideViewController:_leftMenuViewController]; _leftMenuViewController = leftMenuViewController; - + [self addChildViewController:self.leftMenuViewController]; self.leftMenuViewController.view.frame = self.view.bounds; self.leftMenuViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; @@ -782,13 +863,13 @@ - (UIStatusBarStyle)preferredStatusBarStyle { UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault; IF_IOS7_OR_GREATER( - statusBarStyle = self.visible ? self.menuPreferredStatusBarStyle : self.contentViewController.preferredStatusBarStyle; - if (self.contentViewContainer.frame.origin.y > 10) { - statusBarStyle = self.menuPreferredStatusBarStyle; - } else { - statusBarStyle = self.contentViewController.preferredStatusBarStyle; - } - ); + statusBarStyle = self.visible ? self.menuPreferredStatusBarStyle : self.contentViewController.preferredStatusBarStyle; + if (self.contentViewContainer.frame.origin.y > 10) { + statusBarStyle = self.menuPreferredStatusBarStyle; + } else { + statusBarStyle = self.contentViewController.preferredStatusBarStyle; + } + ); return statusBarStyle; } @@ -796,13 +877,13 @@ - (BOOL)prefersStatusBarHidden { BOOL statusBarHidden = NO; IF_IOS7_OR_GREATER( - statusBarHidden = self.visible ? self.menuPrefersStatusBarHidden : self.contentViewController.prefersStatusBarHidden; - if (self.contentViewContainer.frame.origin.y > 10) { - statusBarHidden = self.menuPrefersStatusBarHidden; - } else { - statusBarHidden = self.contentViewController.prefersStatusBarHidden; - } - ); + statusBarHidden = self.visible ? self.menuPrefersStatusBarHidden : self.contentViewController.prefersStatusBarHidden; + if (self.contentViewContainer.frame.origin.y > 10) { + statusBarHidden = self.menuPrefersStatusBarHidden; + } else { + statusBarHidden = self.contentViewController.prefersStatusBarHidden; + } + ); return statusBarHidden; } @@ -810,13 +891,13 @@ - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation { UIStatusBarAnimation statusBarAnimation = UIStatusBarAnimationNone; IF_IOS7_OR_GREATER( - statusBarAnimation = self.visible ? self.leftMenuViewController.preferredStatusBarUpdateAnimation : self.contentViewController.preferredStatusBarUpdateAnimation; - if (self.contentViewContainer.frame.origin.y > 10) { - statusBarAnimation = self.leftMenuViewController.preferredStatusBarUpdateAnimation; - } else { - statusBarAnimation = self.contentViewController.preferredStatusBarUpdateAnimation; - } - ); + statusBarAnimation = self.visible ? self.leftMenuViewController.preferredStatusBarUpdateAnimation : self.contentViewController.preferredStatusBarUpdateAnimation; + if (self.contentViewContainer.frame.origin.y > 10) { + statusBarAnimation = self.leftMenuViewController.preferredStatusBarUpdateAnimation; + } else { + statusBarAnimation = self.contentViewController.preferredStatusBarUpdateAnimation; + } + ); return statusBarAnimation; }