Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit 91f70ce825cecb52d01b560ca0c4c5b236d9b199 Mark Pospesel committed
Showing with 5,954 additions and 0 deletions.
  1. +521 −0 EnterTheMatrix.xcodeproj/project.pbxproj
  2. +7 −0 EnterTheMatrix.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  3. +15 −0 EnterTheMatrix/AppDelegate.h
  4. +48 −0 EnterTheMatrix/AppDelegate.m
  5. +23 −0 EnterTheMatrix/Arc.h
  6. +216 −0 EnterTheMatrix/Arc.m
  7. BIN EnterTheMatrix/Bacon.png
  8. BIN EnterTheMatrix/Bacon@2x.png
  9. +13 −0 EnterTheMatrix/BaseView.h
  10. +49 −0 EnterTheMatrix/BaseView.m
  11. +48 −0 EnterTheMatrix/BasicAnimationViewController.h
  12. +230 −0 EnterTheMatrix/BasicAnimationViewController.m
  13. BIN EnterTheMatrix/Blueprint - iPad.png
  14. BIN EnterTheMatrix/Book.png
  15. BIN EnterTheMatrix/Book@2x.png
  16. +16 −0 EnterTheMatrix/CATransformController.h
  17. +25 −0 EnterTheMatrix/CATransformController.m
  18. +14 −0 EnterTheMatrix/CGAffineController.h
  19. +49 −0 EnterTheMatrix/CGAffineController.m
  20. +60 −0 EnterTheMatrix/EnterTheMatrix-Info.plist
  21. +19 −0 EnterTheMatrix/EnterTheMatrix-Prefix.pch
  22. +19 −0 EnterTheMatrix/Enumerations.h
  23. +47 −0 EnterTheMatrix/FlipViewController.h
  24. +548 −0 EnterTheMatrix/FlipViewController.m
  25. +42 −0 EnterTheMatrix/FoldViewController.h
  26. +284 −0 EnterTheMatrix/FoldViewController.m
  27. BIN EnterTheMatrix/Ghost.png
  28. BIN EnterTheMatrix/Ghost@2x.png
  29. +24 −0 EnterTheMatrix/GridView.h
  30. +190 −0 EnterTheMatrix/GridView.m
  31. +26 −0 EnterTheMatrix/GridViewController.h
  32. +221 −0 EnterTheMatrix/GridViewController.m
  33. BIN EnterTheMatrix/Info.png
  34. BIN EnterTheMatrix/Info@2x.png
  35. +14 −0 EnterTheMatrix/InfoView.h
  36. +58 −0 EnterTheMatrix/InfoView.m
  37. BIN EnterTheMatrix/Key.png
  38. BIN EnterTheMatrix/Key@2x.png
  39. +41 −0 EnterTheMatrix/KeyframeViewController.h
  40. +195 −0 EnterTheMatrix/KeyframeViewController.m
  41. BIN EnterTheMatrix/Lock.png
  42. BIN EnterTheMatrix/Lock@2x.png
  43. +15 −0 EnterTheMatrix/MPAnimation.h
  44. +37 −0 EnterTheMatrix/MPAnimation.m
  45. +44 −0 EnterTheMatrix/MPTransform.h
  46. +395 −0 EnterTheMatrix/MPTransform.m
  47. BIN EnterTheMatrix/PaperAirplane.png
  48. BIN EnterTheMatrix/PaperAirplane@2x.png
  49. BIN EnterTheMatrix/Sketchbook.png
  50. BIN EnterTheMatrix/Sketchbook@2x.png
  51. BIN EnterTheMatrix/Sword.png
  52. BIN EnterTheMatrix/Sword@2x.png
  53. +37 −0 EnterTheMatrix/TransformController.h
  54. +351 −0 EnterTheMatrix/TransformController.m
  55. +34 −0 EnterTheMatrix/TransformTable.h
  56. +445 −0 EnterTheMatrix/TransformTable.m
  57. BIN EnterTheMatrix/Unlock.png
  58. BIN EnterTheMatrix/Unlock@2x.png
  59. +2 −0 EnterTheMatrix/en.lproj/InfoPlist.strings
  60. +1,514 −0 EnterTheMatrix/en.lproj/MainStoryboard_iPad.storyboard
  61. +18 −0 EnterTheMatrix/main.m
  62. BIN EnterTheMatrix/matrix_01.png
  63. BIN EnterTheMatrix/matrix_01@2x.png
  64. BIN EnterTheMatrix/matrix_02.png
  65. BIN EnterTheMatrix/matrix_02@2x.png
  66. BIN EnterTheMatrix/matrix_03.png
  67. BIN EnterTheMatrix/matrix_03@2x.png
  68. BIN EnterTheMatrix/matrix_04.png
  69. BIN EnterTheMatrix/matrix_04@2x.png
  70. BIN Icon-72.png
  71. BIN Icon-72@2x.png
  72. BIN Icon-Small-50.png
  73. BIN Icon-Small-50@2x.png
  74. BIN iTunesArtwork
521 EnterTheMatrix.xcodeproj/project.pbxproj
@@ -0,0 +1,521 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 4D177E331503781B0046AD1C /* Sketchbook.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D177E2F1503781B0046AD1C /* Sketchbook.png */; };
+ 4D177E341503781B0046AD1C /* Sketchbook@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D177E301503781B0046AD1C /* Sketchbook@2x.png */; };
+ 4D177E351503781B0046AD1C /* Sword.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D177E311503781B0046AD1C /* Sword.png */; };
+ 4D177E361503781B0046AD1C /* Sword@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D177E321503781B0046AD1C /* Sword@2x.png */; };
+ 4D177E3915037A250046AD1C /* GridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D177E3815037A250046AD1C /* GridView.m */; };
+ 4D177E401504D7330046AD1C /* GridViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D177E3F1504D7330046AD1C /* GridViewController.m */; };
+ 4D40BDBB150CC23700970F2D /* Arc.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D40BDBA150CC23700970F2D /* Arc.m */; };
+ 4D63B8C1150B6C0F00FA4482 /* FlipViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D63B8C0150B6C0F00FA4482 /* FlipViewController.m */; };
+ 4D63B8C6150B6F8600FA4482 /* matrix_01.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D63B8C2150B6F8600FA4482 /* matrix_01.png */; };
+ 4D63B8C7150B6F8600FA4482 /* matrix_02.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D63B8C3150B6F8600FA4482 /* matrix_02.png */; };
+ 4D63B8C8150B6F8600FA4482 /* matrix_03.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D63B8C4150B6F8600FA4482 /* matrix_03.png */; };
+ 4D63B8C9150B6F8600FA4482 /* matrix_04.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D63B8C5150B6F8600FA4482 /* matrix_04.png */; };
+ 4D63B8CC150B71A400FA4482 /* MPAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D63B8CB150B71A400FA4482 /* MPAnimation.m */; };
+ 4D6E91C41511041400B7D1D1 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91C31511041300B7D1D1 /* Icon-72.png */; };
+ 4D6E91C71511042D00B7D1D1 /* Icon-Small-50.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91C61511042D00B7D1D1 /* Icon-Small-50.png */; };
+ 4D6E91C91511049200B7D1D1 /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91C81511049200B7D1D1 /* Icon-72@2x.png */; };
+ 4D6E91CB151104D900B7D1D1 /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91CA151104D900B7D1D1 /* Icon-Small-50@2x.png */; };
+ 4D6E91CD1511077100B7D1D1 /* iTunesArtwork in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91CC1511077100B7D1D1 /* iTunesArtwork */; };
+ 4D6E91D0151109DD00B7D1D1 /* PaperAirplane.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91CE151109DD00B7D1D1 /* PaperAirplane.png */; };
+ 4D6E91D1151109DD00B7D1D1 /* PaperAirplane@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91CF151109DD00B7D1D1 /* PaperAirplane@2x.png */; };
+ 4D6E91D415110A3A00B7D1D1 /* Key.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91D215110A3A00B7D1D1 /* Key.png */; };
+ 4D6E91D515110A3A00B7D1D1 /* Key@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91D315110A3A00B7D1D1 /* Key@2x.png */; };
+ 4D6E91D815110B5000B7D1D1 /* Book.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91D615110B5000B7D1D1 /* Book.png */; };
+ 4D6E91D915110B5000B7D1D1 /* Book@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91D715110B5000B7D1D1 /* Book@2x.png */; };
+ 4D6E91E01511335900B7D1D1 /* TransformController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D6E91DF1511335900B7D1D1 /* TransformController.m */; };
+ 4D6E91E31511EBF700B7D1D1 /* matrix_02@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91E21511EBF700B7D1D1 /* matrix_02@2x.png */; };
+ 4D6E91E51511F46D00B7D1D1 /* matrix_01@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91E41511F46D00B7D1D1 /* matrix_01@2x.png */; };
+ 4D6E91E81511F47900B7D1D1 /* matrix_04@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91E61511F47900B7D1D1 /* matrix_04@2x.png */; };
+ 4D6E91E91511F47900B7D1D1 /* matrix_03@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91E71511F47900B7D1D1 /* matrix_03@2x.png */; };
+ 4D6E91F01511FCEE00B7D1D1 /* Blueprint - iPad.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6E91EF1511FCEE00B7D1D1 /* Blueprint - iPad.png */; };
+ 4D996D4D1508D37F00F8F186 /* BasicAnimationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D996D4C1508D37F00F8F186 /* BasicAnimationViewController.m */; };
+ 4D996D511509010300F8F186 /* Ghost.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D996D4F1509010300F8F186 /* Ghost.png */; };
+ 4D996D521509010300F8F186 /* Ghost@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D996D501509010300F8F186 /* Ghost@2x.png */; };
+ 4D996D651509A64600F8F186 /* KeyframeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D996D641509A64600F8F186 /* KeyframeViewController.m */; };
+ 4D996D681509A65800F8F186 /* FoldViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D996D671509A65800F8F186 /* FoldViewController.m */; };
+ 4DBE7B2614FB9290008174E8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DBE7B2514FB9290008174E8 /* UIKit.framework */; };
+ 4DBE7B2814FB9290008174E8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DBE7B2714FB9290008174E8 /* Foundation.framework */; };
+ 4DBE7B2A14FB9290008174E8 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DBE7B2914FB9290008174E8 /* CoreGraphics.framework */; };
+ 4DBE7B3014FB9290008174E8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B2E14FB9290008174E8 /* InfoPlist.strings */; };
+ 4DBE7B3214FB9290008174E8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B3114FB9290008174E8 /* main.m */; };
+ 4DBE7B3614FB9290008174E8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B3514FB9290008174E8 /* AppDelegate.m */; };
+ 4DBE7B3C14FB9290008174E8 /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B3A14FB9290008174E8 /* MainStoryboard_iPad.storyboard */; };
+ 4DBE7B3F14FB9290008174E8 /* CGAffineController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B3E14FB9290008174E8 /* CGAffineController.m */; };
+ 4DBE7B4614FB9290008174E8 /* CATransformController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B4514FB9290008174E8 /* CATransformController.m */; };
+ 4DBE7B5514FB9BE2008174E8 /* TransformTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B5414FB9BE2008174E8 /* TransformTable.m */; };
+ 4DBE7B6A14FCE557008174E8 /* MPTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBE7B6914FCE557008174E8 /* MPTransform.m */; };
+ 4DBE7B7914FD12C5008174E8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DBE7B7814FD12C5008174E8 /* QuartzCore.framework */; };
+ 4DBE7B8014FD16DE008174E8 /* Lock.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B7E14FD16DE008174E8 /* Lock.png */; };
+ 4DBE7B8114FD16DE008174E8 /* Lock@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B7F14FD16DE008174E8 /* Lock@2x.png */; };
+ 4DBE7B8814FD19E8008174E8 /* Unlock.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B8414FD19E7008174E8 /* Unlock.png */; };
+ 4DBE7B8914FD19E8008174E8 /* Unlock@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DBE7B8514FD19E7008174E8 /* Unlock@2x.png */; };
+ 4DCCB5FC15022E7E0065AA19 /* BaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DCCB5FB15022E7E0065AA19 /* BaseView.m */; };
+ 4DE4181914FDB6930007800B /* Bacon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DE4181714FDB6930007800B /* Bacon.png */; };
+ 4DE4181A14FDB6930007800B /* Bacon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DE4181814FDB6930007800B /* Bacon@2x.png */; };
+ 4DE4182214FE3C520007800B /* Info.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DE4182014FE3C520007800B /* Info.png */; };
+ 4DE4182314FE3C520007800B /* Info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DE4182114FE3C520007800B /* Info@2x.png */; };
+ 4DE4182914FE3F0E0007800B /* InfoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE4182814FE3F0E0007800B /* InfoView.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 4D177E2F1503781B0046AD1C /* Sketchbook.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Sketchbook.png; sourceTree = "<group>"; };
+ 4D177E301503781B0046AD1C /* Sketchbook@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Sketchbook@2x.png"; sourceTree = "<group>"; };
+ 4D177E311503781B0046AD1C /* Sword.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Sword.png; sourceTree = "<group>"; };
+ 4D177E321503781B0046AD1C /* Sword@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Sword@2x.png"; sourceTree = "<group>"; };
+ 4D177E3715037A250046AD1C /* GridView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GridView.h; sourceTree = "<group>"; };
+ 4D177E3815037A250046AD1C /* GridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GridView.m; sourceTree = "<group>"; };
+ 4D177E3E1504D7330046AD1C /* GridViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GridViewController.h; sourceTree = "<group>"; };
+ 4D177E3F1504D7330046AD1C /* GridViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GridViewController.m; sourceTree = "<group>"; };
+ 4D40BDB9150CC23700970F2D /* Arc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Arc.h; sourceTree = "<group>"; };
+ 4D40BDBA150CC23700970F2D /* Arc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Arc.m; sourceTree = "<group>"; };
+ 4D63B8BF150B6C0F00FA4482 /* FlipViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlipViewController.h; sourceTree = "<group>"; };
+ 4D63B8C0150B6C0F00FA4482 /* FlipViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlipViewController.m; sourceTree = "<group>"; };
+ 4D63B8C2150B6F8600FA4482 /* matrix_01.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = matrix_01.png; sourceTree = "<group>"; };
+ 4D63B8C3150B6F8600FA4482 /* matrix_02.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = matrix_02.png; sourceTree = "<group>"; };
+ 4D63B8C4150B6F8600FA4482 /* matrix_03.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = matrix_03.png; sourceTree = "<group>"; };
+ 4D63B8C5150B6F8600FA4482 /* matrix_04.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = matrix_04.png; sourceTree = "<group>"; };
+ 4D63B8CA150B71A400FA4482 /* MPAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnimation.h; sourceTree = "<group>"; };
+ 4D63B8CB150B71A400FA4482 /* MPAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnimation.m; sourceTree = "<group>"; };
+ 4D6E91C31511041300B7D1D1 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = "<group>"; };
+ 4D6E91C61511042D00B7D1D1 /* Icon-Small-50.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50.png"; sourceTree = "<group>"; };
+ 4D6E91C81511049200B7D1D1 /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = "<group>"; };
+ 4D6E91CA151104D900B7D1D1 /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = "<group>"; };
+ 4D6E91CC1511077100B7D1D1 /* iTunesArtwork */ = {isa = PBXFileReference; lastKnownFileType = file; path = iTunesArtwork; sourceTree = "<group>"; };
+ 4D6E91CE151109DD00B7D1D1 /* PaperAirplane.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PaperAirplane.png; sourceTree = "<group>"; };
+ 4D6E91CF151109DD00B7D1D1 /* PaperAirplane@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PaperAirplane@2x.png"; sourceTree = "<group>"; };
+ 4D6E91D215110A3A00B7D1D1 /* Key.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Key.png; sourceTree = "<group>"; };
+ 4D6E91D315110A3A00B7D1D1 /* Key@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Key@2x.png"; sourceTree = "<group>"; };
+ 4D6E91D615110B5000B7D1D1 /* Book.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Book.png; sourceTree = "<group>"; };
+ 4D6E91D715110B5000B7D1D1 /* Book@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Book@2x.png"; sourceTree = "<group>"; };
+ 4D6E91DE1511335900B7D1D1 /* TransformController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformController.h; sourceTree = "<group>"; };
+ 4D6E91DF1511335900B7D1D1 /* TransformController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransformController.m; sourceTree = "<group>"; };
+ 4D6E91E21511EBF700B7D1D1 /* matrix_02@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "matrix_02@2x.png"; sourceTree = "<group>"; };
+ 4D6E91E41511F46D00B7D1D1 /* matrix_01@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "matrix_01@2x.png"; sourceTree = "<group>"; };
+ 4D6E91E61511F47900B7D1D1 /* matrix_04@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "matrix_04@2x.png"; sourceTree = "<group>"; };
+ 4D6E91E71511F47900B7D1D1 /* matrix_03@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "matrix_03@2x.png"; sourceTree = "<group>"; };
+ 4D6E91EF1511FCEE00B7D1D1 /* Blueprint - iPad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Blueprint - iPad.png"; sourceTree = "<group>"; };
+ 4D996D4B1508D37F00F8F186 /* BasicAnimationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicAnimationViewController.h; sourceTree = "<group>"; };
+ 4D996D4C1508D37F00F8F186 /* BasicAnimationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BasicAnimationViewController.m; sourceTree = "<group>"; };
+ 4D996D4F1509010300F8F186 /* Ghost.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Ghost.png; sourceTree = "<group>"; };
+ 4D996D501509010300F8F186 /* Ghost@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Ghost@2x.png"; sourceTree = "<group>"; };
+ 4D996D631509A64600F8F186 /* KeyframeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyframeViewController.h; sourceTree = "<group>"; };
+ 4D996D641509A64600F8F186 /* KeyframeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeyframeViewController.m; sourceTree = "<group>"; };
+ 4D996D661509A65800F8F186 /* FoldViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoldViewController.h; sourceTree = "<group>"; };
+ 4D996D671509A65800F8F186 /* FoldViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FoldViewController.m; sourceTree = "<group>"; };
+ 4DBE7B2114FB9290008174E8 /* EnterTheMatrix.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EnterTheMatrix.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4DBE7B2514FB9290008174E8 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 4DBE7B2714FB9290008174E8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 4DBE7B2914FB9290008174E8 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 4DBE7B2D14FB9290008174E8 /* EnterTheMatrix-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EnterTheMatrix-Info.plist"; sourceTree = "<group>"; };
+ 4DBE7B2F14FB9290008174E8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 4DBE7B3114FB9290008174E8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 4DBE7B3314FB9290008174E8 /* EnterTheMatrix-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EnterTheMatrix-Prefix.pch"; sourceTree = "<group>"; };
+ 4DBE7B3414FB9290008174E8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+ 4DBE7B3514FB9290008174E8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ 4DBE7B3B14FB9290008174E8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = "<group>"; };
+ 4DBE7B3D14FB9290008174E8 /* CGAffineController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CGAffineController.h; sourceTree = "<group>"; };
+ 4DBE7B3E14FB9290008174E8 /* CGAffineController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CGAffineController.m; sourceTree = "<group>"; };
+ 4DBE7B4414FB9290008174E8 /* CATransformController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CATransformController.h; sourceTree = "<group>"; };
+ 4DBE7B4514FB9290008174E8 /* CATransformController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CATransformController.m; sourceTree = "<group>"; };
+ 4DBE7B5314FB9BE2008174E8 /* TransformTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformTable.h; sourceTree = "<group>"; };
+ 4DBE7B5414FB9BE2008174E8 /* TransformTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransformTable.m; sourceTree = "<group>"; };
+ 4DBE7B5614FBA69D008174E8 /* Enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Enumerations.h; sourceTree = "<group>"; };
+ 4DBE7B6814FCE557008174E8 /* MPTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTransform.h; sourceTree = "<group>"; };
+ 4DBE7B6914FCE557008174E8 /* MPTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTransform.m; sourceTree = "<group>"; };
+ 4DBE7B7814FD12C5008174E8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 4DBE7B7E14FD16DE008174E8 /* Lock.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Lock.png; sourceTree = "<group>"; };
+ 4DBE7B7F14FD16DE008174E8 /* Lock@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Lock@2x.png"; sourceTree = "<group>"; };
+ 4DBE7B8414FD19E7008174E8 /* Unlock.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Unlock.png; sourceTree = "<group>"; };
+ 4DBE7B8514FD19E7008174E8 /* Unlock@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Unlock@2x.png"; sourceTree = "<group>"; };
+ 4DCCB5FA15022E7E0065AA19 /* BaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseView.h; sourceTree = "<group>"; };
+ 4DCCB5FB15022E7E0065AA19 /* BaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseView.m; sourceTree = "<group>"; };
+ 4DE4181714FDB6930007800B /* Bacon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Bacon.png; sourceTree = "<group>"; };
+ 4DE4181814FDB6930007800B /* Bacon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Bacon@2x.png"; sourceTree = "<group>"; };
+ 4DE4182014FE3C520007800B /* Info.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Info.png; sourceTree = "<group>"; };
+ 4DE4182114FE3C520007800B /* Info@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Info@2x.png"; sourceTree = "<group>"; };
+ 4DE4182714FE3F0D0007800B /* InfoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoView.h; sourceTree = "<group>"; };
+ 4DE4182814FE3F0E0007800B /* InfoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InfoView.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4DBE7B1E14FB9290008174E8 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4DBE7B7914FD12C5008174E8 /* QuartzCore.framework in Frameworks */,
+ 4DBE7B2614FB9290008174E8 /* UIKit.framework in Frameworks */,
+ 4DBE7B2814FB9290008174E8 /* Foundation.framework in Frameworks */,
+ 4DBE7B2A14FB9290008174E8 /* CoreGraphics.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4DBE7B1614FB9290008174E8 = {
+ isa = PBXGroup;
+ children = (
+ 4D6E91C81511049200B7D1D1 /* Icon-72@2x.png */,
+ 4D6E91C31511041300B7D1D1 /* Icon-72.png */,
+ 4D6E91C61511042D00B7D1D1 /* Icon-Small-50.png */,
+ 4D6E91CA151104D900B7D1D1 /* Icon-Small-50@2x.png */,
+ 4D6E91CC1511077100B7D1D1 /* iTunesArtwork */,
+ 4DBE7B7814FD12C5008174E8 /* QuartzCore.framework */,
+ 4DBE7B2B14FB9290008174E8 /* EnterTheMatrix */,
+ 4DBE7B2414FB9290008174E8 /* Frameworks */,
+ 4DBE7B2214FB9290008174E8 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 4DBE7B2214FB9290008174E8 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4DBE7B2114FB9290008174E8 /* EnterTheMatrix.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4DBE7B2414FB9290008174E8 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 4DBE7B2514FB9290008174E8 /* UIKit.framework */,
+ 4DBE7B2714FB9290008174E8 /* Foundation.framework */,
+ 4DBE7B2914FB9290008174E8 /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 4DBE7B2B14FB9290008174E8 /* EnterTheMatrix */ = {
+ isa = PBXGroup;
+ children = (
+ 4DBE7B5014FB9458008174E8 /* images */,
+ 4DBE7B2C14FB9290008174E8 /* Supporting Files */,
+ 4DBE7B3414FB9290008174E8 /* AppDelegate.h */,
+ 4DBE7B3514FB9290008174E8 /* AppDelegate.m */,
+ 4DBE7B3A14FB9290008174E8 /* MainStoryboard_iPad.storyboard */,
+ 4DBE7B3D14FB9290008174E8 /* CGAffineController.h */,
+ 4DBE7B3E14FB9290008174E8 /* CGAffineController.m */,
+ 4DBE7B4414FB9290008174E8 /* CATransformController.h */,
+ 4DBE7B4514FB9290008174E8 /* CATransformController.m */,
+ 4D6E91DE1511335900B7D1D1 /* TransformController.h */,
+ 4D6E91DF1511335900B7D1D1 /* TransformController.m */,
+ 4DBE7B5314FB9BE2008174E8 /* TransformTable.h */,
+ 4DBE7B5414FB9BE2008174E8 /* TransformTable.m */,
+ 4DE4182714FE3F0D0007800B /* InfoView.h */,
+ 4DE4182814FE3F0E0007800B /* InfoView.m */,
+ 4DCCB5FA15022E7E0065AA19 /* BaseView.h */,
+ 4DCCB5FB15022E7E0065AA19 /* BaseView.m */,
+ 4D177E3715037A250046AD1C /* GridView.h */,
+ 4D177E3815037A250046AD1C /* GridView.m */,
+ 4D177E3E1504D7330046AD1C /* GridViewController.h */,
+ 4D177E3F1504D7330046AD1C /* GridViewController.m */,
+ 4D996D4B1508D37F00F8F186 /* BasicAnimationViewController.h */,
+ 4D996D4C1508D37F00F8F186 /* BasicAnimationViewController.m */,
+ 4D996D631509A64600F8F186 /* KeyframeViewController.h */,
+ 4D996D641509A64600F8F186 /* KeyframeViewController.m */,
+ 4D996D661509A65800F8F186 /* FoldViewController.h */,
+ 4D996D671509A65800F8F186 /* FoldViewController.m */,
+ 4D63B8BF150B6C0F00FA4482 /* FlipViewController.h */,
+ 4D63B8C0150B6C0F00FA4482 /* FlipViewController.m */,
+ 4D63B8CA150B71A400FA4482 /* MPAnimation.h */,
+ 4D63B8CB150B71A400FA4482 /* MPAnimation.m */,
+ 4DBE7B6814FCE557008174E8 /* MPTransform.h */,
+ 4DBE7B6914FCE557008174E8 /* MPTransform.m */,
+ 4D40BDB9150CC23700970F2D /* Arc.h */,
+ 4D40BDBA150CC23700970F2D /* Arc.m */,
+ );
+ path = EnterTheMatrix;
+ sourceTree = "<group>";
+ };
+ 4DBE7B2C14FB9290008174E8 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 4DBE7B2D14FB9290008174E8 /* EnterTheMatrix-Info.plist */,
+ 4DBE7B2E14FB9290008174E8 /* InfoPlist.strings */,
+ 4DBE7B3114FB9290008174E8 /* main.m */,
+ 4DBE7B3314FB9290008174E8 /* EnterTheMatrix-Prefix.pch */,
+ 4DBE7B5614FBA69D008174E8 /* Enumerations.h */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 4DBE7B5014FB9458008174E8 /* images */ = {
+ isa = PBXGroup;
+ children = (
+ 4D6E91EF1511FCEE00B7D1D1 /* Blueprint - iPad.png */,
+ 4DBE7B7E14FD16DE008174E8 /* Lock.png */,
+ 4DBE7B7F14FD16DE008174E8 /* Lock@2x.png */,
+ 4DBE7B8414FD19E7008174E8 /* Unlock.png */,
+ 4DBE7B8514FD19E7008174E8 /* Unlock@2x.png */,
+ 4DE4181714FDB6930007800B /* Bacon.png */,
+ 4DE4181814FDB6930007800B /* Bacon@2x.png */,
+ 4DE4182014FE3C520007800B /* Info.png */,
+ 4DE4182114FE3C520007800B /* Info@2x.png */,
+ 4D177E2F1503781B0046AD1C /* Sketchbook.png */,
+ 4D177E301503781B0046AD1C /* Sketchbook@2x.png */,
+ 4D177E311503781B0046AD1C /* Sword.png */,
+ 4D177E321503781B0046AD1C /* Sword@2x.png */,
+ 4D996D4F1509010300F8F186 /* Ghost.png */,
+ 4D996D501509010300F8F186 /* Ghost@2x.png */,
+ 4D6E91D215110A3A00B7D1D1 /* Key.png */,
+ 4D6E91D315110A3A00B7D1D1 /* Key@2x.png */,
+ 4D6E91CE151109DD00B7D1D1 /* PaperAirplane.png */,
+ 4D6E91CF151109DD00B7D1D1 /* PaperAirplane@2x.png */,
+ 4D6E91D615110B5000B7D1D1 /* Book.png */,
+ 4D6E91D715110B5000B7D1D1 /* Book@2x.png */,
+ 4D63B8C2150B6F8600FA4482 /* matrix_01.png */,
+ 4D6E91E41511F46D00B7D1D1 /* matrix_01@2x.png */,
+ 4D63B8C3150B6F8600FA4482 /* matrix_02.png */,
+ 4D6E91E21511EBF700B7D1D1 /* matrix_02@2x.png */,
+ 4D63B8C4150B6F8600FA4482 /* matrix_03.png */,
+ 4D6E91E71511F47900B7D1D1 /* matrix_03@2x.png */,
+ 4D63B8C5150B6F8600FA4482 /* matrix_04.png */,
+ 4D6E91E61511F47900B7D1D1 /* matrix_04@2x.png */,
+ );
+ name = images;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 4DBE7B2014FB9290008174E8 /* EnterTheMatrix */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4DBE7B4D14FB9290008174E8 /* Build configuration list for PBXNativeTarget "EnterTheMatrix" */;
+ buildPhases = (
+ 4DBE7B1D14FB9290008174E8 /* Sources */,
+ 4DBE7B1E14FB9290008174E8 /* Frameworks */,
+ 4DBE7B1F14FB9290008174E8 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = EnterTheMatrix;
+ productName = EnterTheMatrix;
+ productReference = 4DBE7B2114FB9290008174E8 /* EnterTheMatrix.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 4DBE7B1814FB9290008174E8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ ORGANIZATIONNAME = "Mark Pospesel";
+ };
+ buildConfigurationList = 4DBE7B1B14FB9290008174E8 /* Build configuration list for PBXProject "EnterTheMatrix" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 4DBE7B1614FB9290008174E8;
+ productRefGroup = 4DBE7B2214FB9290008174E8 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4DBE7B2014FB9290008174E8 /* EnterTheMatrix */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 4DBE7B1F14FB9290008174E8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4DBE7B3014FB9290008174E8 /* InfoPlist.strings in Resources */,
+ 4DBE7B3C14FB9290008174E8 /* MainStoryboard_iPad.storyboard in Resources */,
+ 4DBE7B8014FD16DE008174E8 /* Lock.png in Resources */,
+ 4DBE7B8114FD16DE008174E8 /* Lock@2x.png in Resources */,
+ 4DBE7B8814FD19E8008174E8 /* Unlock.png in Resources */,
+ 4DBE7B8914FD19E8008174E8 /* Unlock@2x.png in Resources */,
+ 4DE4181914FDB6930007800B /* Bacon.png in Resources */,
+ 4DE4181A14FDB6930007800B /* Bacon@2x.png in Resources */,
+ 4DE4182214FE3C520007800B /* Info.png in Resources */,
+ 4DE4182314FE3C520007800B /* Info@2x.png in Resources */,
+ 4D177E331503781B0046AD1C /* Sketchbook.png in Resources */,
+ 4D177E341503781B0046AD1C /* Sketchbook@2x.png in Resources */,
+ 4D177E351503781B0046AD1C /* Sword.png in Resources */,
+ 4D177E361503781B0046AD1C /* Sword@2x.png in Resources */,
+ 4D996D511509010300F8F186 /* Ghost.png in Resources */,
+ 4D996D521509010300F8F186 /* Ghost@2x.png in Resources */,
+ 4D63B8C6150B6F8600FA4482 /* matrix_01.png in Resources */,
+ 4D63B8C7150B6F8600FA4482 /* matrix_02.png in Resources */,
+ 4D63B8C8150B6F8600FA4482 /* matrix_03.png in Resources */,
+ 4D63B8C9150B6F8600FA4482 /* matrix_04.png in Resources */,
+ 4D6E91C41511041400B7D1D1 /* Icon-72.png in Resources */,
+ 4D6E91C71511042D00B7D1D1 /* Icon-Small-50.png in Resources */,
+ 4D6E91C91511049200B7D1D1 /* Icon-72@2x.png in Resources */,
+ 4D6E91CB151104D900B7D1D1 /* Icon-Small-50@2x.png in Resources */,
+ 4D6E91CD1511077100B7D1D1 /* iTunesArtwork in Resources */,
+ 4D6E91D0151109DD00B7D1D1 /* PaperAirplane.png in Resources */,
+ 4D6E91D1151109DD00B7D1D1 /* PaperAirplane@2x.png in Resources */,
+ 4D6E91D415110A3A00B7D1D1 /* Key.png in Resources */,
+ 4D6E91D515110A3A00B7D1D1 /* Key@2x.png in Resources */,
+ 4D6E91D815110B5000B7D1D1 /* Book.png in Resources */,
+ 4D6E91D915110B5000B7D1D1 /* Book@2x.png in Resources */,
+ 4D6E91E31511EBF700B7D1D1 /* matrix_02@2x.png in Resources */,
+ 4D6E91E51511F46D00B7D1D1 /* matrix_01@2x.png in Resources */,
+ 4D6E91E81511F47900B7D1D1 /* matrix_04@2x.png in Resources */,
+ 4D6E91E91511F47900B7D1D1 /* matrix_03@2x.png in Resources */,
+ 4D6E91F01511FCEE00B7D1D1 /* Blueprint - iPad.png in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4DBE7B1D14FB9290008174E8 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4DBE7B3214FB9290008174E8 /* main.m in Sources */,
+ 4DBE7B3614FB9290008174E8 /* AppDelegate.m in Sources */,
+ 4DBE7B3F14FB9290008174E8 /* CGAffineController.m in Sources */,
+ 4DBE7B4614FB9290008174E8 /* CATransformController.m in Sources */,
+ 4DBE7B5514FB9BE2008174E8 /* TransformTable.m in Sources */,
+ 4DBE7B6A14FCE557008174E8 /* MPTransform.m in Sources */,
+ 4DE4182914FE3F0E0007800B /* InfoView.m in Sources */,
+ 4DCCB5FC15022E7E0065AA19 /* BaseView.m in Sources */,
+ 4D177E3915037A250046AD1C /* GridView.m in Sources */,
+ 4D177E401504D7330046AD1C /* GridViewController.m in Sources */,
+ 4D996D4D1508D37F00F8F186 /* BasicAnimationViewController.m in Sources */,
+ 4D996D651509A64600F8F186 /* KeyframeViewController.m in Sources */,
+ 4D996D681509A65800F8F186 /* FoldViewController.m in Sources */,
+ 4D63B8C1150B6C0F00FA4482 /* FlipViewController.m in Sources */,
+ 4D63B8CC150B71A400FA4482 /* MPAnimation.m in Sources */,
+ 4D40BDBB150CC23700970F2D /* Arc.m in Sources */,
+ 4D6E91E01511335900B7D1D1 /* TransformController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 4DBE7B2E14FB9290008174E8 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4DBE7B2F14FB9290008174E8 /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ 4DBE7B3A14FB9290008174E8 /* MainStoryboard_iPad.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 4DBE7B3B14FB9290008174E8 /* en */,
+ );
+ name = MainStoryboard_iPad.storyboard;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 4DBE7B4B14FB9290008174E8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4DBE7B4C14FB9290008174E8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 4DBE7B4E14FB9290008174E8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "EnterTheMatrix/EnterTheMatrix-Prefix.pch";
+ INFOPLIST_FILE = "EnterTheMatrix/EnterTheMatrix-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 2;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 4DBE7B4F14FB9290008174E8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "EnterTheMatrix/EnterTheMatrix-Prefix.pch";
+ INFOPLIST_FILE = "EnterTheMatrix/EnterTheMatrix-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = 2;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4DBE7B1B14FB9290008174E8 /* Build configuration list for PBXProject "EnterTheMatrix" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4DBE7B4B14FB9290008174E8 /* Debug */,
+ 4DBE7B4C14FB9290008174E8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4DBE7B4D14FB9290008174E8 /* Build configuration list for PBXNativeTarget "EnterTheMatrix" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4DBE7B4E14FB9290008174E8 /* Debug */,
+ 4DBE7B4F14FB9290008174E8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 4DBE7B1814FB9290008174E8 /* Project object */;
+}
7 EnterTheMatrix.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:EnterTheMatrix.xcodeproj">
+ </FileRef>
+</Workspace>
15 EnterTheMatrix/AppDelegate.h
@@ -0,0 +1,15 @@
+//
+// AppDelegate.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
48 EnterTheMatrix/AppDelegate.m
@@ -0,0 +1,48 @@
+//
+// AppDelegate.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@implementation AppDelegate
+
+@synthesize window = _window;
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
23 EnterTheMatrix/Arc.h
@@ -0,0 +1,23 @@
+//
+// Arc.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/11/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface Arc : UIView
+
+@property (nonatomic, assign) CGFloat radius;
+@property (nonatomic, assign) CGFloat arcWidth;
+@property (nonatomic, assign) CGFloat arcOpacity;
+@property (nonatomic, strong) UIColor* color;
+@property (nonatomic, strong) UIColor* highlightColor;
+@property (nonatomic, readonly) CGFloat innerRadius;
+@property (nonatomic, readonly) CGFloat midRadius;
+@property (nonatomic, readonly) CGFloat outerRadius;
+@property (nonatomic, readonly) CGPoint arCenter;
+
+@end
216 EnterTheMatrix/Arc.m
@@ -0,0 +1,216 @@
+//
+// Arc.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/11/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "Arc.h"
+
+#define DEFAULT_RADIUS 444
+#define DEFAULT_ARC_WIDTH 120
+#define DEFAULT_ARC_OPACITY 1.00
+#define DEFAULT_ITEM_GAP 20
+#define GRADIENT_LIGHT_ANGLE 115
+#define DEFAULT_CAROUSEL_HEIGHT 132
+#define HORZ_GAP 10
+
+@implementation Arc
+@synthesize radius;
+@synthesize arcWidth;
+@synthesize arcOpacity;
+@synthesize color;
+@synthesize highlightColor;
+
+- (void)doInit
+{
+ radius = DEFAULT_RADIUS;
+ arcWidth = DEFAULT_ARC_WIDTH;
+ arcOpacity = DEFAULT_ARC_OPACITY;
+ color = [UIColor colorWithRed:56./255 green:84./255 blue:135./255 alpha:1.0];
+ highlightColor = [UIColor colorWithRed:155./255 green:169./255 blue:195./255 alpha:1.0];
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self) {
+ // Initialization code
+ [self doInit];
+ }
+ return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ // Initialization code
+ [self doInit];
+ }
+ return self;
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super initWithCoder:aDecoder];
+ if (self) {
+ // Initialization code
+ [self doInit];
+ }
+ return self;
+}
+
+#pragma mark - Properties
+
+- (CGFloat)innerRadius
+{
+ return self.radius - self.arcWidth;
+}
+
+- (CGFloat)midRadius
+{
+ return self.radius - (self.arcWidth / 2);
+}
+
+- (CGFloat)outerRadius
+{
+ return self.radius;
+}
+
+- (CGPoint)arCenter
+{
+ return CGPointMake(self.bounds.size.width - self.arcWidth / 2, self.bounds.size.height - self.arcWidth / 2);
+}
+
+- (CGPathRef)newArcPath
+{
+ CGFloat innerRadius = [self innerRadius];
+ CGFloat outerRadius = [self outerRadius];
+ CGRect bounds = self.bounds;
+
+ // get the current graphics context
+ CGPoint center = [self arCenter];
+
+ // build our arc shape
+ CGMutablePathRef path = CGPathCreateMutable();
+ CGPathAddArc(path, nil, center.x, center.y, outerRadius, radians(-180), radians(-90), NO);
+ CGPathAddLineToPoint(path, nil, bounds.size.width, bounds.size.height - self.arcWidth/2 - self.midRadius);
+ CGPathAddLineToPoint(path, nil,bounds.size.width - self.arcWidth / 2, bounds.size.height - self.arcWidth/2 - innerRadius);
+ CGPathAddArc(path, nil, center.x, center.y, innerRadius, radians(-90), radians(-180), YES);
+ CGPathAddLineToPoint(path, nil, bounds.size.width - self.arcWidth/2 - self.midRadius, bounds.size.height);
+ CGPathAddLineToPoint(path, nil,bounds.size.width - self.arcWidth / 2 - outerRadius, bounds.size.height - self.arcWidth/2);
+
+ return path;
+ //CGPathRef fixedPath = CGPathCreateCopy(path);
+ //CGPathRelease(path);
+ //return fixedPath;
+}
+
+- (CGColorRef)newColorFromSpace:(CGColorSpaceRef)colorSpace color1:(CGColorRef)color1 color2:(CGColorRef)color2
+{
+ const CGFloat* components1 = CGColorGetComponents(color1);
+ const CGFloat* components2 = CGColorGetComponents(color2);
+ int numberOfComponents1 = CGColorGetNumberOfComponents(color1);
+ int numberOfComponents2 = CGColorGetNumberOfComponents(color2);
+ if (numberOfComponents1 != numberOfComponents2) {
+ [NSException raise:@"Diffferent color spaces" format:@"Color 1 has %d color components, but Color 2 has %d color components", numberOfComponents1, numberOfComponents2];
+ }
+ CGFloat midComponents[numberOfComponents1];
+ for (int i = 0; i < numberOfComponents1; i++)
+ midComponents[i] = (components1[i] + components2[i])/2.0;
+ return CGColorCreate(colorSpace, midComponents);
+}
+
+- (void)layoutSubviews
+{
+ CGRect bounds = self.bounds;
+
+ self.radius = MIN(bounds.size.width, bounds.size.height) - self.arcWidth / 2;
+ [self setNeedsDisplay];
+}
+
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect
+{
+ // Drawing code
+ // draw arc segment as it intersects screen
+ // need to determine angle theta as well as height of the arc segment
+ CGFloat innerRadius = [self innerRadius];
+ CGFloat outerRadius = [self outerRadius];
+ CGRect bounds = self.bounds;
+
+ // get the current graphics context
+ CGPoint center = [self arCenter];
+
+ CGPoint innerTop = CGPointMake(bounds.size.width - self.arcWidth / 2, bounds.size.height - self.arcWidth/2 - innerRadius);
+ CGPoint innerBottom = CGPointMake(bounds.size.width - self.arcWidth / 2 - innerRadius, bounds.size.height - self.arcWidth/2);
+
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextSaveGState(context);
+
+ // build our arc shape
+ CGPathRef path = [self newArcPath];
+ CGContextAddPath(context, path);
+
+ // create our colors and gradient
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGFloat locations[] = { 0.0, 0.25, 0.75, 1.0 };
+
+ CGFloat midColorComponents[] = { 0, 0, 0, 1 };
+ CGFloat endColorComponents[] = { 0, 0, .75, 1 };
+
+ CGColorRef cgMidColor = CGColorCreate(colorSpace, midColorComponents);
+ CGColorRef cgEndColor = CGColorCreate(colorSpace, endColorComponents);
+ NSArray *colors = [NSArray arrayWithObjects:(__bridge id)cgEndColor, (__bridge id)cgMidColor, (__bridge id)cgMidColor, (__bridge id)cgEndColor, nil];
+
+ CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,
+ (__bridge CFArrayRef) colors, locations);
+
+ /*CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGFloat locations[] = { 0, 0.2, 1.0 };
+
+ CGColorRef startColor = [[[self highlightColor] colorWithAlphaComponent:self.arcOpacity] CGColor];
+ CGColorRef endColor = [[[self color] colorWithAlphaComponent:self.arcOpacity] CGColor];
+ const CGFloat* components = CGColorGetComponents(endColor);
+ CGFloat midComponents[4];
+ for (int i = 0; i < 3; i++)
+ midComponents[i] = (components[i] + 1.0)/2.0;
+ midComponents[3] = self.arcOpacity;
+ CGColorRef midColor = [self newColorFromSpace:colorSpace color1:startColor color2:endColor];
+ NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)midColor, (__bridge id)endColor, nil];
+
+ CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,
+ (__bridge CFArrayRef) colors, locations);*/
+
+ // clip context to our shape, then draw gradient
+ CGContextClip(context);
+ CGFloat lightSourceRadians = radians(GRADIENT_LIGHT_ANGLE);
+ CGPoint startPoint = CGPointMake(bounds.origin.x + outerRadius*cos(-lightSourceRadians) + center.x, bounds.origin.y + outerRadius*sin(-lightSourceRadians) + center.y);
+ // end point of gradient- at intersection of line from startPoint to center and line from innerTop to innerBottom
+ CGFloat A1 = startPoint.y-center.y;
+ CGFloat B1 = center.x-startPoint.x;
+ CGFloat C1 = A1*center.x+B1*center.y;
+ CGFloat A2 = (innerTop.y + center.y) - (innerBottom.y + center.y);
+ CGFloat B2 = (innerBottom.x + center.x)-(innerTop.x + center.x);
+ CGFloat C2 = A2*(innerBottom.x + center.x)+B2*(innerBottom.y + center.y);
+ double det = A1*B2 - A2*B1;
+ CGPoint endPoint = CGPointMake((B2*C1 - B1*C2)/det, (A1*C2 - A2*C1)/det);
+ //CGPoint startPoint = CGPointMake(bounds.origin.x, bounds.origin.y);
+ //CGPoint endPoint = CGPointMake(bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height);
+ CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
+
+ // cleanup
+ CGContextRestoreGState(context); // Important! remove the clipping
+ CGPathRelease(path);
+ //CGColorRelease(midColor);
+ CGColorRelease(cgEndColor);
+ CGColorRelease(cgMidColor);
+ CGColorSpaceRelease(colorSpace);
+ CGGradientRelease(gradient);
+}
+
+
+@end
BIN EnterTheMatrix/Bacon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN EnterTheMatrix/Bacon@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 EnterTheMatrix/BaseView.h
@@ -0,0 +1,13 @@
+//
+// BaseView.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/3/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface BaseView : UIViewController
+
+@end
49 EnterTheMatrix/BaseView.m
@@ -0,0 +1,49 @@
+//
+// BaseView.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/3/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "BaseView.h"
+
+@interface BaseView ()
+
+@end
+
+@implementation BaseView
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)loadView
+{
+ // If you create your views manually, you MUST override this method and use it to create your views.
+ // If you use Interface Builder to create your views, then you must NOT override this method.
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+@end
48 EnterTheMatrix/BasicAnimationViewController.h
@@ -0,0 +1,48 @@
+//
+// BasicAnimationViewController.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/8/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum
+{
+ OrientationLeft,
+ OrientationTop,
+ OrientationRight,
+ OrientationBottom
+} OrientationMode;
+
+typedef enum
+{
+ AnimationFrame,
+ AnimationTransform
+} AnimationMode;
+
+@interface BasicAnimationViewController : UIViewController
+
+@property (weak, nonatomic) IBOutlet UISegmentedControl *modeSegment;
+@property (weak, nonatomic) IBOutlet UISwitch *speedSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *translateSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *scaleSwitch;
+@property (weak, nonatomic) IBOutlet UISwitch *rotateSwitch;
+@property (weak, nonatomic) IBOutlet UIView *bar;
+@property (weak, nonatomic) IBOutlet UILabel *translateLabel;
+@property (weak, nonatomic) IBOutlet UILabel *scaleLabel;
+@property (weak, nonatomic) IBOutlet UILabel *rotateLabel;
+@property (weak, nonatomic) IBOutlet UIView *controlFrame;
+
+@property (assign, nonatomic) OrientationMode orientation;
+@property (readonly, nonatomic) BOOL isFast;
+@property (readonly, nonatomic) BOOL useTranslate;
+@property (readonly, nonatomic) BOOL useScale;
+@property (readonly, nonatomic) BOOL useRotate;
+@property (readonly, nonatomic) AnimationMode animation;
+
+- (IBAction)goPressed:(id)sender;
+- (IBAction)animationChanged:(id)sender;
+
+@end
230 EnterTheMatrix/BasicAnimationViewController.m
@@ -0,0 +1,230 @@
+//
+// BasicAnimationViewController.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/8/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "BasicAnimationViewController.h"
+#include <QuartzCore/QuartzCore.h>
+
+#define MINOR_AXIS 100
+
+@interface BasicAnimationViewController ()
+
+@end
+
+@implementation BasicAnimationViewController
+
+@synthesize modeSegment;
+@synthesize speedSwitch;
+@synthesize translateSwitch;
+@synthesize scaleSwitch;
+@synthesize rotateSwitch;
+@synthesize bar;
+@synthesize translateLabel;
+@synthesize scaleLabel;
+@synthesize rotateLabel;
+@synthesize controlFrame;
+@synthesize orientation;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)addDropShadowToView:(UIView *)view
+{
+ view.layer.shadowOpacity = 0.5;
+ view.layer.shadowOffset = CGSizeMake(0, 3);
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+
+ self.controlFrame.layer.cornerRadius = 5;
+ [self addDropShadowToView:self.controlFrame];
+
+ orientation = OrientationBottom;
+ [self addDropShadowToView:self.bar];
+
+ // Do any additional setup after loading the view.
+}
+
+- (void)viewDidUnload
+{
+ [self setBar:nil];
+ [self setSpeedSwitch:nil];
+ [self setModeSegment:nil];
+ [self setTranslateSwitch:nil];
+ [self setScaleSwitch:nil];
+ [self setRotateSwitch:nil];
+ [self setTranslateLabel:nil];
+ [self setScaleLabel:nil];
+ [self setRotateLabel:nil];
+ [self setControlFrame:nil];
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+- (BOOL)isFast
+{
+ return [[self speedSwitch] isOn];
+}
+
+- (BOOL)useTranslate
+{
+ return [[self translateSwitch] isOn];
+}
+
+- (BOOL)useScale
+{
+ return [[self scaleSwitch] isOn];
+}
+
+- (BOOL)useRotate
+{
+ return [[self rotateSwitch] isOn];
+}
+
+- (AnimationMode)animation
+{
+ return (AnimationMode)[[self modeSegment] selectedSegmentIndex];
+}
+
+- (IBAction)goPressed:(id)sender {
+
+ CGRect newFrame;
+ UIViewAutoresizing newResizing;
+ OrientationMode newOrientation;
+ CGSize viewSize = self.view.bounds.size;
+
+ switch ([self orientation]) {
+ case OrientationLeft:
+ // rotating from left to top
+ newFrame = CGRectMake(0, 0, viewSize.width, MINOR_AXIS);
+ newOrientation = OrientationTop;
+ newResizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
+ break;
+
+ case OrientationTop:
+ // rotating from top to right
+ newFrame = CGRectMake(viewSize.width - MINOR_AXIS, 0, MINOR_AXIS, viewSize.height);
+ newOrientation = OrientationRight;
+ newResizing = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
+ break;
+
+ case OrientationRight:
+ // rotating from right to bottom
+ newFrame = CGRectMake(0, viewSize.height - MINOR_AXIS, viewSize.width, MINOR_AXIS);
+ newOrientation = OrientationBottom;
+ newResizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+ break;
+
+ case OrientationBottom:
+ // rotating from bottom to left
+ newFrame = CGRectMake(0, 0, MINOR_AXIS, viewSize.height);
+ newOrientation = OrientationLeft;
+ newResizing = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin;
+ break;
+ }
+
+ [UIView animateWithDuration:([self isFast]? 0.5 : 2.5)
+ delay:0
+ options:UIViewAnimationCurveEaseInOut
+ animations:^{
+ switch ([self animation]) {
+ case AnimationFrame:
+ self.bar.frame = newFrame;
+ break;
+
+ case AnimationTransform:
+ {
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGSize barSize = self.bar.bounds.size;
+
+ switch ([self orientation]) {
+ case OrientationLeft:
+ // rotating from left to top
+ if ([self useTranslate])
+ t = CGAffineTransformTranslate(t, (viewSize.width - MINOR_AXIS)/2, -(barSize.height - MINOR_AXIS)/2);
+ if ([self useRotate])
+ t = CGAffineTransformRotate(t, radians(-90));
+ if ([self useScale])
+ t = CGAffineTransformScale(t, 1, viewSize.width / barSize.height);
+ break;
+
+ case OrientationTop:
+ // rotating from top to right
+ if ([self useTranslate])
+ t = CGAffineTransformTranslate(t, (barSize.width - MINOR_AXIS)/2, (viewSize.height - MINOR_AXIS)/2);
+ if ([self useRotate])
+ t = CGAffineTransformRotate(t, radians(-90));
+ if ([self useScale])
+ t = CGAffineTransformScale(t, viewSize.height / barSize.width, 1);
+ break;
+
+ case OrientationRight:
+ // rotating from right to bottom
+ if ([self useTranslate])
+ t = CGAffineTransformTranslate(t, -(viewSize.width - MINOR_AXIS)/2, (barSize.height - MINOR_AXIS)/2);
+ if ([self useRotate])
+ t = CGAffineTransformRotate(t, radians(-90));
+ if ([self useScale])
+ t = CGAffineTransformScale(t, 1, viewSize.width / barSize.height);
+ break;
+
+ case OrientationBottom:
+ // rotating from bottom to left
+ if ([self useTranslate])
+ t = CGAffineTransformTranslate(t, -(barSize.width - MINOR_AXIS)/2, -(viewSize.height - MINOR_AXIS)/2);
+ if ([self useRotate])
+ t = CGAffineTransformRotate(t, radians(-90));
+ if ([self useScale])
+ t = CGAffineTransformScale(t, viewSize.height / barSize.width, 1);
+ break;
+ }
+
+ self.bar.transform = t;
+ }
+ break;
+ }
+ } completion:^(BOOL finished) {
+
+ [UIView animateWithDuration:([self animation] == AnimationTransform && (![self useTranslate] || ![self useRotate] || ![self useScale]))? 0.5 : 0
+ animations:^{
+ self.bar.transform = CGAffineTransformIdentity;
+ self.bar.frame = newFrame;
+ } completion:^(BOOL finished) {
+ self.orientation = newOrientation;
+ self.bar.autoresizingMask = newResizing;
+ }];
+ }
+ ];
+}
+
+- (IBAction)animationChanged:(id)sender {
+ // enable/disable controls
+ BOOL isTransform = [self animation] == AnimationTransform;
+
+ translateSwitch.enabled = isTransform;
+ scaleSwitch.enabled = isTransform;
+ rotateSwitch.enabled = isTransform;
+
+ translateLabel.textColor = isTransform? [UIColor darkTextColor] : [UIColor lightGrayColor];
+ scaleLabel.textColor = isTransform? [UIColor darkTextColor] : [UIColor lightGrayColor];
+ rotateLabel.textColor = isTransform? [UIColor darkTextColor] : [UIColor lightGrayColor];
+}
+@end
BIN EnterTheMatrix/Blueprint - iPad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN EnterTheMatrix/Book.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN EnterTheMatrix/Book@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 EnterTheMatrix/CATransformController.h
@@ -0,0 +1,16 @@
+//
+// CATransformController.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "TransformController.h"
+
+@interface CATransformController : TransformController
+
+@property (readonly, nonatomic) BOOL is3D;
+
+@end
25 EnterTheMatrix/CATransformController.m
@@ -0,0 +1,25 @@
+//
+// CATransformController.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#include <QuartzCore/QuartzCore.h>
+#import "CATransformController.h"
+
+@interface CATransformController ()
+
+@end
+
+@implementation CATransformController
+
+#pragma mark - Property
+
+- (BOOL)is3D
+{
+ return YES;
+}
+
+@end
14 EnterTheMatrix/CGAffineController.h
@@ -0,0 +1,14 @@
+//
+// CGAffineController.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "TransformController.h"
+
+@interface CGAffineController : TransformController
+
+@end
49 EnterTheMatrix/CGAffineController.m
@@ -0,0 +1,49 @@
+//
+// CGAffineController.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#include <QuartzCore/QuartzCore.h>
+#import "CGAffineController.h"
+#import "TransformTable.h"
+
+@interface CGAffineController ()
+
+@end
+
+@implementation CGAffineController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ // Test:
+ /*UIView *square = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
+ square.backgroundColor = [UIColor purpleColor];
+ square.layer.borderColor = [[UIColor blackColor] CGColor];
+ square.layer.borderWidth = 2;
+ [self.view addSubview:square];
+ NSLog(@"O Frame = %@", NSStringFromCGRect(square.frame));
+ NSLog(@"O Bounds = %@", NSStringFromCGRect(square.bounds));
+ NSLog(@"O Center = %@\n", NSStringFromCGPoint(square.center));
+ CATransform3D t = CATransform3DMakeTranslation(60, 140, 0);
+ square.layer.transform = t;
+ NSLog(@"T Frame = %@", NSStringFromCGRect(square.frame));
+ NSLog(@"T Bounds = %@", NSStringFromCGRect(square.bounds));
+ NSLog(@"T Center = %@\n", NSStringFromCGPoint(square.center));
+ t = CATransform3DScale(t, 0.5, 0.5, 0.5);
+ square.layer.transform = t;
+ NSLog(@"S Frame = %@", NSStringFromCGRect(square.frame));
+ NSLog(@"S Bounds = %@", NSStringFromCGRect(square.bounds));
+ NSLog(@"S Center = %@\n", NSStringFromCGPoint(square.center));
+ t = CATransform3DRotate(t, radians(60), 0, 0, 1);
+ square.layer.transform = t;
+ NSLog(@"R Frame = %@", NSStringFromCGRect(square.frame));
+ NSLog(@"R Bounds = %@", NSStringFromCGRect(square.bounds));
+ NSLog(@"R Center = %@\n", NSStringFromCGPoint(square.center));*/
+}
+
+@end
60 EnterTheMatrix/EnterTheMatrix-Info.plist
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIcons</key>
+ <dict>
+ <key>CFBundlePrimaryIcon</key>
+ <dict>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>Icon-72.png</string>
+ <string>Icon-72@2x.png</string>
+ </array>
+ </dict>
+ </dict>
+ <key>CFBundleIdentifier</key>
+ <string>com.markpospesel.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIMainStoryboardFile</key>
+ <string>MainStoryboard_iPhone</string>
+ <key>UIMainStoryboardFile~ipad</key>
+ <string>MainStoryboard_iPad</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
19 EnterTheMatrix/EnterTheMatrix-Prefix.pch
@@ -0,0 +1,19 @@
+//
+// Prefix header for all source files of the 'EnterTheMatrix' target in the 'EnterTheMatrix' project
+//
+
+#import <Availability.h>
+#include <math.h>
+#import "Enumerations.h"
+
+static inline double radians (double degrees) {return degrees * M_PI/180;}
+static inline double degrees (double radians) {return radians * 180/M_PI;}
+
+#ifndef __IPHONE_5_0
+#warning "This project uses features only available in iOS SDK 5.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
19 EnterTheMatrix/Enumerations.h
@@ -0,0 +1,19 @@
+//
+// Enumerations.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 2/27/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#ifndef EnterTheMatrix_Enumerations_h
+#define EnterTheMatrix_Enumerations_h
+
+typedef enum {
+ TransformTranslate,
+ TransformScale,
+ TransformRotate
+} TransformOperation;
+
+
+#endif
47 EnterTheMatrix/FlipViewController.h
@@ -0,0 +1,47 @@
+//
+// FlipViewController.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/10/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum {
+ FlipOrientationVertical,
+ FlipOrientationHorizontal
+} FlipOrientation;
+
+typedef enum {
+ FlipDirectionForward,
+ FlipDirectionBackward
+} FlipDirection;
+
+@interface FlipViewController : UIViewController<UIGestureRecognizerDelegate>
+{
+ int currentImage;
+ FlipDirection direction;
+ FlipOrientation orientation;
+
+ BOOL isFlipFrontPage;
+ BOOL isAnimating;
+ BOOL isPanning;
+ CGPoint panStart;
+}
+
+@property (weak, nonatomic) IBOutlet UIView *contentView;
+@property (weak, nonatomic) IBOutlet UIImageView *imageView;
+@property (weak, nonatomic) IBOutlet UISwitch *speedSwitch;
+@property (weak, nonatomic) IBOutlet UISlider *skewSlider;
+@property (weak, nonatomic) IBOutlet UILabel *skewLabel;
+@property (weak, nonatomic) IBOutlet UIView *controlFrame;
+
+@property (strong, nonatomic) UIImageView *pageFront;
+@property (strong, nonatomic) UIImageView *pageBack;
+@property (strong, nonatomic) UIImageView *pageFacing;
+@property (readonly) CGFloat skew;
+
+- (IBAction)skewValueChanged:(id)sender;
+
+@end
548 EnterTheMatrix/FlipViewController.m
@@ -0,0 +1,548 @@
+//
+// FlipViewController.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/10/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "FlipViewController.h"
+#import <QuartzCore/QuartzCore.h>
+#import "MPAnimation.h"
+
+#define IMAGE_COUNT 4
+#define DEFAULT_SKEW -(1. / 1000.)
+#define ANGLE 90
+#define MARGIN 72
+
+#define SWIPE_UP_THRESHOLD -1000.0f
+#define SWIPE_DOWN_THRESHOLD 1000.0f
+#define SWIPE_LEFT_THRESHOLD -1000.0f
+#define SWIPE_RIGHT_THRESHOLD 1000.0f
+
+@interface FlipViewController ()
+
+@end
+
+@implementation FlipViewController
+@synthesize contentView;
+@synthesize imageView;
+@synthesize speedSwitch;
+@synthesize skewSlider;
+@synthesize skewLabel;
+@synthesize controlFrame;
+@synthesize pageFront;
+@synthesize pageBack;
+@synthesize pageFacing;
+
+- (void)doInit
+{
+ direction = FlipDirectionForward;
+ orientation = FlipOrientationVertical;
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self) {
+ // Custom initialization
+ [self doInit];
+ }
+ return self;
+}
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ [self doInit];
+ }
+ return self;
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ self = [super initWithCoder:aDecoder];
+ if (self) {
+ // Custom initialization
+ [self doInit];
+ }
+ return self;
+}
+
+- (void)addDropShadowToView:(UIView *)view
+{
+ view.layer.shadowOpacity = 0.5;
+ view.layer.shadowOffset = CGSizeMake(0, 3);
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+
+ self.controlFrame.layer.cornerRadius = 5;
+ [self addDropShadowToView:self.controlFrame];
+
+ UISwipeGestureRecognizer *left = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
+ left.direction = UISwipeGestureRecognizerDirectionLeft;
+ left.delegate = self;
+ [self.view addGestureRecognizer:left];
+
+ UISwipeGestureRecognizer *right = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
+ right.direction = UISwipeGestureRecognizerDirectionRight;
+ right.delegate = self;
+ [self.view addGestureRecognizer:right];
+
+ UISwipeGestureRecognizer *up = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
+ up.direction = UISwipeGestureRecognizerDirectionUp;
+ up.delegate = self;
+ [self.view addGestureRecognizer:up];
+
+ UISwipeGestureRecognizer *down = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
+ down.direction = UISwipeGestureRecognizerDirectionDown;
+ down.delegate = self;
+ [self.view addGestureRecognizer:down];
+
+ UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
+ [self.contentView addGestureRecognizer:tap];
+
+ UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
+ pan.delegate = self;
+ [self.contentView addGestureRecognizer:pan];
+
+ // drop-shadow for content view
+ [self addDropShadowToView:self.contentView];
+}
+
+- (void)viewDidUnload
+{
+ [self setContentView:nil];
+ [self setImageView:nil];
+ [self setSpeedSwitch:nil];
+ [self setSkewSlider:nil];
+ [self setSkewLabel:nil];
+ [self setControlFrame:nil];
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+#pragma mark - Properties
+
+- (CGFloat)skew
+{
+ return -[[self skewSlider] value];
+}
+
+#pragma mark - Gesture handlers
+
+- (void)handleSwipe:(UIGestureRecognizer *)gestureRecognizer
+{
+ if (isAnimating || isPanning)
+ return;
+
+ UISwipeGestureRecognizer *swipeGesture = (UISwipeGestureRecognizer *)gestureRecognizer;
+
+ switch (swipeGesture.direction)
+ {
+ case UISwipeGestureRecognizerDirectionLeft:
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationHorizontal];
+ break;
+
+ case UISwipeGestureRecognizerDirectionUp:
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationVertical];
+ break;
+
+ case UISwipeGestureRecognizerDirectionRight:
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationHorizontal];
+ break;
+
+ case UISwipeGestureRecognizerDirectionDown:
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationVertical];
+ break;
+ }
+}
+
+- (void)handleTap:(UIGestureRecognizer *)gestureRecognizer
+{
+ if (isAnimating || isPanning)
+ return;
+
+ CGPoint tapPoint = [gestureRecognizer locationInView:self.contentView];
+ if (tapPoint.x <= MARGIN)
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationHorizontal];
+ else if (tapPoint.x >= self.contentView.bounds.size.width - MARGIN)
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationHorizontal];
+ else if (tapPoint.y <= MARGIN)
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationVertical];
+ else if (tapPoint.y >= self.contentView.bounds.size.height - MARGIN)
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationVertical];
+}
+
+- (CGFloat)progressFromPosition:(CGPoint)position
+{
+ // Determine where we are in our page turn animation
+ // 0 - 1 means flipping the front-side of the page
+ // 1 - 2 means flipping the back-side of the page
+ BOOL isForward = (direction == FlipDirectionForward);
+ BOOL isVertical = (orientation == FlipOrientationVertical);
+
+ CGFloat difference = isVertical? position.y - panStart.y : position.x - panStart.x;
+ CGFloat halfWidth = (isVertical? self.contentView.frame.size.height / 2 : self.contentView.frame.size.width / 2);
+ CGFloat progress = difference / halfWidth * (isForward? - 1 : 1);
+ if (progress < 0)
+ progress = 0;
+ if (progress > 2)
+ progress = 2;
+ return progress;
+}
+
+- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer
+{
+ UIGestureRecognizerState state = [gestureRecognizer state];
+ CGPoint currentPosition = [gestureRecognizer locationInView:self.contentView];
+
+ if (state == UIGestureRecognizerStateBegan)
+ {
+ if (isAnimating)
+ return;
+
+ // See if touch started near one of the edges, in which case we'll pan a page turn
+ if (currentPosition.x <= MARGIN)
+ [self startFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationHorizontal];
+ else if (currentPosition.x >= self.contentView.bounds.size.width - MARGIN)
+ [self startFlipWithDirection:FlipDirectionForward orientation:FlipOrientationHorizontal];
+ else if (currentPosition.y <= MARGIN)
+ [self startFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationVertical];
+ else if (currentPosition.y >= self.contentView.bounds.size.height - MARGIN)
+ [self startFlipWithDirection:FlipDirectionForward orientation:FlipOrientationVertical];
+ else
+ {
+ // Do nothing for now, but it might become a swipe later
+ return;
+ }
+
+ isAnimating = YES;
+ isPanning = YES;
+ panStart = currentPosition;
+ }
+
+ if (isPanning && state == UIGestureRecognizerStateChanged)
+ {
+ CGFloat progress = [self progressFromPosition:currentPosition];
+ BOOL wasFlipFrontPage = isFlipFrontPage;
+ isFlipFrontPage = progress < 1;
+ if (wasFlipFrontPage != isFlipFrontPage)
+ {
+ // switching between the 2 halves of the animation - between front and back sides of the page we're turning
+ if (isFlipFrontPage)
+ {
+ [self doFlip2:0];
+ }
+ [self.pageFront setHidden:!isFlipFrontPage];
+ [self.pageBack setHidden:isFlipFrontPage];
+ }
+ if (isFlipFrontPage)
+ [self doFlip1:progress];
+ else
+ [self doFlip2:progress - 1];
+ }
+
+ if (state == UIGestureRecognizerStateEnded)
+ {
+ CGPoint vel = [gestureRecognizer velocityInView:gestureRecognizer.view];
+
+ if (isPanning)
+ {
+ // If moving slowly, let page fall either forward or back depending on where we were
+ BOOL shouldFallBack = isFlipFrontPage;
+
+ // But, if user was swiping in an appropriate direction, go ahead and honor that
+ if (orientation == FlipOrientationHorizontal)
+ {
+ if (vel.x < SWIPE_LEFT_THRESHOLD)
+ {
+ // Detected a swipe to the left
+ shouldFallBack = direction != FlipDirectionForward;
+ }
+ else if (vel.x > SWIPE_RIGHT_THRESHOLD)
+ {
+ // Detected a swipe to the right
+ shouldFallBack = direction == FlipDirectionForward;
+ }
+ }
+ else
+ {
+ if (vel.y < SWIPE_UP_THRESHOLD)
+ {
+ // Detected a swipe up
+ shouldFallBack = direction != FlipDirectionForward;
+ }
+ else if (vel.y > SWIPE_DOWN_THRESHOLD)
+ {
+ // Detected a swipe down
+ shouldFallBack = direction == FlipDirectionForward;
+ }
+ }
+
+ // finishAnimation
+ if (shouldFallBack != isFlipFrontPage)
+ {
+ // 2-stage animation (we're swiping either forward or back)
+ // We'll pro-rate the delay for the first half of the animation based on our current position
+ CGFloat progress = [self progressFromPosition:currentPosition];
+ if ((isFlipFrontPage && progress > 1) || (!isFlipFrontPage && progress < 1))
+ progress = 1;
+ NSTimeInterval duration = (isFlipFrontPage? (1- progress) : (progress - 1)) * 0.5 * ([self.speedSwitch isOn]? 1 : 5);
+
+ [UIView animateWithDuration:duration delay:0 options:UIViewAnimationCurveLinear animations:^{
+ // animate up to middle position
+ if (shouldFallBack)
+ [self doFlip2:0];
+ else
+ [self doFlip1:1];
+ } completion:^(BOOL finished) {
+ // run the 2nd half of the animation
+ isFlipFrontPage = shouldFallBack;
+ self.pageFront.hidden = !shouldFallBack;
+ self.pageBack.hidden = shouldFallBack;
+
+ [UIView animateWithDuration:[self.speedSwitch isOn]? 0.5 : 2.5 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
+ if (shouldFallBack)
+ [self doFlip1:0];
+ else
+ [self doFlip2:1];
+ } completion:^(BOOL finished) {
+
+ [self endFlip:!shouldFallBack];
+
+ // Clear flags
+ isAnimating = NO;
+ isPanning = NO;
+ }];
+ }];
+ }
+ else
+ {
+ // 1-stage animation
+ [UIView animateWithDuration:[self.speedSwitch isOn]? 0.5 : 2.5 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
+ if (shouldFallBack)
+ [self doFlip1:0];
+ else
+ [self doFlip2:1];
+ } completion:^(BOOL finished) {
+
+ [self endFlip:!shouldFallBack];
+
+ // Clear flags
+ isAnimating = NO;
+ isPanning = NO;
+ }];
+ }
+ }
+ else if (!isAnimating)
+ {
+ // we weren't panning (because touch didn't start near any margin) but test for swipe
+ if (vel.x < SWIPE_LEFT_THRESHOLD)
+ {
+ // Detected a swipe to the left
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationHorizontal];
+ }
+ else if (vel.x > SWIPE_RIGHT_THRESHOLD)
+ {
+ // Detected a swipe to the right
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationHorizontal];
+ }
+ else if (vel.y < SWIPE_UP_THRESHOLD)
+ {
+ // TODO: Detected a swipe up
+ [self performFlipWithDirection:FlipDirectionForward orientation:FlipOrientationVertical];
+ }
+ else if (vel.y > SWIPE_DOWN_THRESHOLD)
+ {
+ // TODO: Detected a swipe down
+ [self performFlipWithDirection:FlipDirectionBackward orientation:FlipOrientationVertical];
+ }
+ }
+ }
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+ // don't recognize any further gestures if we're in the middle of animating a page-turn
+ if (isAnimating)
+ return NO;
+
+ // don't recognize swipe on a slider!
+ return ![touch.view isKindOfClass:[UISlider class]];
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
+{
+ // Allow simultanoues pan & swipe recognizers
+ return YES;
+}
+
+#pragma mark - Animation
+
+- (UIImage *)currentImage
+{
+ return [UIImage imageNamed:[NSString stringWithFormat:@"matrix_%02d", currentImage + 1]];
+}
+
+- (UIImage *)prevImage
+{
+ int prevIndex = (currentImage + (IMAGE_COUNT - 1)) % IMAGE_COUNT;
+ return [UIImage imageNamed:[NSString stringWithFormat:@"matrix_%02d", prevIndex + 1]];
+}
+
+- (UIImage *)nextImage
+{
+ int nextIndex = (currentImage + 1) % IMAGE_COUNT;
+ return [UIImage imageNamed:[NSString stringWithFormat:@"matrix_%02d", nextIndex + 1]];
+}
+
+- (void)performFlipWithDirection:(FlipDirection)aDirection orientation:(FlipOrientation)anOrientation
+{
+ isAnimating = YES;
+ [self startFlipWithDirection:aDirection orientation:anOrientation];
+
+ [UIView animateWithDuration:[self.speedSwitch isOn]? 0.5 : 2.5 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
+
+ [self doFlip1:1.0];
+
+ } completion:^(BOOL finished) {
+ isFlipFrontPage = NO;
+ self.pageFront.hidden = YES;
+ self.pageBack.hidden = NO;
+ [UIView animateWithDuration:[self.speedSwitch isOn]? 0.5 : 2.5 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
+
+ [self doFlip2:1.0];
+
+ } completion:^(BOOL finished) {
+ [self endFlip:YES];
+ isAnimating = NO;
+ }];
+ }];
+}
+
+- (void)startFlipWithDirection:(FlipDirection)aDirection orientation:(FlipOrientation)anOrientation
+{
+ direction = aDirection;
+ orientation = anOrientation;
+ isFlipFrontPage = YES;
+
+ BOOL isForward = (direction == FlipDirectionForward);
+ BOOL isVertical = (orientation == FlipOrientationVertical);
+
+ UIImage *next = isForward? [self nextImage] : [self prevImage];
+ CGRect rect = self.contentView.bounds;
+ CGRect half1Rect = rect;
+ if (orientation == FlipOrientationVertical)
+ half1Rect.size.height = rect.size.height / 2;
+ else
+ half1Rect.size.width = rect.size.width / 2;
+ CGRect half2Rect = half1Rect;
+ if (orientation == FlipOrientationVertical)
+ half2Rect.origin.y = half1Rect.size.height;
+ else
+ half2Rect.origin.x = half1Rect.size.width;
+
+ self.pageFront = [[UIImageView alloc] initWithImage:[MPAnimation renderImageFromView:self.contentView withRect:isForward? half2Rect : half1Rect]];
+ self.pageFacing = [[UIImageView alloc] initWithImage:[MPAnimation renderImageFromView:self.contentView withRect:isForward? half1Rect : half2Rect]];
+
+ self.imageView.image = next;
+
+ self.pageBack = [[UIImageView alloc] initWithImage:[MPAnimation renderImageFromView:self.contentView withRect:isForward? half1Rect : half2Rect]];
+ self.pageBack.hidden = YES;
+
+ half1Rect = [self.view convertRect:half1Rect fromView:self.contentView];
+ half2Rect = [self.view convertRect:half2Rect fromView:self.contentView];
+
+ half1Rect = CGRectOffset(half1Rect, isVertical? 0 : half1Rect.size.width/2, isVertical? half1Rect.size.height/2 : 0);
+ half2Rect = CGRectOffset(half2Rect, isVertical? 0 : -half1Rect.size.width/2, isVertical? -half1Rect.size.height/2 : 0);
+ self.pageFront.frame = isForward? half2Rect : half1Rect;
+ self.pageBack.frame = isForward? half1Rect : half2Rect;
+ self.pageFacing.frame = isForward? half1Rect : half2Rect;
+
+ // set anchor point to be along center spine (bottom edge of top half/top edge of bottom half/right edge of left half/left edge of right half)
+ self.pageFront.layer.anchorPoint = isVertical? CGPointMake(0.5, isForward? 0 : 1) : CGPointMake(isForward? 0 : 1, 0.5);
+ self.pageBack.layer.anchorPoint = isVertical? CGPointMake(0.5, isForward? 1 : 0) : CGPointMake(isForward? 1 : 0, 0.5);
+ self.pageFacing.layer.anchorPoint = self.pageBack.layer.anchorPoint;
+
+ [self.view addSubview:pageFront];
+ [self.view addSubview:pageFacing];
+ [self.view addSubview:pageBack ];
+
+ // set shadows on the 2 pages we'll be animating
+ self.pageFront.layer.shadowOpacity = 0.5;
+ self.pageFront.layer.shadowRadius = 1;
+ self.pageFront.layer.shadowOffset = isVertical? CGSizeMake(0, isForward? 1 : -1) : CGSizeMake(isForward? 1 : -1, 0);
+ self.pageBack.layer.shadowOpacity = 0.5;
+ self.pageBack.layer.shadowRadius = 1;
+ self.pageBack.layer.shadowOffset = isVertical? CGSizeMake(0, isForward? -1 : 1) : CGSizeMake(isForward? -1 : 1, 0);
+
+ // set the back page in the vertical position (midpoint of animation)
+ [self doFlip2:0];
+}
+
+ - (void)doFlip1:(CGFloat)progress
+{
+ BOOL isForward = (direction == FlipDirectionForward);
+ BOOL isVertical = (orientation == FlipOrientationVertical);
+ CATransform3D tHalf1 = CATransform3DIdentity;
+ tHalf1.m34 = [self skew] * sinf(radians(90 * progress));
+ tHalf1 = CATransform3DRotate(tHalf1, radians(ANGLE * progress * (isForward? -1 : 1)), isVertical? -1 : 0, isVertical? 0 : 1, 0); // rotate away from viewer
+ self.pageFront.layer.transform = tHalf1;
+}
+
+ - (void)doFlip2:(CGFloat)progress
+{
+ BOOL isForward = (direction == FlipDirectionForward);
+ BOOL isVertical = (orientation == FlipOrientationVertical);
+ CATransform3D tHalf2 = CATransform3DIdentity;
+ tHalf2.m34 = [self skew] * cosf(radians(90 * progress));
+ tHalf2 = CATransform3DRotate(tHalf2, radians(ANGLE * (1 - progress)) * (isForward? 1 : -1), isVertical? -1 : 0, isVertical? 0 : 1, 0); // rotate away from viewer
+ self.pageBack.layer.transform = tHalf2;
+}
+
+- (void)endFlip:(BOOL)completed
+{
+ [self.pageFront removeFromSuperview];
+ [self.pageBack removeFromSuperview];
+ [self.pageFacing removeFromSuperview];
+ self.pageFront = nil;
+ self.pageBack = nil;
+ self.pageFacing = nil;
+
+ if (completed)
+ {
+ if (direction == FlipDirectionForward)
+ currentImage++;
+ else
+ currentImage += IMAGE_COUNT - 1;
+
+ currentImage = currentImage % IMAGE_COUNT;
+ }
+ else
+ self.imageView.image = [self currentImage];
+
+ [self.imageView setHidden:NO];
+}
+
+#pragma mark - Slider
+
+- (IBAction)skewValueChanged:(id)sender {
+ UISlider *slider = sender;
+ self.skewLabel.text = [NSString stringWithFormat:@"%.04f", slider.value];
+}
+
+@end
42 EnterTheMatrix/FoldViewController.h
@@ -0,0 +1,42 @@
+//
+// FoldViewController.h
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/8/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum
+{
+ SkewModeIn,
+ SkewModeNone,
+ SkewModeOut
+} SkewMode;
+
+@interface FoldViewController : UIViewController
+{
+ BOOL folded;
+
+ CGFloat pinchStartGap;
+ CGFloat lastProgress;
+}
+
+@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
+@property (weak, nonatomic) IBOutlet UIView *contentView;
+@property (weak, nonatomic) IBOutlet UIView *topBar;
+@property (weak, nonatomic) IBOutlet UIView *centerBar;
+@property (weak, nonatomic) IBOutlet UIView *bottomBar;
+@property (weak, nonatomic) IBOutlet UISegmentedControl *skewSegment;
+@property (weak, nonatomic) IBOutlet UIView *controlFrame;
+
+@property (strong, nonatomic) UIImageView *foldTop;
+@property (strong, nonatomic) UIImageView *foldBottom;
+
+@property (readonly) CGFloat skew;
+@property (readonly) CGFloat skewAngle;
+
+- (void)handlePinch:(UIGestureRecognizer *)gestureRecognizer;
+
+@end
284 EnterTheMatrix/FoldViewController.m
@@ -0,0 +1,284 @@
+//
+// FoldViewController.m
+// EnterTheMatrix
+//
+// Created by Mark Pospesel on 3/8/12.
+// Copyright (c) 2012 Mark Pospesel. All rights reserved.
+//
+
+#import "FoldViewController.h"
+#import <QuartzCore/QuartzCore.h>
+#import "MPAnimation.h"
+
+#define FOLD_HEIGHT 120.
+#define DEFAULT_SKEW -(1. / 500.)
+#define SKEW_ANGLE_OFFSET 7
+
+@interface FoldViewController ()
+
+@end
+
+@implementation FoldViewController
+@synthesize scrollView;
+@synthesize contentView;
+@synthesize topBar;
+@synthesize centerBar;
+@synthesize bottomBar;
+@synthesize skewSegment;
+@synthesize controlFrame;
+@synthesize foldBottom;
+@synthesize foldTop;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+
+ self.controlFrame.layer.cornerRadius = 5;
+ [self setDropShadow:self.controlFrame];
+ [self setDropShadow:self.topBar];
+ [self setDropShadow:self.centerBar];
+ [self setDropShadow:self.bottomBar];
+
+ // Add our pinch gesture recognizer
+ UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
+ [self.view addGestureRecognizer:pinchGesture];
+
+ // We want to split the center bar in 2 and create 2 images from it- these will be our folding halves
+
+ // Calculate the 2 rects
+ CGRect barRect = self.centerBar.bounds;
+ CGRect topRect = barRect;
+ topRect.size.height = barRect.size.height / 2;
+ CGRect bottomRect = topRect;
+ bottomRect.origin.y = topRect.size.height;
+
+ // paint the images from the view
+ UIImage *topImage = [MPAnimation renderImageFromView:self.centerBar withRect:topRect];
+ UIImage *bottomImage = [MPAnimation renderImageFromView:self.centerBar withRect:bottomRect];
+
+ // create UIImageView's to hold the images
+ [self setFoldTop: [[UIImageView alloc] initWithImage:topImage]];
+ self.foldTop.frame = topRect;
+ self.foldTop.layer.anchorPoint = CGPointMake(0.5, 0); // anchor at top
+ [self setFoldBottom:[[UIImageView alloc] initWithImage:bottomImage]];
+ self.foldBottom.frame = bottomRect;
+ self.foldBottom.layer.anchorPoint = CGPointMake(0.5, 1); // anchor at bottom
+ [self setDropShadow:self.foldTop];
+ [self setDropShadow:self.foldBottom];
+}
+
+- (void)viewDidUnload
+{
+ [self setScrollView:nil];
+ [self setContentView:nil];
+ [self setTopBar:nil];
+ [self setCenterBar:nil];
+ [self setBottomBar:nil];
+ [self setFoldTop:nil];
+ [self setFoldBottom:nil];
+ [self setSkewSegment:nil];
+ [self setControlFrame:nil];
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+#pragma mark - Properties
+
+- (CGFloat)skew
+{
+ switch ((SkewMode)[self.skewSegment selectedSegmentIndex])
+ {
+ case SkewModeIn:
+ return DEFAULT_SKEW;
+
+ case SkewModeNone:
+ return 0;
+
+ case SkewModeOut:
+ return -DEFAULT_SKEW;
+ }
+}
+
+- (CGFloat)skewAngle
+{
+ switch ((SkewMode)[self.skewSegment selectedSegmentIndex])
+ {
+ case SkewModeIn:
+ return 90 - SKEW_ANGLE_OFFSET;
+
+ case SkewModeNone:
+ return 90;
+
+ case SkewModeOut:
+ return 90 + SKEW_ANGLE_OFFSET;
+ }
+}
+
+#pragma mark - methods
+
+- (void)setDropShadow:(UIView *)view
+{
+ view.layer.shadowOpacity = 0.5;
+ view.layer.shadowOffset = CGSizeMake(0, 1);
+}
+
+#pragma mark - Gesture handlers
+
+- (void)handlePinch:(UIPinchGestureRecognizer *)gestureRecognizer {
+ UIGestureRecognizerState state = [gestureRecognizer state];
+
+ CGFloat currentGap = pinchStartGap;
+ if (state != UIGestureRecognizerStateEnded && gestureRecognizer.numberOfTouches == 2)
+ {
+ CGPoint p1 = [gestureRecognizer locationOfTouch:0 inView:self.view];
+ CGPoint p2 = [gestureRecognizer locationOfTouch:1 inView:self.view];
+ currentGap = fabsf(p1.y - p2.y);
+ }
+
+ if (state == UIGestureRecognizerStateBegan)
+ {
+ pinchStartGap = currentGap;
+ [self startFold];
+ }
+
+ if (state == UIGestureRecognizerStateEnded)
+ {
+ [self endFold];
+ }
+ else if (state == UIGestureRecognizerStateChanged && gestureRecognizer.numberOfTouches == 2)
+ {
+ if (folded)
+ {
+ // pinching out, want + diff
+ if (currentGap < pinchStartGap)
+ currentGap = pinchStartGap; // min
+
+ if (currentGap > pinchStartGap + FOLD_HEIGHT)
+ currentGap = pinchStartGap + FOLD_HEIGHT; // max
+ }
+ else
+ {
+ // pinching in, want - diff
+ if (currentGap < pinchStartGap - FOLD_HEIGHT)
+ currentGap = pinchStartGap - FOLD_HEIGHT; // min
+
+ if (currentGap > pinchStartGap)
+ currentGap = pinchStartGap; // max
+ }
+
+ [self doFold:currentGap - pinchStartGap];
+ }
+}
+
+#pragma mark - Animations
+
+- (void)startFold
+{
+ // replace the center bar with the 2 image halves
+ CGRect barRect = self.centerBar.frame;//[self.contentView convertRect:self.centerBar.frame fromView:self.centerBar];
+ CGRect topRect = barRect;
+ topRect.size.height = barRect.size.height / 2;
+ CGRect bottomRect = topRect;
+ bottomRect.origin.y += topRect.size.height;
+
+ self.foldTop.frame = topRect;
+ self.foldBottom.frame = bottomRect;
+
+ [self.contentView insertSubview:foldTop belowSubview:self.topBar];
+ [self.contentView insertSubview:foldBottom belowSubview:self.bottomBar];
+
+ [self.centerBar setHidden:YES];
+}
+
+- (void)doFold:(CGFloat)difference
+{
+ CGFloat progress = fabsf(difference) / FOLD_HEIGHT;
+ if (progress == lastProgress)
+ return;
+ lastProgress = progress;
+ if (folded)
+ progress = 1-progress;
+
+ //self.topBar.transform = CGAffineTransformMakeTranslation(0, -difference/2);
+ //self.bottomBar.transform = CGAffineTransformMakeTranslation(0, difference/2);
+
+ // We need to move the folding flaps towards the center based on the cosine of the angle of our fold
+ // Basically what this does is keep the bottom of the top fold (and top of the bottom fold) anchored to the midpoint.
+ CGFloat cosine = cosf(radians(90 * progress));
+ CGFloat verticalOffset = (FOLD_HEIGHT / 2) * (1- cosine); // how much to offset each panel by
+
+ // move the top and bottom panels towards the center
+ self.topBar.transform = CGAffineTransformMakeTranslation(0, verticalOffset);
+ self.bottomBar.transform = CGAffineTransformMakeTranslation(0, -verticalOffset);
+
+ // fold the top and bottom halves of the center panel away from us
+ CATransform3D tTop = CATransform3DIdentity;
+ tTop.m34 = [self skew] * progress;
+ tTop = CATransform3DTranslate(tTop, 0, verticalOffset, 0); // shift panel towards center
+ tTop = CATransform3DRotate(tTop, radians([self skewAngle] * progress), -1, 0, 0); // rotate away from viewer
+ self.foldTop.layer.transform = tTop;
+
+ CATransform3D tBottom = CATransform3DIdentity;
+ tBottom.m34 = [self skew] * progress;
+ tBottom = CATransform3DTranslate(tBottom, 0, -verticalOffset, 0); // shift panel towards center
+ tBottom = CATransform3DRotate(tBottom, radians(-[self skewAngle] * progress), -1, 0, 0); // rotate away from viewer
+ self.foldBottom.layer.transform = tBottom;
+}
+
+- (void)endFold
+{
+ BOOL finish = NO;
+ if (folded)
+ {
+ finish = 1 - cosf(radians(90 * (1-lastProgress))) <= 0.5;
+ }
+ else
+ {
+ finish = 1 - cosf(radians(90 * lastProgress)) >= 0.5;
+ }
+
+ [UIView animateWithDuration:0.3 animations:^{
+ if (finish)
+ {
+ [self doFold:FOLD_HEIGHT];
+ }
+ else
+ {
+ [self doFold:0];
+ }
+ } completion:^(BOOL finished) {
+
+ if (finish)
+ folded = !folded;
+
+ // remove the 2 image halves and restore the center bar
+ [foldTop removeFromSuperview];
+ [foldBottom re