├── .gitignore ├── README.md ├── fiatlux.xcodeproj └── project.pbxproj └── fiatlux ├── AppDelegate.h ├── AppDelegate.m ├── SMShadowedLayer.h ├── SMShadowedLayer.m ├── SMTransformLayer.h ├── SMTransformLayer.m ├── ViewController.h ├── ViewController.m ├── en.lproj ├── InfoPlist.strings └── ViewController.xib ├── fiatlux-Info.plist ├── fiatlux-Prefix.pch ├── logo_periwinkle.png └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | A CALayer subclass with an approximation of Lambert shading and specular highlighting. Provides the graphical glory of a very basic lighting model combined with the relatively heavy-weight Core Animation object model. This yields visual results that are hard to achieve in Core Animation, seamlessly integrated with the ease of animation that is so hard to achieve in OpenGL. 5 | 6 | In short: a layer with shininess and shadowing. 7 | 8 | There's a blog post with slightly more detail here: [http://www.ultrajoke.net/2012/03/smshadowedlayer/](http://www.ultrajoke.net/2012/03/smshadowedlayer/) 9 | 10 | HOW IT WORKS 11 | ------------ 12 | 13 | When a transform is set on this layer, it does a little math to determine how close its normal is to the direction of incident light (which is assumed to be at the viewer's eye, at least for this release). It renders a shadow with linear falloff, and a specular highlight with exponential falloff. It also does a little internal jiggery-pokery to change color values on a per-frame basis, rather than depending on the provided implicit animations. This matters e.g. when the layer rotates from facing left to facing right, passing through facing forward. 14 | 15 | HOW TO USE IT 16 | ------------- 17 | 18 | Use as you would any other CALayer. Set background color, contents, and so on, and position in your scene. It comes with reasonable defaults (shadow on, highlight off, full shadow color black with 75% opacity), but is fully customizable, from colors to the exponential falloff rate of the specular highlight. When a transform is applied, it will do the right thing for you. If you know the animation from the current transform to the new one won't involve a non-linear change in the layer's orientation to the screen, using `[layer setTransform:transform animatePerFrame:NO]` will save some CPU cycles. 19 | 20 | The shadow and specular properties can also be used to fake other effects, such as the layer being shadowed by something above it. Simply set the currentShadowOpacity or currentSpecularOpacity. Note that subsequently transforming the layer will reset these as per the animation. 21 | 22 | The project includes an optional CATransformLayer subclass that's aware of the shadowed layer's unique properties. If you use SMTransformLayer to contain SMShadowedLayers, they will behave as expected. If you prefer to use CATransformLayer, you'll have to call `[layer setTransform:layer.transform animatePerFrame:YES]` in any transaction in which you change the transform layer's `transform` or `sublayerTransform` properties. 23 | 24 | LICENSE 25 | ------- 26 | 27 | Copyright (C) 2012 by Spaceman Labs 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy 30 | of this software and associated documentation files (the "Software"), to deal 31 | in the Software without restriction, including without limitation the rights 32 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | copies of the Software, and to permit persons to whom the Software is 34 | furnished to do so, subject to the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be included in 37 | all copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 | THE SOFTWARE. 46 | -------------------------------------------------------------------------------- /fiatlux.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6B7D5FBF15117F0500DE17EE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B7D5FBE15117F0500DE17EE /* UIKit.framework */; }; 11 | 6B7D5FC115117F0500DE17EE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B7D5FC015117F0500DE17EE /* Foundation.framework */; }; 12 | 6B7D5FC315117F0500DE17EE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B7D5FC215117F0500DE17EE /* CoreGraphics.framework */; }; 13 | 6B7D5FC915117F0500DE17EE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6B7D5FC715117F0500DE17EE /* InfoPlist.strings */; }; 14 | 6B7D5FCB15117F0500DE17EE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7D5FCA15117F0500DE17EE /* main.m */; }; 15 | 6B7D5FCF15117F0500DE17EE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7D5FCE15117F0500DE17EE /* AppDelegate.m */; }; 16 | 6B7D5FD215117F0500DE17EE /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7D5FD115117F0500DE17EE /* ViewController.m */; }; 17 | 6B7D5FD515117F0500DE17EE /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6B7D5FD315117F0500DE17EE /* ViewController.xib */; }; 18 | 6B7D5FDE1511808700DE17EE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B7D5FDD1511808700DE17EE /* QuartzCore.framework */; }; 19 | 6B7D5FDF1511809800DE17EE /* SMShadowedLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7D5FDC15117F2C00DE17EE /* SMShadowedLayer.m */; }; 20 | 6B7D5FFC151298AE00DE17EE /* logo_periwinkle.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B7D5FFB151298AE00DE17EE /* logo_periwinkle.png */; }; 21 | 6B7D60A315191F4500DE17EE /* SMTransformLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7D60A215191F4500DE17EE /* SMTransformLayer.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | 6B7D5FBA15117F0500DE17EE /* fiatlux.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fiatlux.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 6B7D5FBE15117F0500DE17EE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 27 | 6B7D5FC015117F0500DE17EE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | 6B7D5FC215117F0500DE17EE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | 6B7D5FC615117F0500DE17EE /* fiatlux-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "fiatlux-Info.plist"; sourceTree = ""; }; 30 | 6B7D5FC815117F0500DE17EE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 31 | 6B7D5FCA15117F0500DE17EE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | 6B7D5FCC15117F0500DE17EE /* fiatlux-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "fiatlux-Prefix.pch"; sourceTree = ""; }; 33 | 6B7D5FCD15117F0500DE17EE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 34 | 6B7D5FCE15117F0500DE17EE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 35 | 6B7D5FD015117F0500DE17EE /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 36 | 6B7D5FD115117F0500DE17EE /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 37 | 6B7D5FD415117F0500DE17EE /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 38 | 6B7D5FDB15117F2C00DE17EE /* SMShadowedLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SMShadowedLayer.h; sourceTree = ""; }; 39 | 6B7D5FDC15117F2C00DE17EE /* SMShadowedLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SMShadowedLayer.m; sourceTree = ""; }; 40 | 6B7D5FDD1511808700DE17EE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 41 | 6B7D5FFB151298AE00DE17EE /* logo_periwinkle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo_periwinkle.png; sourceTree = ""; }; 42 | 6B7D60A115191F4500DE17EE /* SMTransformLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMTransformLayer.h; sourceTree = ""; }; 43 | 6B7D60A215191F4500DE17EE /* SMTransformLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMTransformLayer.m; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 6B7D5FB715117F0500DE17EE /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | 6B7D5FDE1511808700DE17EE /* QuartzCore.framework in Frameworks */, 52 | 6B7D5FBF15117F0500DE17EE /* UIKit.framework in Frameworks */, 53 | 6B7D5FC115117F0500DE17EE /* Foundation.framework in Frameworks */, 54 | 6B7D5FC315117F0500DE17EE /* CoreGraphics.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 6B7D5FAF15117F0500DE17EE = { 62 | isa = PBXGroup; 63 | children = ( 64 | 6B7D5FDD1511808700DE17EE /* QuartzCore.framework */, 65 | 6B7D5FC415117F0500DE17EE /* fiatlux */, 66 | 6B7D5FBD15117F0500DE17EE /* Frameworks */, 67 | 6B7D5FBB15117F0500DE17EE /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | 6B7D5FBB15117F0500DE17EE /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 6B7D5FBA15117F0500DE17EE /* fiatlux.app */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | 6B7D5FBD15117F0500DE17EE /* Frameworks */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 6B7D5FBE15117F0500DE17EE /* UIKit.framework */, 83 | 6B7D5FC015117F0500DE17EE /* Foundation.framework */, 84 | 6B7D5FC215117F0500DE17EE /* CoreGraphics.framework */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | 6B7D5FC415117F0500DE17EE /* fiatlux */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 6B7D5FCD15117F0500DE17EE /* AppDelegate.h */, 93 | 6B7D5FCE15117F0500DE17EE /* AppDelegate.m */, 94 | 6B7D5FD015117F0500DE17EE /* ViewController.h */, 95 | 6B7D5FD115117F0500DE17EE /* ViewController.m */, 96 | 6B7D5FDB15117F2C00DE17EE /* SMShadowedLayer.h */, 97 | 6B7D5FDC15117F2C00DE17EE /* SMShadowedLayer.m */, 98 | 6B7D60A115191F4500DE17EE /* SMTransformLayer.h */, 99 | 6B7D60A215191F4500DE17EE /* SMTransformLayer.m */, 100 | 6B7D5FD315117F0500DE17EE /* ViewController.xib */, 101 | 6B7D5FC515117F0500DE17EE /* Supporting Files */, 102 | ); 103 | path = fiatlux; 104 | sourceTree = ""; 105 | }; 106 | 6B7D5FC515117F0500DE17EE /* Supporting Files */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 6B7D5FFB151298AE00DE17EE /* logo_periwinkle.png */, 110 | 6B7D5FC615117F0500DE17EE /* fiatlux-Info.plist */, 111 | 6B7D5FC715117F0500DE17EE /* InfoPlist.strings */, 112 | 6B7D5FCA15117F0500DE17EE /* main.m */, 113 | 6B7D5FCC15117F0500DE17EE /* fiatlux-Prefix.pch */, 114 | ); 115 | name = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | /* End PBXGroup section */ 119 | 120 | /* Begin PBXNativeTarget section */ 121 | 6B7D5FB915117F0500DE17EE /* fiatlux */ = { 122 | isa = PBXNativeTarget; 123 | buildConfigurationList = 6B7D5FD815117F0500DE17EE /* Build configuration list for PBXNativeTarget "fiatlux" */; 124 | buildPhases = ( 125 | 6B7D5FB615117F0500DE17EE /* Sources */, 126 | 6B7D5FB715117F0500DE17EE /* Frameworks */, 127 | 6B7D5FB815117F0500DE17EE /* Resources */, 128 | ); 129 | buildRules = ( 130 | ); 131 | dependencies = ( 132 | ); 133 | name = fiatlux; 134 | productName = fiatlux; 135 | productReference = 6B7D5FBA15117F0500DE17EE /* fiatlux.app */; 136 | productType = "com.apple.product-type.application"; 137 | }; 138 | /* End PBXNativeTarget section */ 139 | 140 | /* Begin PBXProject section */ 141 | 6B7D5FB115117F0500DE17EE /* Project object */ = { 142 | isa = PBXProject; 143 | attributes = { 144 | LastUpgradeCheck = 0430; 145 | ORGANIZATIONNAME = "Spaceman Labs"; 146 | }; 147 | buildConfigurationList = 6B7D5FB415117F0500DE17EE /* Build configuration list for PBXProject "fiatlux" */; 148 | compatibilityVersion = "Xcode 3.2"; 149 | developmentRegion = English; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | ); 154 | mainGroup = 6B7D5FAF15117F0500DE17EE; 155 | productRefGroup = 6B7D5FBB15117F0500DE17EE /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 6B7D5FB915117F0500DE17EE /* fiatlux */, 160 | ); 161 | }; 162 | /* End PBXProject section */ 163 | 164 | /* Begin PBXResourcesBuildPhase section */ 165 | 6B7D5FB815117F0500DE17EE /* Resources */ = { 166 | isa = PBXResourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 6B7D5FC915117F0500DE17EE /* InfoPlist.strings in Resources */, 170 | 6B7D5FD515117F0500DE17EE /* ViewController.xib in Resources */, 171 | 6B7D5FFC151298AE00DE17EE /* logo_periwinkle.png in Resources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXSourcesBuildPhase section */ 178 | 6B7D5FB615117F0500DE17EE /* Sources */ = { 179 | isa = PBXSourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 6B7D5FCB15117F0500DE17EE /* main.m in Sources */, 183 | 6B7D5FCF15117F0500DE17EE /* AppDelegate.m in Sources */, 184 | 6B7D5FD215117F0500DE17EE /* ViewController.m in Sources */, 185 | 6B7D5FDF1511809800DE17EE /* SMShadowedLayer.m in Sources */, 186 | 6B7D60A315191F4500DE17EE /* SMTransformLayer.m in Sources */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXSourcesBuildPhase section */ 191 | 192 | /* Begin PBXVariantGroup section */ 193 | 6B7D5FC715117F0500DE17EE /* InfoPlist.strings */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | 6B7D5FC815117F0500DE17EE /* en */, 197 | ); 198 | name = InfoPlist.strings; 199 | sourceTree = ""; 200 | }; 201 | 6B7D5FD315117F0500DE17EE /* ViewController.xib */ = { 202 | isa = PBXVariantGroup; 203 | children = ( 204 | 6B7D5FD415117F0500DE17EE /* en */, 205 | ); 206 | name = ViewController.xib; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXVariantGroup section */ 210 | 211 | /* Begin XCBuildConfiguration section */ 212 | 6B7D5FD615117F0500DE17EE /* Debug */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 217 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 218 | COPY_PHASE_STRIP = NO; 219 | GCC_C_LANGUAGE_STANDARD = gnu99; 220 | GCC_DYNAMIC_NO_PIC = NO; 221 | GCC_OPTIMIZATION_LEVEL = 0; 222 | GCC_PREPROCESSOR_DEFINITIONS = ( 223 | "DEBUG=1", 224 | "$(inherited)", 225 | ); 226 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 227 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 232 | SDKROOT = iphoneos; 233 | TARGETED_DEVICE_FAMILY = 2; 234 | }; 235 | name = Debug; 236 | }; 237 | 6B7D5FD715117F0500DE17EE /* Release */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 242 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 243 | COPY_PHASE_STRIP = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu99; 245 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 246 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 247 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 250 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 251 | SDKROOT = iphoneos; 252 | TARGETED_DEVICE_FAMILY = 2; 253 | VALIDATE_PRODUCT = YES; 254 | }; 255 | name = Release; 256 | }; 257 | 6B7D5FD915117F0500DE17EE /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | CLANG_ENABLE_OBJC_ARC = YES; 261 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 262 | GCC_PREFIX_HEADER = "fiatlux/fiatlux-Prefix.pch"; 263 | INFOPLIST_FILE = "fiatlux/fiatlux-Info.plist"; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | WRAPPER_EXTENSION = app; 266 | }; 267 | name = Debug; 268 | }; 269 | 6B7D5FDA15117F0500DE17EE /* Release */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | CLANG_ENABLE_OBJC_ARC = YES; 273 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 274 | GCC_PREFIX_HEADER = "fiatlux/fiatlux-Prefix.pch"; 275 | INFOPLIST_FILE = "fiatlux/fiatlux-Info.plist"; 276 | PRODUCT_NAME = "$(TARGET_NAME)"; 277 | WRAPPER_EXTENSION = app; 278 | }; 279 | name = Release; 280 | }; 281 | /* End XCBuildConfiguration section */ 282 | 283 | /* Begin XCConfigurationList section */ 284 | 6B7D5FB415117F0500DE17EE /* Build configuration list for PBXProject "fiatlux" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | 6B7D5FD615117F0500DE17EE /* Debug */, 288 | 6B7D5FD715117F0500DE17EE /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | 6B7D5FD815117F0500DE17EE /* Build configuration list for PBXNativeTarget "fiatlux" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | 6B7D5FD915117F0500DE17EE /* Debug */, 297 | 6B7D5FDA15117F0500DE17EE /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | /* End XCConfigurationList section */ 303 | }; 304 | rootObject = 6B7D5FB115117F0500DE17EE /* Project object */; 305 | } 306 | -------------------------------------------------------------------------------- /fiatlux/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/14/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /fiatlux/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/14/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize viewController = _viewController; 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 20 | { 21 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 22 | // Override point for customization after application launch. 23 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 24 | self.window.rootViewController = self.viewController; 25 | [self.window makeKeyAndVisible]; 26 | return YES; 27 | } 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application 30 | { 31 | // 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. 32 | // 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. 33 | } 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application 36 | { 37 | // 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. 38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application 42 | { 43 | // 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. 44 | } 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application 47 | { 48 | // 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. 49 | } 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application 52 | { 53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /fiatlux/SMShadowedLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMShadowedLayer.h 3 | // 4 | // 5 | // Created by Joel Kraut on 3/13/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Note: subclasses that draw content must call [super display] 12 | @interface SMShadowedLayer : CALayer 13 | 14 | // not animating per frame will yield better performance; however, the shadow 15 | // and highlight will not animate correctly in situations where they'd undergo 16 | // a non-linear animation (e.g. rotating the layer from -M_PI to M_PI) 17 | - (void)setTransform:(CATransform3D)transform animatePerFrame:(BOOL)internalAnimate; 18 | 19 | @property (nonatomic, assign) BOOL showShadow; 20 | @property (nonatomic, strong) UIColor *shadowingColor; 21 | @property (nonatomic, assign) float currentShadowOpacity; 22 | 23 | @property (nonatomic, assign) BOOL showHighlight; 24 | @property (nonatomic, strong) UIColor *specularColor; 25 | @property (nonatomic, assign) float specularFalloff; 26 | @property (nonatomic, assign) float currentSpecularOpacity; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /fiatlux/SMShadowedLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMShadowedLayer.m 3 | // 4 | // 5 | // Created by Joel Kraut on 3/13/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #if ! __has_feature(objc_arc) 10 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 11 | #endif 12 | 13 | #import "SMShadowedLayer.h" 14 | 15 | #import 16 | 17 | @interface SMShadowedLayer() { 18 | CALayer *shadowLayer; 19 | CALayer *specularLayer; 20 | BOOL parentIsTransformLayer; 21 | } 22 | 23 | @property (nonatomic, assign) float _animator; 24 | 25 | - (void)respondToTransform:(CATransform3D)transform; 26 | 27 | @end 28 | 29 | @implementation SMShadowedLayer 30 | 31 | @synthesize shadowingColor, showShadow, 32 | specularColor, specularFalloff, showHighlight; 33 | @dynamic currentShadowOpacity, 34 | currentSpecularOpacity; 35 | 36 | @dynamic _animator; 37 | 38 | #pragma mark - Life cycle 39 | 40 | - (id)init 41 | { 42 | if ((self = [super init])) 43 | { 44 | shadowLayer = [CALayer layer]; 45 | shadowLayer.opacity = 0.f; 46 | [self addSublayer:shadowLayer]; 47 | self.shadowingColor = [UIColor colorWithWhite:0.f alpha:.75f]; 48 | 49 | specularLayer = [CALayer layer]; 50 | specularLayer.opacity = 0.f; 51 | specularLayer.hidden = YES; 52 | [self addSublayer:specularLayer]; 53 | self.specularColor = [UIColor colorWithWhite:1.f alpha:.9f]; 54 | specularFalloff = 64.f; 55 | 56 | showShadow = YES; 57 | showHighlight = NO; 58 | } 59 | return self; 60 | } 61 | 62 | 63 | - (void)addSublayer:(CALayer *)layer 64 | { 65 | [self insertSublayer:layer below:shadowLayer]; 66 | } 67 | 68 | #pragma mark - Reasons to reconstruct the shadow layer's mask 69 | 70 | - (void)setBounds:(CGRect)bounds 71 | { 72 | [super setBounds:bounds]; 73 | shadowLayer.frame = bounds; 74 | shadowLayer.mask = [self constructShadowMask]; 75 | specularLayer.frame = bounds; 76 | specularLayer.mask = [self constructShadowMask]; 77 | } 78 | 79 | - (void)setContents:(id)contents 80 | { 81 | [super setContents:contents]; 82 | shadowLayer.mask = [self constructShadowMask]; 83 | specularLayer.mask = [self constructShadowMask]; 84 | } 85 | 86 | - (void)setContentsCenter:(CGRect)contentsCenter 87 | { 88 | [super setContentsCenter:contentsCenter]; 89 | shadowLayer.mask = [self constructShadowMask]; 90 | specularLayer.mask = [self constructShadowMask]; 91 | } 92 | 93 | - (void)setContentsGravity:(NSString *)contentsGravity 94 | { 95 | [super setContentsGravity:contentsGravity]; 96 | shadowLayer.mask = [self constructShadowMask]; 97 | specularLayer.mask = [self constructShadowMask]; 98 | } 99 | 100 | - (void)setContentsRect:(CGRect)contentsRect 101 | { 102 | [super setContentsRect:contentsRect]; 103 | shadowLayer.mask = [self constructShadowMask]; 104 | specularLayer.mask = [self constructShadowMask]; 105 | } 106 | 107 | - (void)setContentsScale:(CGFloat)contentsScale 108 | { 109 | [super setContentsScale:contentsScale]; 110 | shadowLayer.mask = [self constructShadowMask]; 111 | specularLayer.mask = [self constructShadowMask]; 112 | } 113 | 114 | #pragma mark - Animation triggers 115 | 116 | - (void)setTransform:(CATransform3D)transform 117 | { 118 | [self setTransform:transform animatePerFrame:YES]; 119 | } 120 | 121 | - (void)setTransform:(CATransform3D)transform animatePerFrame:(BOOL)internalAnimate 122 | { 123 | [super setTransform:transform]; 124 | if (internalAnimate) 125 | self._animator = self._animator ? 0.f : 1.f; 126 | [self respondToTransform:transform]; 127 | } 128 | 129 | #pragma mark - Shadow and highlight configuration 130 | 131 | - (void)setShowHighlight:(BOOL)show 132 | { 133 | showHighlight = show; 134 | specularLayer.hidden = !showHighlight; 135 | } 136 | 137 | - (void)setSpecularColor:(UIColor *)color 138 | { 139 | if ([color isEqual:specularColor]) 140 | return; 141 | specularColor = color; 142 | specularLayer.backgroundColor = specularColor.CGColor; 143 | } 144 | 145 | - (float)currentSpecularOpacity 146 | { 147 | return specularLayer.opacity; 148 | } 149 | 150 | - (void)setCurrentSpecularOpacity:(float)currentSpecularOpacity 151 | { 152 | specularLayer.opacity = currentSpecularOpacity; 153 | } 154 | 155 | - (void)setShowShadow:(BOOL)show 156 | { 157 | showShadow = show; 158 | shadowLayer.hidden = !showShadow; 159 | } 160 | 161 | - (void)setShadowingColor:(UIColor *)color 162 | { 163 | if ([color isEqual:shadowingColor]) 164 | return; 165 | shadowingColor = color; 166 | shadowLayer.backgroundColor = shadowingColor.CGColor; 167 | } 168 | 169 | - (float)currentShadowOpacity 170 | { 171 | return shadowLayer.opacity; 172 | } 173 | 174 | - (void)setCurrentShadowOpacity:(float)currentShadowOpacity 175 | { 176 | shadowLayer.opacity = currentShadowOpacity; 177 | } 178 | 179 | #pragma mark - Internal logic 180 | 181 | - (void)display 182 | { 183 | [CATransaction begin]; 184 | [CATransaction setDisableActions:YES]; 185 | [self respondToTransform:((CALayer*)self.presentationLayer).transform]; 186 | [CATransaction commit]; 187 | } 188 | 189 | - (void)respondToTransform:(CATransform3D)transform 190 | { 191 | // add in the parent's transforms 192 | CALayer *superlayer = self.superlayer.presentationLayer; 193 | if (!superlayer) 194 | return; 195 | 196 | transform = CATransform3DConcat(superlayer.sublayerTransform, transform); 197 | if (parentIsTransformLayer) 198 | transform = CATransform3DConcat(superlayer.transform, transform); 199 | CATransform3D normal; 200 | memset(&normal, 0, sizeof(CATransform3D)); 201 | normal.m31 = 1.f; 202 | // get the normal to the transformed surface 203 | CATransform3D newNormal = CATransform3DConcat(transform, normal); 204 | float magnitude = sqrtf(newNormal.m11 * newNormal.m11 + newNormal.m21 * newNormal.m21 + newNormal.m31 * newNormal.m31); 205 | // technically correct, but we don't use the results of these 206 | //newNormal.m11 /= magnitude; 207 | //newNormal.m21 /= magnitude; 208 | newNormal.m31 /= magnitude; 209 | float dotProduct = newNormal.m31; 210 | shadowLayer.opacity = fmaxf(0, fminf(1, (1.f - dotProduct))); 211 | specularLayer.opacity = fmaxf(0, fminf(1, powf(dotProduct, specularFalloff))); 212 | } 213 | 214 | - (CALayer*)constructShadowMask 215 | { 216 | if (!self.contents) 217 | return nil; 218 | CALayer *mask = [CALayer layer]; 219 | mask.frame = shadowLayer.bounds; 220 | mask.contents = self.contents; 221 | mask.contentsRect = self.contentsRect; 222 | mask.contentsCenter = self.contentsCenter; 223 | mask.contentsGravity = self.contentsGravity; 224 | mask.contentsScale = self.contentsScale; 225 | 226 | return mask; 227 | } 228 | 229 | - (id < CAAction >)actionForKey:(NSString *)key 230 | { 231 | // if we're under a transform layer, we also need to account for its transform 232 | if ([key isEqualToString:@"onOrderIn"]) 233 | parentIsTransformLayer = ([self.superlayer isKindOfClass:[CATransformLayer class]]); 234 | 235 | return [super actionForKey:key]; 236 | } 237 | 238 | #pragma mark - Class Methods 239 | 240 | + (BOOL)needsDisplayForKey:(NSString *)key 241 | { 242 | if ([key isEqualToString:@"_animator"]) 243 | return YES; 244 | return [super needsDisplayForKey:key]; 245 | } 246 | 247 | + (id < CAAction >)defaultActionForKey:(NSString *)key 248 | { 249 | if ([key isEqualToString:@"_animator"]) 250 | return [CABasicAnimation animation]; 251 | return [super defaultActionForKey:key]; 252 | } 253 | 254 | @end 255 | -------------------------------------------------------------------------------- /fiatlux/SMTransformLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMTransformLayer.h 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/20/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | // This class exists only to be aware of SM layers that care about transforms. 10 | // If you're not using SMShadowedLayer, you don't need this. 11 | 12 | #import 13 | 14 | @interface SMTransformLayer : CATransformLayer 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /fiatlux/SMTransformLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMTransformLayer.m 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/20/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #if ! __has_feature(objc_arc) 10 | #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). 11 | #endif 12 | 13 | #import "SMTransformLayer.h" 14 | #import "SMShadowedLayer.h" 15 | 16 | @interface SMTransformLayer () 17 | @property (nonatomic, readonly) NSMutableSet *shadowedLayers; 18 | - (void)trackPotentialShadowedLayer:(CALayer*)layer; 19 | - (void)checkSublayersForShadows; 20 | @end 21 | 22 | @implementation SMTransformLayer 23 | @synthesize shadowedLayers; 24 | 25 | 26 | #pragma mark - inform shadowed layer sublayers of our transforms 27 | 28 | - (void)setTransform:(CATransform3D)transform 29 | { 30 | [super setTransform:transform]; 31 | for (SMShadowedLayer *layer in shadowedLayers) 32 | [layer setTransform:layer.transform animatePerFrame:YES]; 33 | } 34 | 35 | - (void)setSublayerTransform:(CATransform3D)sublayerTransform 36 | { 37 | [super setSublayerTransform:sublayerTransform]; 38 | for (SMShadowedLayer *layer in shadowedLayers) 39 | [layer setTransform:layer.transform animatePerFrame:YES]; 40 | } 41 | 42 | #pragma mark - keep track of shadowed layer sublayers 43 | 44 | - (void)trackPotentialShadowedLayer:(CALayer*)layer 45 | { 46 | if ([layer isKindOfClass:[SMShadowedLayer class]]) 47 | [self.shadowedLayers addObject:layer]; 48 | } 49 | 50 | - (void)checkSublayersForShadows 51 | { 52 | for (CALayer *layer in self.sublayers) 53 | [self trackPotentialShadowedLayer:layer]; 54 | [shadowedLayers intersectSet:[NSSet setWithArray:self.sublayers]]; 55 | } 56 | 57 | - (id < CAAction >)actionForKey:(NSString *)key 58 | { 59 | // pay attention to when our sublayers change 60 | if ([key isEqualToString:@"sublayers"]) 61 | [self performSelector:@selector(checkSublayersForShadows) withObject:nil afterDelay:0.f]; 62 | 63 | return [super actionForKey:key]; 64 | } 65 | 66 | #pragma mark - Property accessors 67 | 68 | - (NSMutableSet*)shadowedLayers 69 | { 70 | if (shadowedLayers) 71 | return shadowedLayers; 72 | shadowedLayers = [[NSMutableSet alloc] initWithCapacity:5]; 73 | return shadowedLayers; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /fiatlux/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/14/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /fiatlux/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/14/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SMShadowedLayer.h" 11 | #import "SMTransformLayer.h" 12 | 13 | @interface ViewController () 14 | { 15 | SMShadowedLayer *layer; 16 | SMTransformLayer *transformLayer; 17 | } 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad 23 | { 24 | [super viewDidLoad]; 25 | // Do any additional setup after loading the view, typically from a nib. 26 | } 27 | 28 | - (void)viewDidUnload 29 | { 30 | [super viewDidUnload]; 31 | // Release any retained subviews of the main view. 32 | } 33 | 34 | - (void)viewWillAppear:(BOOL)animated 35 | { 36 | [super viewWillAppear:animated]; 37 | CATransform3D perspective = CATransform3DIdentity; 38 | perspective.m34 = -1.f/1000.f; 39 | self.view.layer.sublayerTransform = perspective; 40 | self.view.backgroundColor = [UIColor grayColor]; 41 | 42 | transformLayer = [SMTransformLayer layer]; 43 | [self.view.layer addSublayer:transformLayer]; 44 | 45 | layer = [SMShadowedLayer layer]; 46 | layer.showHighlight = YES; 47 | [transformLayer addSublayer:layer]; 48 | 49 | UIImage *image = [UIImage imageNamed:@"logo_periwinkle"]; 50 | layer.contents = (id)image.CGImage; 51 | 52 | UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; 53 | [self.view addGestureRecognizer:pan]; 54 | 55 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)]; 56 | [self.view addGestureRecognizer:tap]; 57 | } 58 | 59 | - (void)pan:(UIPanGestureRecognizer*)pan 60 | { 61 | CGPoint location = [pan locationInView:self.view]; 62 | CGSize viewSize = self.view.bounds.size; 63 | location = CGPointMake((location.x - viewSize.width / 2) / viewSize.width, 64 | (location.y - viewSize.height / 2) / viewSize.height); 65 | [CATransaction begin]; 66 | [CATransaction setDisableActions:YES]; 67 | transformLayer.transform = CATransform3DRotate(CATransform3DMakeRotation(M_PI * location.x, 0, 1, 0), -M_PI * location.y, 1, 0, 0); 68 | // if I weren't using SMShadowedTransformLayer, here I would simply do: 69 | // [layer setTransform:layer.transform animatePerFrame:YES]; 70 | [CATransaction commit]; 71 | } 72 | 73 | - (void)tap:(UITapGestureRecognizer*)tap 74 | { 75 | CGPoint location = [tap locationInView:self.view]; 76 | CGSize viewSize = self.view.bounds.size; 77 | location = CGPointMake((location.x - viewSize.width / 2) / viewSize.width, 78 | (location.y - viewSize.height / 2) / viewSize.height); 79 | [CATransaction begin]; 80 | [CATransaction setAnimationDuration:1.f]; 81 | transformLayer.transform = CATransform3DRotate(CATransform3DMakeRotation(M_PI * location.x, 0, 1, 0), -M_PI * location.y, 1, 0, 0); 82 | // if I weren't using SMShadowedTransformLayer, here I would simply do: 83 | // [layer setTransform:layer.transform animatePerFrame:YES]; 84 | [CATransaction commit]; 85 | } 86 | 87 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 88 | { 89 | return YES; 90 | } 91 | 92 | - (void)viewDidLayoutSubviews 93 | { 94 | CGSize viewSize = self.view.bounds.size; 95 | layer.frame = CGRectMake(viewSize.width/2 - 150, viewSize.height/2 - 150, 300, 300); 96 | transformLayer.frame = self.view.bounds; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /fiatlux/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /fiatlux/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11C25 6 | 1919 7 | 1138.11 8 | 566.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 916 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBIPadFramework 28 | 29 | 30 | IBFirstResponder 31 | IBIPadFramework 32 | 33 | 34 | 35 | 274 36 | {{0, 20}, {768, 1004}} 37 | 38 | 39 | 40 | 3 41 | MQA 42 | 43 | 2 44 | 45 | 46 | 47 | 2 48 | 49 | IBIPadFramework 50 | 51 | 52 | 53 | 54 | 55 | 56 | view 57 | 58 | 59 | 60 | 3 61 | 62 | 63 | 64 | 65 | 66 | 0 67 | 68 | 69 | 70 | 71 | 72 | -1 73 | 74 | 75 | File's Owner 76 | 77 | 78 | -2 79 | 80 | 81 | 82 | 83 | 2 84 | 85 | 86 | 87 | 88 | 89 | 90 | ViewController 91 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 92 | UIResponder 93 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 94 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 95 | 96 | 97 | 98 | 99 | 100 | 3 101 | 102 | 103 | 104 | 105 | ViewController 106 | UIViewController 107 | 108 | IBProjectSource 109 | ./Classes/ViewController.h 110 | 111 | 112 | 113 | 114 | 0 115 | IBIPadFramework 116 | YES 117 | 3 118 | 916 119 | 120 | 121 | -------------------------------------------------------------------------------- /fiatlux/fiatlux-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.spacemanlabs.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations~ipad 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /fiatlux/fiatlux-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'fiatlux' target in the 'fiatlux' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /fiatlux/logo_periwinkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spaceman-Labs/ShadowedLayer/c3d23671e07c3f2c75c57d9266048bc8a2d7aa4c/fiatlux/logo_periwinkle.png -------------------------------------------------------------------------------- /fiatlux/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // fiatlux 4 | // 5 | // Created by Joel Kraut on 3/14/12. 6 | // Copyright (c) 2012 Spaceman Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | --------------------------------------------------------------------------------