├── .DS_Store ├── etc └── image1.png ├── BtnResources ├── buy.png ├── back@2x.png ├── bkbtn.png ├── bkbtn_d.png ├── buy_d.png ├── click.wav ├── back_d@2x.png ├── back_x@2x.png ├── buttons.atlasc │ ├── buttons.1.png │ ├── buttons.1@2x.png │ ├── buttons.1@3x.png │ └── buttons.plist └── Buttons.swift ├── SgButtonDemoIOS ├── .DS_Store ├── SgButtonDemoIOS.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ ├── TonyPham.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── nguyenpham.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcuserdata │ │ ├── TonyPham.xcuserdatad │ │ │ └── xcschemes │ │ │ │ ├── xcschememanagement.plist │ │ │ │ └── SgButtonDemoIOS.xcscheme │ │ └── nguyenpham.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── SgButtonDemoIOS.xcscheme │ └── project.pbxproj ├── SgButtonDemoIOSTests │ ├── Info.plist │ └── SgButtonDemoIOSTests.swift └── SgButtonDemoIOS │ ├── GameViewController.swift │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.xib │ ├── AppDelegate.swift │ └── GameScene.swift ├── SgButtonDemo ├── SgButtonDemo │ ├── Actions.sks │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── GameViewController.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── AppDelegate.swift │ └── GameScene.swift └── SgButtonDemo.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── nguyenpham.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── xcuserdata │ └── nguyenpham.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ └── project.pbxproj ├── sgbutton.podspec ├── LICENSE ├── README.md └── SgButton └── SgButton.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/.DS_Store -------------------------------------------------------------------------------- /etc/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/etc/image1.png -------------------------------------------------------------------------------- /BtnResources/buy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/buy.png -------------------------------------------------------------------------------- /BtnResources/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/back@2x.png -------------------------------------------------------------------------------- /BtnResources/bkbtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/bkbtn.png -------------------------------------------------------------------------------- /BtnResources/bkbtn_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/bkbtn_d.png -------------------------------------------------------------------------------- /BtnResources/buy_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/buy_d.png -------------------------------------------------------------------------------- /BtnResources/click.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/click.wav -------------------------------------------------------------------------------- /BtnResources/back_d@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/back_d@2x.png -------------------------------------------------------------------------------- /BtnResources/back_x@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/back_x@2x.png -------------------------------------------------------------------------------- /SgButtonDemoIOS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/SgButtonDemoIOS/.DS_Store -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Actions.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/SgButtonDemo/SgButtonDemo/Actions.sks -------------------------------------------------------------------------------- /BtnResources/buttons.atlasc/buttons.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/buttons.atlasc/buttons.1.png -------------------------------------------------------------------------------- /BtnResources/buttons.atlasc/buttons.1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/buttons.atlasc/buttons.1@2x.png -------------------------------------------------------------------------------- /BtnResources/buttons.atlasc/buttons.1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/BtnResources/buttons.atlasc/buttons.1@3x.png -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/SgButtonDemo/SgButtonDemo.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/xcuserdata/TonyPham.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/xcuserdata/TonyPham.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenpham/sgbutton/HEAD/SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SgButtonDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /sgbutton.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "sgbutton" 3 | s.version = "0.0.2" 4 | s.summary = "Button library for SpriteKit in Swift" 5 | s.homepage = "https://github.com/nguyenpham/sgbutton" 6 | s.license = "MIT" 7 | s.author = { "nguyenpham" => "axchess@yahoo.com" } 8 | 9 | s.ios.deployment_target = "8.0" 10 | s.source = { :git => "https://github.com/nguyenpham/sgbutton.git", :tag => s.version } 11 | 12 | s.source_files = "SgButton/*.swift" 13 | end 14 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/xcuserdata/TonyPham.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SgButtonDemoIOS.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | B153314E1A9FE49A0026FE28 16 | 17 | primary 18 | 19 | 20 | B15331671A9FE49A0026FE28 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SgButtonDemoIOS.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | B153314E1A9FE49A0026FE28 16 | 17 | primary 18 | 19 | 20 | B15331671A9FE49A0026FE28 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOSTests/SgButtonDemoIOSTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SgButtonDemoIOSTests.swift 3 | // SgButtonDemoIOSTests 4 | // 5 | // Created by Nguyen Pham on 27/02/2015. 6 | // Copyright (c) 2015 Softgaroo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SgButtonDemoIOSTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // SgButtonDemo 4 | // 5 | // Created by Nguyen Pham on 22/3/2023. 6 | // 7 | 8 | import UIKit 9 | import SpriteKit 10 | import GameplayKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | if let view = self.view as! SKView? { 18 | let scene = GameScene(size: view.bounds.size) 19 | 20 | // Set the scale mode to scale to fit the window 21 | scene.scaleMode = .aspectFill 22 | 23 | // Present the scene 24 | view.presentScene(scene) 25 | 26 | view.ignoresSiblingOrder = true 27 | 28 | view.showsFPS = true 29 | view.showsNodeCount = true 30 | } 31 | } 32 | 33 | override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 34 | if UIDevice.current.userInterfaceIdiom == .phone { 35 | return .allButUpsideDown 36 | } else { 37 | return .all 38 | } 39 | } 40 | 41 | override var prefersStatusBarHidden: Bool { 42 | return true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /BtnResources/Buttons.swift: -------------------------------------------------------------------------------- 1 | // --------------------------------------- 2 | // Sprite definitions for 'buttons' 3 | // Generated with TexturePacker 3.6.0 4 | // 5 | // http://www.codeandweb.com/texturepacker 6 | // --------------------------------------- 7 | 8 | import SpriteKit 9 | 10 | 11 | class Buttons { 12 | 13 | // sprite names 14 | let BACK = "back" 15 | let BACK_D = "back_d" 16 | let BACK_X = "back_x" 17 | let BUY = "buy" 18 | let BUY_D = "buy_d" 19 | let GREENBUTTON = "greenbutton" 20 | let YELLOWBUTTON = "yellowbutton" 21 | 22 | 23 | // load texture atlas 24 | let textureAtlas = SKTextureAtlas(named: "buttons") 25 | 26 | 27 | // individual texture objects 28 | func back() -> SKTexture { return textureAtlas.textureNamed(BACK) } 29 | func back_d() -> SKTexture { return textureAtlas.textureNamed(BACK_D) } 30 | func back_x() -> SKTexture { return textureAtlas.textureNamed(BACK_X) } 31 | func buy() -> SKTexture { return textureAtlas.textureNamed(BUY) } 32 | func buy_d() -> SKTexture { return textureAtlas.textureNamed(BUY_D) } 33 | func greenbutton() -> SKTexture { return textureAtlas.textureNamed(GREENBUTTON) } 34 | func yellowbutton() -> SKTexture { return textureAtlas.textureNamed(YELLOWBUTTON) } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, SmartFish Software Ltd. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // SgButtonDemoIOS 4 | // 5 | // Created by Nguyen Pham on 27/02/2015. 6 | // Copyright (c) 2015 Softgaroo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SpriteKit 11 | 12 | class GameViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | let skView = self.view as! SKView 18 | let scene = GameScene(size: skView.bounds.size) 19 | 20 | // Configure the view. 21 | skView.showsFPS = true 22 | skView.showsNodeCount = true 23 | 24 | /* Sprite Kit applies additional optimizations to improve rendering performance */ 25 | skView.ignoresSiblingOrder = true 26 | 27 | /* Set the scale mode to scale to fit the window */ 28 | scene.scaleMode = .AspectFill 29 | 30 | skView.presentScene(scene) 31 | 32 | } 33 | 34 | override func shouldAutorotate() -> Bool { 35 | return true 36 | } 37 | 38 | override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 39 | if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 40 | return UIInterfaceOrientationMask.AllButUpsideDown 41 | } else { 42 | return UIInterfaceOrientationMask.All 43 | } 44 | } 45 | 46 | override func didReceiveMemoryWarning() { 47 | super.didReceiveMemoryWarning() 48 | // Release any cached data, images, etc that aren't in use. 49 | } 50 | 51 | override func prefersStatusBarHidden() -> Bool { 52 | return true 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarHidden 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SgButtonDemo 4 | // 5 | // Created by Nguyen Pham on 22/3/2023. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // 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. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // 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. 28 | } 29 | 30 | func applicationWillEnterForeground(_ application: UIApplication) { 31 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 32 | } 33 | 34 | func applicationDidBecomeActive(_ application: UIApplication) { 35 | // 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. 36 | } 37 | 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SgButtonDemoIOS 4 | // 5 | // Created by Nguyen Pham on 27/02/2015. 6 | // Copyright (c) 2015 Softgaroo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SgButton in Swift for SpriteKit 2 | =============================== 3 | Update March 2023 4 | ----------------- 5 | - Support Swift 5 6 | - Support sounds, new button type 7 | 8 | 9 | Background 10 | ---------- 11 | 12 | When starting working with SpriteKit, we have found that that framework has not supported buttons yet. Some current open-source is not good enough for me. Thus I have created this component to fill my needs. The code is written in Swift. We share it in hope it may be usefull to others as well as having more contributes / improvements from other programmers. 13 | 14 | Screenshots 15 | ------- 16 | ![Simple selector](https://github.com/nguyenpham/sgbutton/blob/master/etc/image1.png?raw=true) 17 | 18 | 19 | Features 20 | ------- 21 | * Create buttons from image files or texture (sprite sheet) 22 | * Create rectangle / round corner rectangle buttons 23 | * Create buttons with string (text) 24 | * Sound click 25 | * Work well with defferent screen (rentina) 26 | * Work well after being rotated, changed anchorPoint 27 | 28 | Installation 29 | ------- 30 | 31 | ### Add files directly 32 | 33 | Copy the file SgButton.swift (in the SgButton folder) into your project. 34 | 35 | 36 | Usage 37 | ----- 38 | Use image files to create buttons: 39 | 40 | var btn1 = SgButton(normalImageNamed: "back.png") 41 | var btn2 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 42 | 43 | Use textures (from spritesheet) to create buttons: 44 | 45 | var btn3 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.buy_d(), buttonFunc: tappedButton) 46 | 47 | Create text buttons (round corner button): 48 | 49 | var btn4 = SgButton(normalString: "Tap me", normalStringColor: UIColor.blue, size: CGSizeMake(200, 40), cornerRadius: 10.0, buttonFunc: tappedButton) 50 | 51 | Users can setup for highlighed and disabled state too. Just any of parametters will be fine: 52 | 53 | var btn44 = SgButton(normalString: "Tap me", normalStringColor: UIColor.blue, highlightedStringColor: UIColor.yellow, size: CGSizeMake(200, 40), cornerRadius: 10.0, buttonFunc: tappedButton) 54 | 55 | Create text buttons with image as background 56 | 57 | var btn5 = SgButton(normalTexture: buttonSheet.greenbutton(), highlightedTexture: buttonSheet.yellowbutton(), buttonFunc: tappedButton) 58 | btn5.setString(.Normal, string: "Are you sure?", fontSize: 24, stringColor: UIColor.white) 59 | 60 | License 61 | ------- 62 | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) 63 | Almost total free, just fair use! 64 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/xcuserdata/TonyPham.xcuserdatad/xcschemes/SgButtonDemoIOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcschemes/SgButtonDemoIOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS/GameScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameScene.swift 3 | // SgButtonDemoIOS 4 | // 5 | // Created by Nguyen Pham on 27/02/2015. 6 | // Copyright (c) 2015 Softgaroo. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class GameScene: SKScene { 12 | var buttonSheet = Buttons() 13 | override func didMoveToView(view: SKView) { 14 | self.backgroundColor = UIColor.grayColor() 15 | 16 | let x: CGFloat = 100 17 | var y: CGFloat = self.frame.height - 80 18 | 19 | /* 20 | * Using image file 21 | */ 22 | // Simplest 23 | let btn00 = SgButton(normalImageNamed: "back.png", buttonFunc: tappedButton) 24 | btn00.position = CGPointMake(x, y) 25 | btn00.tag = 0 26 | self.addChild(btn00) 27 | 28 | 29 | // 3 images for 3 states, rotate 30 | let btn01 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 31 | btn01.position = CGPointMake(x + 100, y) 32 | btn01.tag = 1 33 | btn01.zRotation = CGFloat(M_PI_2) 34 | self.addChild(btn01) 35 | 36 | 37 | // 3 images for 3 states 38 | y -= 80 39 | let btn10 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 40 | btn10.position = CGPointMake(x, y) 41 | btn10.tag = 10 42 | self.addChild(btn10) 43 | 44 | // 3 images for 3 states, start by highlighted state 45 | let btn11 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 46 | btn11.position = CGPointMake(x + 100, y) 47 | btn11.buttonState = .Highlighted 48 | btn11.tag = 11 49 | self.addChild(btn11) 50 | 51 | // 3 images for 3 states, disabled 52 | let btn12 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 53 | btn12.position = CGPointMake(x + 200, y) 54 | btn12.disabled = true 55 | btn12.tag = 13 56 | self.addChild(btn12) 57 | 58 | /* 59 | * Using texture from sprite sheet 60 | */ 61 | 62 | y -= 80 63 | let btn20 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.buy_d(), buttonFunc: tappedButton) 64 | btn20.position = CGPointMake(x, y) 65 | btn20.tag = 20 66 | self.addChild(btn20) 67 | 68 | // the second texture for highlighted is bigger than the first one, but button is still same size 69 | let btn21 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.back(), buttonFunc: tappedButton) 70 | btn21.position = CGPointMake(x + 100, y) 71 | btn21.tag = 21 72 | self.addChild(btn21) 73 | 74 | // using closure as the button func, change texture randomly after tapping 75 | let btn22 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.back(), buttonFunc: { (button: SgButton) -> Void in 76 | let names: [ String ] = [ self.buttonSheet.BUY, self.buttonSheet.BUY_D, self.buttonSheet.BACK, self.buttonSheet.BACK_D, self.buttonSheet.BACK_X ] 77 | let k = Int(arc4random() % UInt32(names.count)) 78 | let str = names[k] 79 | let newTex = self.buttonSheet.textureAtlas.textureNamed(str) 80 | button.setTexture(.Normal, texture: newTex) 81 | }) 82 | btn22.position = CGPointMake(x + 200, y) 83 | btn22.tag = 22 84 | self.addChild(btn22) 85 | 86 | /* 87 | * Using text and background as plan color 88 | */ 89 | 90 | // Simplest case. The button created with black text, white background, size is just fit to the text 91 | y -= 80 92 | let btn30 = SgButton(normalString: "Hello World!!!", buttonFunc: tappedButton) 93 | btn30.position = CGPointMake(x, y) 94 | btn30.tag = 30 95 | self.addChild(btn30) 96 | 97 | // Round corner button 98 | let btn31 = SgButton(normalString: "Tap me", normalStringColor: UIColor.blueColor(), normalFontName: "Arial", normalFontSize: 25, backgroundNormalColor: UIColor.yellowColor(), size: CGSizeMake(200, 40), cornerRadius: 10.0, buttonFunc: tappedButton) 99 | btn31.setString(.Highlighted, string: "Being tapped", stringColor: UIColor.redColor(), backgroundColor: UIColor.greenColor()) 100 | btn31.position = CGPointMake(x + 200, y) 101 | btn31.tag = 31 102 | self.addChild(btn31) 103 | 104 | /* 105 | * Using text & image as background 106 | */ 107 | y -= 90 108 | let btn40 = SgButton(normalImageNamed: "bkbtn.png", buttonFunc: tappedButton) 109 | btn40.setString(.Normal, string: "REGISTER", stringColor: UIColor.blueColor()) 110 | btn40.setString(.Highlighted, string: "REGISTER", stringColor: UIColor.redColor()) 111 | btn40.position = CGPointMake(x, y) 112 | btn40.tag = 40 113 | self.addChild(btn40) 114 | 115 | let btn41 = SgButton(normalImageNamed: "bkbtn.png", buttonFunc: tappedButton) 116 | btn41.setString(.Normal, string: "Fun", stringColor: UIColor.blueColor()) 117 | btn41.setString(.Highlighted, string: "Funiest", stringColor: UIColor.redColor()) 118 | btn41.position = CGPointMake(x + 200, y) 119 | btn41.zRotation = CGFloat(M_PI_4) 120 | btn41.tag = 40 121 | self.addChild(btn41) 122 | 123 | 124 | /* 125 | * Using text & texture as background 126 | * WARRNING: in the case of combining text and texture, due to the current limit of the technique (convert texture to image), 127 | * all black point of the texture will be converted into transparent. Avoid to use black details in the texture if you don not 128 | * want that effect 129 | */ 130 | y -= 90 131 | let btn50 = SgButton(normalTexture: buttonSheet.greenbutton(), highlightedTexture: buttonSheet.yellowbutton(), buttonFunc: tappedButton) 132 | btn50.setString(.Normal, string: "Are you sure?", fontSize: 24, stringColor: UIColor.whiteColor()) 133 | btn50.setString(.Highlighted, string: "LOL!!!", stringColor: UIColor.blueColor()) 134 | btn50.position = CGPointMake(x, y) 135 | btn50.tag = 50 136 | self.addChild(btn50) 137 | } 138 | 139 | func tappedButton(button: SgButton) { 140 | print("tappedButton tappedButton tag=\(button.tag)") 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo/GameScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameScene.swift 3 | // SgButtonDemo 4 | // 5 | // Created by Nguyen Pham on 22/3/2023. 6 | // 7 | 8 | import SpriteKit 9 | import GameplayKit 10 | 11 | class GameScene: SKScene { 12 | 13 | var buttonSheet = Buttons() 14 | 15 | override func didMove(to view: SKView) { 16 | self.backgroundColor = UIColor.gray 17 | 18 | let x: CGFloat = 100 19 | var y: CGFloat = self.frame.height - 160 20 | 21 | /* 22 | * Using image file 23 | */ 24 | // Simplest 25 | let btn00 = SgButton(normalImageNamed: "back.png", buttonFunc: tappedButton) 26 | btn00.position = CGPointMake(x, y) 27 | btn00.tag = 0 28 | self.addChild(btn00) 29 | 30 | 31 | // 3 images for 3 states, rotate 32 | let btn01 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", 33 | clickSoundName: "click", buttonFunc: tappedButton) 34 | btn01.position = CGPointMake(x + 100, y) 35 | btn01.tag = 1 36 | btn01.zRotation = CGFloat(Float.pi / 2) 37 | self.addChild(btn01) 38 | 39 | 40 | // 3 images for 3 states 41 | y -= 80 42 | let btn10 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 43 | btn10.position = CGPointMake(x, y) 44 | btn10.tag = 10 45 | self.addChild(btn10) 46 | 47 | // 3 images for 3 states, start by highlighted state 48 | let btn11 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 49 | btn11.position = CGPointMake(x + 100, y) 50 | btn11.state = .highlighted 51 | btn11.tag = 11 52 | self.addChild(btn11) 53 | 54 | // 3 images for 3 states, disabled 55 | let btn12 = SgButton(normalImageNamed: "back.png", highlightedImageNamed: "back_d.png", disabledImageNamed: "back_x.png", buttonFunc: tappedButton) 56 | btn12.position = CGPointMake(x + 200, y) 57 | btn12.disabled = true 58 | btn12.tag = 13 59 | self.addChild(btn12) 60 | 61 | /* 62 | * Using texture from sprite sheet 63 | */ 64 | 65 | y -= 80 66 | let btn20 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.buy_d(), clickSoundName: "click", buttonFunc: tappedButton) 67 | btn20.position = CGPointMake(x, y) 68 | btn20.tag = 20 69 | self.addChild(btn20) 70 | 71 | // the second texture for highlighted is bigger than the first one, but button is still same size 72 | let btn21 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.back(), clickSoundName: "click", buttonFunc: tappedButton) 73 | btn21.position = CGPointMake(x + 100, y) 74 | btn21.tag = 21 75 | self.addChild(btn21) 76 | 77 | // using closure as the button func, change texture randomly after tapping 78 | let btn22 = SgButton(normalTexture: buttonSheet.buy(), highlightedTexture: buttonSheet.back(), clickSoundName: "click", buttonFunc: { (button: SgButton) -> Void in 79 | let names: [ String ] = [ self.buttonSheet.BUY, self.buttonSheet.BUY_D, self.buttonSheet.BACK, self.buttonSheet.BACK_D, self.buttonSheet.BACK_X ] 80 | let k = Int(arc4random() % UInt32(names.count)) 81 | let str = names[k] 82 | let newTex = self.buttonSheet.textureAtlas.textureNamed(str) 83 | button.setTexture(state: .normal, texture: newTex) 84 | }) 85 | btn22.position = CGPointMake(x + 200, y) 86 | btn22.tag = 22 87 | self.addChild(btn22) 88 | 89 | /* 90 | * Using text and background as plan color 91 | */ 92 | 93 | // Simplest case. The button created with black text, white background, size is just fit to the text 94 | y -= 80 95 | let btn30 = SgButton(normalString: "Hello World!!!", clickSoundName: "click", buttonFunc: tappedButton) 96 | btn30.position = CGPointMake(x, y) 97 | btn30.tag = 30 98 | self.addChild(btn30) 99 | 100 | // Round corner button 101 | let btn31 = SgButton(normalString: "Tap me", 102 | normalStringColor: UIColor.blue, 103 | normalBackgroundColor: UIColor.yellow, fontName: "Arial", fontSize: 25, 104 | size: CGSizeMake(200, 40), 105 | cornerRadius: 10.0, 106 | buttonFunc: tappedButton) 107 | 108 | btn31.setString(state: .highlighted, string: "Being tapped", stringColor: UIColor.red, backgroundColor: UIColor.green) 109 | btn31.position = CGPointMake(x + 200, y) 110 | btn31.tag = 31 111 | self.addChild(btn31) 112 | 113 | /* 114 | * Using text & image as background 115 | */ 116 | y -= 90 117 | let btn40 = SgButton(normalImageNamed: "bkbtn.png", buttonFunc: tappedButton) 118 | btn40.setString(state: .normal, string: "REGISTER", stringColor: UIColor.blue) 119 | btn40.setString(state: .highlighted, string: "REGISTER", stringColor: UIColor.red) 120 | btn40.position = CGPointMake(x, y) 121 | btn40.tag = 40 122 | self.addChild(btn40) 123 | 124 | let btn41 = SgButton(normalImageNamed: "bkbtn.png", buttonFunc: tappedButton) 125 | btn41.setString(state: .normal, string: "Fun", stringColor: UIColor.blue) 126 | btn41.setString(state: .highlighted, string: "Funiest", stringColor: UIColor.red) 127 | btn41.position = CGPointMake(x + 200, y) 128 | btn41.zRotation = CGFloat(Float.pi / 4) 129 | btn41.tag = 40 130 | self.addChild(btn41) 131 | 132 | 133 | /* 134 | * Using text & texture as background 135 | * WARRNING: in the case of combining text and texture, due to the current limit of the technique (convert texture to image), 136 | * all black point of the texture will be converted into transparent. Avoid to use black details in the texture if you don not 137 | * want that effect 138 | */ 139 | y -= 90 140 | let btn50 = SgButton(normalTexture: buttonSheet.greenbutton(), highlightedTexture: buttonSheet.yellowbutton(), buttonFunc: tappedButton) 141 | btn50.setString(state: .normal, string: "Are you sure?", fontSize: 24, stringColor: UIColor.white) 142 | btn50.setString(state: .highlighted, string: "LOL!!!", stringColor: UIColor.blue) 143 | btn50.position = CGPointMake(x, y) 144 | btn50.tag = 50 145 | self.addChild(btn50) 146 | } 147 | 148 | func tappedButton(button: SgButton) { 149 | print("tappedButton tappedButton tag=\(button.tag)") 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /BtnResources/buttons.atlasc/buttons.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | codeandweb 6 | 7 | generator 8 | TexturePacker 3.6.0 - http://www.codeandweb.com/texturepacker 9 | smartupdate 10 | $TexturePacker:SmartUpdate:2867a5dd42654d7ff9c511add55c3a36:4874254ddeaf41ed3da6e3a36e3fc0a4:1e86c9befc434447f48cd1c6a2a01fb2$ 11 | 12 | format 13 | APPL 14 | images 15 | 16 | 17 | path 18 | buttons.1@3x.png 19 | size 20 | {233,1732} 21 | subimages 22 | 23 | 24 | aliases 25 | 26 | isFullyOpaque 27 | 28 | name 29 | greenbutton@3x.png 30 | spriteOffset 31 | {0,8} 32 | spriteSourceSize 33 | {600,200} 34 | textureRect 35 | {{1,1},{192,591}} 36 | textureRotated 37 | 38 | 39 | 40 | aliases 41 | 42 | isFullyOpaque 43 | 44 | name 45 | yellowbutton@3x.png 46 | spriteOffset 47 | {9,0} 48 | spriteSourceSize 49 | {600,200} 50 | textureRect 51 | {{1,594},{192,591}} 52 | textureRotated 53 | 54 | 55 | 56 | aliases 57 | 58 | isFullyOpaque 59 | 60 | name 61 | back@3x.png 62 | spriteOffset 63 | {4,0} 64 | spriteSourceSize 65 | {220,125} 66 | textureRect 67 | {{1,1187},{115,212}} 68 | textureRotated 69 | 70 | 71 | 72 | aliases 73 | 74 | isFullyOpaque 75 | 76 | name 77 | buy@3x.png 78 | spriteOffset 79 | {7,1} 80 | spriteSourceSize 81 | {220,125} 82 | textureRect 83 | {{118,1187},{114,210}} 84 | textureRotated 85 | 86 | 87 | 88 | aliases 89 | 90 | isFullyOpaque 91 | 92 | name 93 | back_d@3x.png 94 | spriteOffset 95 | {4,0} 96 | spriteSourceSize 97 | {220,125} 98 | textureRect 99 | {{1,1401},{115,212}} 100 | textureRotated 101 | 102 | 103 | 104 | aliases 105 | 106 | isFullyOpaque 107 | 108 | name 109 | buy_d@3x.png 110 | spriteOffset 111 | {7,1} 112 | spriteSourceSize 113 | {220,125} 114 | textureRect 115 | {{118,1399},{114,210}} 116 | textureRotated 117 | 118 | 119 | 120 | aliases 121 | 122 | isFullyOpaque 123 | 124 | name 125 | back_x@3x.png 126 | spriteOffset 127 | {0,0} 128 | spriteSourceSize 129 | {200,120} 130 | textureRect 131 | {{1,1615},{200,116}} 132 | textureRotated 133 | 134 | 135 | 136 | 137 | 138 | path 139 | buttons.1@2x.png 140 | size 141 | {792,209} 142 | subimages 143 | 144 | 145 | aliases 146 | 147 | isFullyOpaque 148 | 149 | name 150 | greenbutton@2x.png 151 | spriteOffset 152 | {0,5} 153 | spriteSourceSize 154 | {400,133} 155 | textureRect 156 | {{1,1},{394,128}} 157 | textureRotated 158 | 159 | 160 | 161 | aliases 162 | 163 | isFullyOpaque 164 | 165 | name 166 | yellowbutton@2x.png 167 | spriteOffset 168 | {6,0} 169 | spriteSourceSize 170 | {400,133} 171 | textureRect 172 | {{397,1},{394,128}} 173 | textureRotated 174 | 175 | 176 | 177 | aliases 178 | 179 | isFullyOpaque 180 | 181 | name 182 | back@2x.png 183 | spriteOffset 184 | {2,0} 185 | spriteSourceSize 186 | {147,83} 187 | textureRect 188 | {{1,131},{143,77}} 189 | textureRotated 190 | 191 | 192 | 193 | aliases 194 | 195 | isFullyOpaque 196 | 197 | name 198 | back_d@2x.png 199 | spriteOffset 200 | {2,0} 201 | spriteSourceSize 202 | {147,83} 203 | textureRect 204 | {{146,131},{143,77}} 205 | textureRotated 206 | 207 | 208 | 209 | aliases 210 | 211 | isFullyOpaque 212 | 213 | name 214 | buy@2x.png 215 | spriteOffset 216 | {4,0} 217 | spriteSourceSize 218 | {147,83} 219 | textureRect 220 | {{291,131},{141,77}} 221 | textureRotated 222 | 223 | 224 | 225 | aliases 226 | 227 | isFullyOpaque 228 | 229 | name 230 | buy_d@2x.png 231 | spriteOffset 232 | {4,0} 233 | spriteSourceSize 234 | {147,83} 235 | textureRect 236 | {{434,131},{141,77}} 237 | textureRotated 238 | 239 | 240 | 241 | aliases 242 | 243 | isFullyOpaque 244 | 245 | name 246 | back_x@2x.png 247 | spriteOffset 248 | {0,0} 249 | spriteSourceSize 250 | {133,80} 251 | textureRect 252 | {{577,131},{133,77}} 253 | textureRotated 254 | 255 | 256 | 257 | 258 | 259 | path 260 | buttons.1.png 261 | size 262 | {398,108} 263 | subimages 264 | 265 | 266 | aliases 267 | 268 | isFullyOpaque 269 | 270 | name 271 | greenbutton.png 272 | spriteOffset 273 | {0,2} 274 | spriteSourceSize 275 | {200,67} 276 | textureRect 277 | {{1,1},{197,65}} 278 | textureRotated 279 | 280 | 281 | 282 | aliases 283 | 284 | isFullyOpaque 285 | 286 | name 287 | yellowbutton.png 288 | spriteOffset 289 | {3,0} 290 | spriteSourceSize 291 | {200,67} 292 | textureRect 293 | {{200,1},{197,65}} 294 | textureRotated 295 | 296 | 297 | 298 | aliases 299 | 300 | isFullyOpaque 301 | 302 | name 303 | back.png 304 | spriteOffset 305 | {1,0} 306 | spriteSourceSize 307 | {73,42} 308 | textureRect 309 | {{1,68},{71,39}} 310 | textureRotated 311 | 312 | 313 | 314 | aliases 315 | 316 | isFullyOpaque 317 | 318 | name 319 | back_d.png 320 | spriteOffset 321 | {1,0} 322 | spriteSourceSize 323 | {73,42} 324 | textureRect 325 | {{74,68},{71,39}} 326 | textureRotated 327 | 328 | 329 | 330 | aliases 331 | 332 | isFullyOpaque 333 | 334 | name 335 | buy.png 336 | spriteOffset 337 | {2,0} 338 | spriteSourceSize 339 | {73,42} 340 | textureRect 341 | {{147,68},{70,39}} 342 | textureRotated 343 | 344 | 345 | 346 | aliases 347 | 348 | isFullyOpaque 349 | 350 | name 351 | buy_d.png 352 | spriteOffset 353 | {2,0} 354 | spriteSourceSize 355 | {73,42} 356 | textureRect 357 | {{219,68},{70,39}} 358 | textureRotated 359 | 360 | 361 | 362 | aliases 363 | 364 | isFullyOpaque 365 | 366 | name 367 | back_x.png 368 | spriteOffset 369 | {0,0} 370 | spriteSourceSize 371 | {67,40} 372 | textureRect 373 | {{291,68},{67,39}} 374 | textureRotated 375 | 376 | 377 | 378 | 379 | 380 | version 381 | 1 382 | 383 | 384 | -------------------------------------------------------------------------------- /SgButton/SgButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SgButton.swift 3 | // 4 | /* 5 | * Copyright (c) 2016 Nguyen Pham, February 10 2015, code revised on 22 March 2023 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | import SpriteKit 27 | 28 | class SgButton: SKSpriteNode { 29 | enum ButtonType { 30 | case normal, flip 31 | } 32 | 33 | enum State { 34 | case normal, highlighted, disabled 35 | } 36 | 37 | class Record { 38 | /* Input image */ 39 | var imageFileName: String? 40 | var imageTexture: SKTexture? 41 | 42 | /* text */ 43 | var string: String? 44 | var fontName: String? 45 | var fontSize: CGFloat? 46 | var stringColor: UIColor? 47 | 48 | /* Background color */ 49 | var backgroundColor: UIColor? 50 | var cornerRadius: CGFloat? 51 | 52 | /* Size */ 53 | var buttonSize: CGSize? 54 | 55 | var generatedImageTexture: SKTexture? 56 | 57 | init() {} 58 | 59 | init(imageFileName: String) { 60 | self.imageFileName = imageFileName 61 | generateTexture() 62 | } 63 | 64 | init(texture: SKTexture) { 65 | self.imageTexture = texture 66 | generateTexture() 67 | } 68 | 69 | private func getFont() -> UIFont { 70 | let fSz: CGFloat = fontSize == nil ? 18 : fontSize! 71 | var font: UIFont 72 | if fontName != nil { 73 | let f = UIFont(name: fontName!, size: fSz) 74 | assert(f != nil, "Error: Cannot create font \(String(describing: fontName)) / \(String(describing: fontSize))") 75 | font = f! 76 | } else { 77 | font = UIFont.systemFont(ofSize: fSz) 78 | } 79 | return font 80 | } 81 | 82 | func createBkImage(color: UIColor, size: CGSize, cornerRadius: CGFloat?) -> UIImage? { 83 | let rect = CGRectMake(0, 0, size.width, size.height) 84 | UIGraphicsBeginImageContextWithOptions(size, false, 0) 85 | color.setFill() 86 | 87 | if cornerRadius != nil { 88 | UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius!).addClip() 89 | } 90 | 91 | UIRectFill(rect) 92 | let image = UIGraphicsGetImageFromCurrentImageContext() 93 | UIGraphicsEndImageContext() 94 | return image 95 | } 96 | 97 | private func getImage(tex: SKTexture) -> UIImage? { 98 | let sz = tex.size() 99 | 100 | UIGraphicsBeginImageContextWithOptions(sz, false, 0.0); 101 | _ = UIGraphicsGetCurrentContext(); 102 | 103 | let rect = CGRectMake(0, 0, sz.width, sz.height) 104 | let view = SKView(frame:rect) 105 | let scene = SKScene(size: sz) 106 | view.backgroundColor = UIColor.clear 107 | 108 | /* 109 | * WARNING: Limited technique. When converting a texture into image, all transparent points will be lost 110 | * My currrent solution: fill all transparent points by black ones, those black points will be converted 111 | * back into transparent later. Thus texture for background button (only in case using with string) should 112 | * not have black points to avoid that limit 113 | */ 114 | scene.backgroundColor = UIColor.black // -> color will be converted into transparent 115 | let sprite = SKSpriteNode(texture: tex) 116 | sprite.position = CGPoint(x: CGRectGetMidX(view.frame), y: CGRectGetMidY(view.frame)) 117 | 118 | scene.addChild(sprite) 119 | view.presentScene(scene) 120 | view.drawHierarchy(in: view.bounds, afterScreenUpdates: true) 121 | 122 | //Create the image from the context 123 | let image = UIGraphicsGetImageFromCurrentImageContext(); 124 | 125 | //Close the context 126 | UIGraphicsEndImageContext(); 127 | 128 | return image 129 | } 130 | 131 | /* 132 | * WARNING: to avoid blending effect, we convert all black points with value from 0 to 50 into transprent 133 | */ 134 | //RGB color range to mask (make transparent) R-Low, R-High, G-Low, G-High, B-Low, B-High 135 | private let colorMasking:[CGFloat] = [0, 50, 0, 50, 0, 50] 136 | 137 | private func makeTransparent(image: UIImage?) -> UIImage? { 138 | guard 139 | let theimage = image, 140 | let img = UIImage(data: theimage.jpegData(compressionQuality: 1.0)! ), 141 | let imageRef = img.cgImage?.copy(maskingColorComponents: colorMasking) else { 142 | return nil 143 | } 144 | return UIImage(cgImage: imageRef, scale: theimage.scale, orientation: UIImage.Orientation.up) 145 | } 146 | 147 | private var textAttributes: [NSAttributedString.Key: Any]? 148 | private var stringSz: CGSize? 149 | 150 | fileprivate func generateTexture() { 151 | 152 | if string != nil { 153 | let color = stringColor == nil ? UIColor.black : stringColor! 154 | textAttributes = [ 155 | .foregroundColor: color, 156 | .font: getFont() 157 | ] 158 | stringSz = string!.size(withAttributes: textAttributes) 159 | } 160 | 161 | 162 | if imageFileName != nil || (imageTexture == nil && string != nil) { 163 | var image: UIImage? 164 | 165 | if imageFileName != nil { 166 | image = UIImage(named: imageFileName!) 167 | } else { 168 | let sz: CGSize = buttonSize != nil ? buttonSize! : stringSz! 169 | let color: UIColor = backgroundColor ?? UIColor.white 170 | image = createBkImage(color: color, size: sz, cornerRadius: cornerRadius) 171 | } 172 | 173 | assert(image != nil, "Image is nil") 174 | 175 | if let str = string { 176 | generatedImageTexture = generatedStringTexture(image: image, string: str) 177 | } else { 178 | generatedImageTexture = SKTexture(image: image!) 179 | } 180 | return 181 | } 182 | 183 | if imageTexture != nil { 184 | if string == nil { 185 | generatedImageTexture = imageTexture 186 | } else { 187 | /* 188 | * Due to the limit of current technique to convert a texture into image (cannot keep transparence) 189 | * we have to convert later all back points into transparent ones. Don not use black in the background 190 | * button images if you dont want them to be transparent in case of having string 191 | */ 192 | if let image = makeTransparent(image: getImage(tex: imageTexture!)) { 193 | generatedImageTexture = generatedStringTexture(image: image, string: string!) 194 | } 195 | } 196 | } 197 | } 198 | 199 | private func generatedStringTexture(image: UIImage?, string: String) -> SKTexture { 200 | var sz: CGSize 201 | 202 | if buttonSize != nil { 203 | sz = buttonSize! 204 | } else if image != nil { 205 | sz = image!.size 206 | } else { 207 | sz = stringSz! 208 | } 209 | 210 | UIGraphicsBeginImageContextWithOptions(sz, false, 0.0); 211 | guard let ctx = UIGraphicsGetCurrentContext() else { return SKTexture() }; 212 | 213 | if image != nil { 214 | image!.draw(at: CGPointZero) 215 | } else { 216 | let color = backgroundColor ?? UIColor.white 217 | color.setFill() 218 | ctx.fill(CGRectMake(0, 0, sz.width, sz.height)); 219 | } 220 | 221 | let rect = sz==stringSz! ? CGRectMake(0, 0, sz.width, sz.height) : CGRectMake((sz.width - stringSz!.width) * 0.5, (sz.height - stringSz!.height) * 0.5, stringSz!.width, stringSz!.height) 222 | (string as NSString).draw(in: rect, withAttributes: textAttributes) 223 | 224 | //Create the image from the context 225 | let image = UIGraphicsGetImageFromCurrentImageContext(); 226 | 227 | //Close the context 228 | UIGraphicsEndImageContext(); 229 | 230 | return SKTexture(image: image!) 231 | } 232 | } // class Record 233 | 234 | /* 235 | * Assign to name for convernient debug / work 236 | */ 237 | let buttonName = "SgButton" 238 | 239 | /* 240 | * Convernient tag 241 | */ 242 | var tag: Int = 0 243 | 244 | 245 | /* 246 | * Function to be called after being tapped 247 | */ 248 | var buttonFunc: ((_ button: SgButton) -> Void)? 249 | 250 | /* 251 | * ButtonType 252 | */ 253 | var buttonType = ButtonType.normal 254 | 255 | /* 256 | * Sound 257 | */ 258 | var soundOn = true 259 | var clickSoundName: String? = nil 260 | var disableSoundName: String? = nil 261 | 262 | 263 | /* 264 | * Internal data, should not be accessed from outside 265 | */ 266 | 267 | private var records = [ State : Record]() 268 | 269 | private var isDisabled: Bool = false 270 | private var _state = State.normal 271 | private var _size: CGSize? 272 | 273 | 274 | func playSound(clickSound: Bool) { 275 | guard soundOn, 276 | let soundName = clickSound ? clickSoundName : disableSoundName else { 277 | return 278 | } 279 | 280 | let soundAct = SKAction.playSoundFileNamed(soundName, waitForCompletion: false) 281 | self.run(soundAct) 282 | } 283 | 284 | 285 | /* 286 | * Init 287 | */ 288 | 289 | // Button with images 290 | init(buttonType: ButtonType = .normal, 291 | normalImageNamed: String, 292 | highlightedImageNamed: String? = nil, 293 | disabledImageNamed: String? = nil, 294 | size: CGSize? = nil, 295 | clickSoundName: String? = nil, 296 | disableSoundName: String? = nil, 297 | buttonFunc: ((_ button: SgButton) -> Void)? = nil) { 298 | 299 | let record = Record(imageFileName: normalImageNamed) 300 | self.buttonFunc = buttonFunc 301 | 302 | super.init(texture: record.generatedImageTexture, 303 | color: UIColor.clear, 304 | size: record.generatedImageTexture!.size()) 305 | 306 | records[ .normal ] = record 307 | 308 | self.buttonType = buttonType 309 | self.clickSoundName = clickSoundName 310 | self.disableSoundName = disableSoundName 311 | 312 | if highlightedImageNamed != nil { 313 | records[ .highlighted ] = Record(imageFileName: highlightedImageNamed!) 314 | } 315 | 316 | if disabledImageNamed != nil { 317 | records[ .disabled ] = Record(imageFileName: disabledImageNamed!) 318 | } 319 | 320 | completeInit() 321 | } 322 | 323 | // Button with textures 324 | init(buttonType: ButtonType = .normal, 325 | normalTexture: SKTexture, 326 | highlightedTexture: SKTexture? = nil, 327 | disabledTexture: SKTexture? = nil, 328 | clickSoundName: String? = nil, 329 | disableSoundName: String? = nil, 330 | buttonFunc: ((_ button: SgButton) -> Void)? = nil) { 331 | 332 | let record = Record(texture: normalTexture) 333 | 334 | self.buttonFunc = buttonFunc 335 | 336 | super.init(texture: record.generatedImageTexture, 337 | color: UIColor.clear, 338 | size: record.generatedImageTexture!.size()) 339 | 340 | records[ .normal ] = record 341 | 342 | self.buttonType = buttonType 343 | self.clickSoundName = clickSoundName 344 | self.disableSoundName = disableSoundName 345 | 346 | if highlightedTexture != nil { 347 | records[ .highlighted ] = Record(texture: highlightedTexture!) 348 | } 349 | 350 | if disabledTexture != nil { 351 | records[ .disabled ] = Record(texture: disabledTexture!) 352 | } 353 | 354 | completeInit() 355 | } 356 | 357 | // Button with string 358 | init(buttonType: ButtonType = .normal, 359 | normalString: String, 360 | normalStringColor: UIColor = UIColor.white, 361 | normalBackgroundColor: UIColor = UIColor.blue, 362 | 363 | highlightedString: String? = nil, 364 | highlightedStringColor: UIColor? = UIColor.yellow, 365 | highlightedBackgroundColor: UIColor? = UIColor.green, 366 | 367 | disabledString: String? = nil, 368 | disabledStringColor: UIColor? = UIColor.black, 369 | disabledBackgroundColor: UIColor? = UIColor.gray, 370 | 371 | fontName: String? = nil, 372 | fontSize: CGFloat? = nil, 373 | size: CGSize? = nil, 374 | cornerRadius: CGFloat? = nil, 375 | 376 | clickSoundName: String? = nil, 377 | disableSoundName: String? = nil, 378 | buttonFunc: ((_ button: SgButton) -> Void)? = nil) { 379 | 380 | let record = Record() 381 | record.string = normalString 382 | record.stringColor = normalStringColor 383 | record.fontName = fontName 384 | record.fontSize = fontSize 385 | record.backgroundColor = normalBackgroundColor 386 | record.buttonSize = size 387 | record.cornerRadius = cornerRadius 388 | record.generateTexture() 389 | 390 | self.buttonFunc = buttonFunc 391 | 392 | super.init(texture: record.generatedImageTexture, 393 | color: UIColor.clear, 394 | size: record.generatedImageTexture!.size()) 395 | 396 | records[ .normal ] = record 397 | 398 | self.buttonType = buttonType 399 | self.clickSoundName = clickSoundName 400 | self.disableSoundName = disableSoundName 401 | 402 | _size = size 403 | 404 | if highlightedString?.isEmpty == true 405 | || highlightedStringColor != nil 406 | || highlightedBackgroundColor != nil { 407 | let record = Record() 408 | record.string = highlightedString ?? normalString 409 | record.stringColor = highlightedStringColor ?? normalStringColor 410 | record.fontName = fontName 411 | record.fontSize = fontSize 412 | record.backgroundColor = highlightedBackgroundColor ?? normalStringColor 413 | record.buttonSize = size 414 | record.cornerRadius = cornerRadius 415 | record.generateTexture() 416 | records[ .highlighted ] = record 417 | } 418 | 419 | if disabledString?.isEmpty == true 420 | || disabledStringColor != nil 421 | || disabledBackgroundColor != nil { 422 | let record = Record() 423 | record.string = disabledString ?? normalString 424 | record.stringColor = disabledStringColor ?? normalStringColor 425 | record.fontName = fontName 426 | record.fontSize = fontSize 427 | record.backgroundColor = disabledBackgroundColor ?? normalStringColor 428 | record.buttonSize = size 429 | record.cornerRadius = cornerRadius 430 | record.generateTexture() 431 | records[ .disabled ] = record 432 | } 433 | 434 | completeInit() 435 | } 436 | 437 | /* 438 | * Methods 439 | */ 440 | var disabled: Bool { 441 | set { 442 | isDisabled = newValue 443 | state = isDisabled ? .disabled : .normal 444 | 445 | if newValue { 446 | playSound(clickSound: false) 447 | } 448 | } 449 | 450 | get { 451 | return self.isDisabled 452 | } 453 | } 454 | 455 | var state: State { 456 | get { 457 | return self._state 458 | } 459 | 460 | set { 461 | _state = newValue 462 | if let tex = records[newValue]?.generatedImageTexture { 463 | self.texture = tex 464 | } 465 | } 466 | } 467 | 468 | 469 | func setString(state: State, string: String, fontName: String? = nil, fontSize: CGFloat? = nil, stringColor: UIColor? = nil, backgroundColor: UIColor? = nil, size: CGSize? = nil, cornerRadius: CGFloat? = nil) { 470 | var record = records[ state ] 471 | if record == nil { 472 | record = Record() 473 | records[ state ] = record 474 | } 475 | record?.string = string 476 | 477 | /* 478 | * copy data from normal state if current is nil 479 | */ 480 | record!.fontName = fontName != nil ? fontName : records[ .normal ]?.fontName 481 | record!.fontSize = fontSize != nil ? fontSize : records[ .normal ]?.fontSize 482 | record!.stringColor = stringColor != nil ? stringColor : records[ .normal ]?.stringColor 483 | record!.backgroundColor = backgroundColor != nil ? backgroundColor : records[ .normal ]?.backgroundColor 484 | record!.buttonSize = size != nil ? size : records[ .normal ]?.buttonSize 485 | record!.cornerRadius = cornerRadius != nil ? cornerRadius : records[ .normal ]?.cornerRadius 486 | 487 | /* 488 | * copy background from normal state if current one is not enough info 489 | */ 490 | if backgroundColor == nil && state != .normal && record!.imageFileName == nil && record!.imageTexture == nil { 491 | record!.imageFileName = records[ .normal ]?.imageFileName 492 | record!.imageTexture = records[ .normal ]?.imageTexture 493 | } 494 | 495 | record!.generateTexture() 496 | 497 | // update current texture 498 | if self.state == state { 499 | self.state = state 500 | } 501 | } 502 | 503 | func setImage(state: State, imageFileName: String) { 504 | var record = records[ state ] 505 | if record == nil { 506 | record = Record() 507 | records[ state ] = record 508 | } 509 | 510 | record!.imageFileName = imageFileName 511 | 512 | record!.generateTexture() 513 | 514 | // update current texture 515 | self.state = state 516 | } 517 | 518 | func setTexture(state: State, texture: SKTexture) { 519 | var record = records[ state ] 520 | if record == nil { 521 | record = Record() 522 | records[ state ] = record 523 | } 524 | 525 | record!.imageTexture = texture 526 | 527 | record!.generateTexture() 528 | 529 | // update current texture 530 | self.state = state 531 | } 532 | 533 | private func completeInit() { 534 | self.isUserInteractionEnabled = true 535 | self.name = buttonName 536 | } 537 | 538 | /* 539 | * Needed to stop XCode warnings 540 | */ 541 | required init?(coder aDecoder: NSCoder) { 542 | fatalError("init(coder:) has not been implemented") 543 | } 544 | 545 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 546 | if !isDisabled { 547 | if buttonType == .flip { 548 | state = state == .normal ? .highlighted : .normal 549 | } else { 550 | state = .highlighted 551 | } 552 | } 553 | } 554 | 555 | override func touchesEnded(_ touches: Set, with event: UIEvent?) { 556 | if !isDisabled { 557 | if buttonType != .flip { 558 | state = .normal 559 | } 560 | 561 | if buttonFunc != nil { 562 | if let touch = touches.first { 563 | let location = touch.location(in: parent!) 564 | if self.contains(location) { 565 | playSound(clickSound: true) 566 | buttonFunc!(self) 567 | } 568 | } 569 | } 570 | } 571 | } 572 | 573 | override func touchesCancelled(_ touches: Set?, with event: UIEvent?) { 574 | if !isDisabled && buttonType != .flip { 575 | state = .normal 576 | } 577 | } 578 | 579 | } 580 | -------------------------------------------------------------------------------- /SgButtonDemo/SgButtonDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B1D0224929CB137F00B9E20E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D0224829CB137F00B9E20E /* AppDelegate.swift */; }; 11 | B1D0224D29CB137F00B9E20E /* Actions.sks in Resources */ = {isa = PBXBuildFile; fileRef = B1D0224C29CB137F00B9E20E /* Actions.sks */; }; 12 | B1D0224F29CB137F00B9E20E /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D0224E29CB137F00B9E20E /* GameScene.swift */; }; 13 | B1D0225129CB137F00B9E20E /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D0225029CB137F00B9E20E /* GameViewController.swift */; }; 14 | B1D0225429CB137F00B9E20E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1D0225229CB137F00B9E20E /* Main.storyboard */; }; 15 | B1D0225629CB138400B9E20E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B1D0225529CB138400B9E20E /* Assets.xcassets */; }; 16 | B1D0225929CB138400B9E20E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1D0225729CB138400B9E20E /* LaunchScreen.storyboard */; }; 17 | B1D0227129CB13BE00B9E20E /* buy_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226029CB13BC00B9E20E /* buy_d.png */; }; 18 | B1D0227229CB13BE00B9E20E /* buy.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226129CB13BC00B9E20E /* buy.png */; }; 19 | B1D0227329CB13BE00B9E20E /* back@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226229CB13BC00B9E20E /* back@2x.png */; }; 20 | B1D0227429CB13BE00B9E20E /* bkbtn.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226329CB13BC00B9E20E /* bkbtn.png */; }; 21 | B1D0227529CB13BE00B9E20E /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D0226429CB13BC00B9E20E /* Buttons.swift */; }; 22 | B1D0227629CB13BE00B9E20E /* back_x@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226529CB13BC00B9E20E /* back_x@2x.png */; }; 23 | B1D0227729CB13BE00B9E20E /* back_d@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226629CB13BC00B9E20E /* back_d@2x.png */; }; 24 | B1D0227829CB13BE00B9E20E /* buttons.1.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226829CB13BC00B9E20E /* buttons.1.png */; }; 25 | B1D0227929CB13BE00B9E20E /* buttons.plist in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226929CB13BC00B9E20E /* buttons.plist */; }; 26 | B1D0227A29CB13BE00B9E20E /* buttons.1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226A29CB13BC00B9E20E /* buttons.1@2x.png */; }; 27 | B1D0227B29CB13BE00B9E20E /* buttons.1@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226B29CB13BC00B9E20E /* buttons.1@3x.png */; }; 28 | B1D0227C29CB13BE00B9E20E /* click.wav in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226C29CB13BC00B9E20E /* click.wav */; }; 29 | B1D0227D29CB13BE00B9E20E /* bkbtn_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226D29CB13BC00B9E20E /* bkbtn_d.png */; }; 30 | B1D0227E29CB13BE00B9E20E /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = B1D0226E29CB13BD00B9E20E /* README.md */; }; 31 | B1D0227F29CB13BE00B9E20E /* SgButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D0227029CB13BD00B9E20E /* SgButton.swift */; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | B1D0224529CB137F00B9E20E /* SgButtonDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SgButtonDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | B1D0224829CB137F00B9E20E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | B1D0224C29CB137F00B9E20E /* Actions.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Actions.sks; sourceTree = ""; }; 38 | B1D0224E29CB137F00B9E20E /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; }; 39 | B1D0225029CB137F00B9E20E /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; }; 40 | B1D0225329CB137F00B9E20E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | B1D0225529CB138400B9E20E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 42 | B1D0225829CB138400B9E20E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 43 | B1D0226029CB13BC00B9E20E /* buy_d.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buy_d.png; sourceTree = ""; }; 44 | B1D0226129CB13BC00B9E20E /* buy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buy.png; sourceTree = ""; }; 45 | B1D0226229CB13BC00B9E20E /* back@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back@2x.png"; sourceTree = ""; }; 46 | B1D0226329CB13BC00B9E20E /* bkbtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bkbtn.png; sourceTree = ""; }; 47 | B1D0226429CB13BC00B9E20E /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = ""; }; 48 | B1D0226529CB13BC00B9E20E /* back_x@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back_x@2x.png"; sourceTree = ""; }; 49 | B1D0226629CB13BC00B9E20E /* back_d@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back_d@2x.png"; sourceTree = ""; }; 50 | B1D0226829CB13BC00B9E20E /* buttons.1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttons.1.png; sourceTree = ""; }; 51 | B1D0226929CB13BC00B9E20E /* buttons.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = buttons.plist; sourceTree = ""; }; 52 | B1D0226A29CB13BC00B9E20E /* buttons.1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttons.1@2x.png"; sourceTree = ""; }; 53 | B1D0226B29CB13BC00B9E20E /* buttons.1@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttons.1@3x.png"; sourceTree = ""; }; 54 | B1D0226C29CB13BC00B9E20E /* click.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = click.wav; sourceTree = ""; }; 55 | B1D0226D29CB13BC00B9E20E /* bkbtn_d.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bkbtn_d.png; sourceTree = ""; }; 56 | B1D0226E29CB13BD00B9E20E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../../README.md; sourceTree = ""; }; 57 | B1D0227029CB13BD00B9E20E /* SgButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SgButton.swift; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | B1D0224229CB137F00B9E20E /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | B1D0223C29CB137E00B9E20E = { 72 | isa = PBXGroup; 73 | children = ( 74 | B1D0224729CB137F00B9E20E /* SgButtonDemo */, 75 | B1D0224629CB137F00B9E20E /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | B1D0224629CB137F00B9E20E /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | B1D0224529CB137F00B9E20E /* SgButtonDemo.app */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | B1D0224729CB137F00B9E20E /* SgButtonDemo */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | B1D0225F29CB13BC00B9E20E /* BtnResources */, 91 | B1D0226E29CB13BD00B9E20E /* README.md */, 92 | B1D0226F29CB13BD00B9E20E /* SgButton */, 93 | B1D0224829CB137F00B9E20E /* AppDelegate.swift */, 94 | B1D0224C29CB137F00B9E20E /* Actions.sks */, 95 | B1D0224E29CB137F00B9E20E /* GameScene.swift */, 96 | B1D0225029CB137F00B9E20E /* GameViewController.swift */, 97 | B1D0225229CB137F00B9E20E /* Main.storyboard */, 98 | B1D0225529CB138400B9E20E /* Assets.xcassets */, 99 | B1D0225729CB138400B9E20E /* LaunchScreen.storyboard */, 100 | ); 101 | path = SgButtonDemo; 102 | sourceTree = ""; 103 | }; 104 | B1D0225F29CB13BC00B9E20E /* BtnResources */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | B1D0226029CB13BC00B9E20E /* buy_d.png */, 108 | B1D0226129CB13BC00B9E20E /* buy.png */, 109 | B1D0226229CB13BC00B9E20E /* back@2x.png */, 110 | B1D0226329CB13BC00B9E20E /* bkbtn.png */, 111 | B1D0226429CB13BC00B9E20E /* Buttons.swift */, 112 | B1D0226529CB13BC00B9E20E /* back_x@2x.png */, 113 | B1D0226629CB13BC00B9E20E /* back_d@2x.png */, 114 | B1D0226729CB13BC00B9E20E /* buttons.atlasc */, 115 | B1D0226C29CB13BC00B9E20E /* click.wav */, 116 | B1D0226D29CB13BC00B9E20E /* bkbtn_d.png */, 117 | ); 118 | name = BtnResources; 119 | path = ../../BtnResources; 120 | sourceTree = ""; 121 | }; 122 | B1D0226729CB13BC00B9E20E /* buttons.atlasc */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | B1D0226829CB13BC00B9E20E /* buttons.1.png */, 126 | B1D0226929CB13BC00B9E20E /* buttons.plist */, 127 | B1D0226A29CB13BC00B9E20E /* buttons.1@2x.png */, 128 | B1D0226B29CB13BC00B9E20E /* buttons.1@3x.png */, 129 | ); 130 | path = buttons.atlasc; 131 | sourceTree = ""; 132 | }; 133 | B1D0226F29CB13BD00B9E20E /* SgButton */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | B1D0227029CB13BD00B9E20E /* SgButton.swift */, 137 | ); 138 | name = SgButton; 139 | path = ../../SgButton; 140 | sourceTree = ""; 141 | }; 142 | /* End PBXGroup section */ 143 | 144 | /* Begin PBXNativeTarget section */ 145 | B1D0224429CB137F00B9E20E /* SgButtonDemo */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = B1D0225C29CB138400B9E20E /* Build configuration list for PBXNativeTarget "SgButtonDemo" */; 148 | buildPhases = ( 149 | B1D0224129CB137F00B9E20E /* Sources */, 150 | B1D0224229CB137F00B9E20E /* Frameworks */, 151 | B1D0224329CB137F00B9E20E /* Resources */, 152 | ); 153 | buildRules = ( 154 | ); 155 | dependencies = ( 156 | ); 157 | name = SgButtonDemo; 158 | productName = SgButtonDemo; 159 | productReference = B1D0224529CB137F00B9E20E /* SgButtonDemo.app */; 160 | productType = "com.apple.product-type.application"; 161 | }; 162 | /* End PBXNativeTarget section */ 163 | 164 | /* Begin PBXProject section */ 165 | B1D0223D29CB137E00B9E20E /* Project object */ = { 166 | isa = PBXProject; 167 | attributes = { 168 | BuildIndependentTargetsInParallel = 1; 169 | LastSwiftUpdateCheck = 1420; 170 | LastUpgradeCheck = 1420; 171 | TargetAttributes = { 172 | B1D0224429CB137F00B9E20E = { 173 | CreatedOnToolsVersion = 14.2; 174 | }; 175 | }; 176 | }; 177 | buildConfigurationList = B1D0224029CB137E00B9E20E /* Build configuration list for PBXProject "SgButtonDemo" */; 178 | compatibilityVersion = "Xcode 14.0"; 179 | developmentRegion = en; 180 | hasScannedForEncodings = 0; 181 | knownRegions = ( 182 | en, 183 | Base, 184 | ); 185 | mainGroup = B1D0223C29CB137E00B9E20E; 186 | productRefGroup = B1D0224629CB137F00B9E20E /* Products */; 187 | projectDirPath = ""; 188 | projectRoot = ""; 189 | targets = ( 190 | B1D0224429CB137F00B9E20E /* SgButtonDemo */, 191 | ); 192 | }; 193 | /* End PBXProject section */ 194 | 195 | /* Begin PBXResourcesBuildPhase section */ 196 | B1D0224329CB137F00B9E20E /* Resources */ = { 197 | isa = PBXResourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | B1D0225429CB137F00B9E20E /* Main.storyboard in Resources */, 201 | B1D0227A29CB13BE00B9E20E /* buttons.1@2x.png in Resources */, 202 | B1D0227729CB13BE00B9E20E /* back_d@2x.png in Resources */, 203 | B1D0227329CB13BE00B9E20E /* back@2x.png in Resources */, 204 | B1D0227B29CB13BE00B9E20E /* buttons.1@3x.png in Resources */, 205 | B1D0227429CB13BE00B9E20E /* bkbtn.png in Resources */, 206 | B1D0227E29CB13BE00B9E20E /* README.md in Resources */, 207 | B1D0227D29CB13BE00B9E20E /* bkbtn_d.png in Resources */, 208 | B1D0227229CB13BE00B9E20E /* buy.png in Resources */, 209 | B1D0225629CB138400B9E20E /* Assets.xcassets in Resources */, 210 | B1D0227629CB13BE00B9E20E /* back_x@2x.png in Resources */, 211 | B1D0225929CB138400B9E20E /* LaunchScreen.storyboard in Resources */, 212 | B1D0227C29CB13BE00B9E20E /* click.wav in Resources */, 213 | B1D0224D29CB137F00B9E20E /* Actions.sks in Resources */, 214 | B1D0227829CB13BE00B9E20E /* buttons.1.png in Resources */, 215 | B1D0227129CB13BE00B9E20E /* buy_d.png in Resources */, 216 | B1D0227929CB13BE00B9E20E /* buttons.plist in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | B1D0224129CB137F00B9E20E /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | B1D0224F29CB137F00B9E20E /* GameScene.swift in Sources */, 228 | B1D0225129CB137F00B9E20E /* GameViewController.swift in Sources */, 229 | B1D0224929CB137F00B9E20E /* AppDelegate.swift in Sources */, 230 | B1D0227F29CB13BE00B9E20E /* SgButton.swift in Sources */, 231 | B1D0227529CB13BE00B9E20E /* Buttons.swift in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | B1D0225229CB137F00B9E20E /* Main.storyboard */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | B1D0225329CB137F00B9E20E /* Base */, 242 | ); 243 | name = Main.storyboard; 244 | sourceTree = ""; 245 | }; 246 | B1D0225729CB138400B9E20E /* LaunchScreen.storyboard */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | B1D0225829CB138400B9E20E /* Base */, 250 | ); 251 | name = LaunchScreen.storyboard; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXVariantGroup section */ 255 | 256 | /* Begin XCBuildConfiguration section */ 257 | B1D0225A29CB138400B9E20E /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_ENABLE_OBJC_WEAK = YES; 267 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_COMMA = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INFINITE_RECURSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 279 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 280 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 281 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 282 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 283 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 284 | CLANG_WARN_STRICT_PROTOTYPES = YES; 285 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 286 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 287 | CLANG_WARN_UNREACHABLE_CODE = YES; 288 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 289 | COPY_PHASE_STRIP = NO; 290 | DEBUG_INFORMATION_FORMAT = dwarf; 291 | ENABLE_STRICT_OBJC_MSGSEND = YES; 292 | ENABLE_TESTABILITY = YES; 293 | GCC_C_LANGUAGE_STANDARD = gnu11; 294 | GCC_DYNAMIC_NO_PIC = NO; 295 | GCC_NO_COMMON_BLOCKS = YES; 296 | GCC_OPTIMIZATION_LEVEL = 0; 297 | GCC_PREPROCESSOR_DEFINITIONS = ( 298 | "DEBUG=1", 299 | "$(inherited)", 300 | ); 301 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 302 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 303 | GCC_WARN_UNDECLARED_SELECTOR = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 305 | GCC_WARN_UNUSED_FUNCTION = YES; 306 | GCC_WARN_UNUSED_VARIABLE = YES; 307 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 308 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 309 | MTL_FAST_MATH = YES; 310 | ONLY_ACTIVE_ARCH = YES; 311 | SDKROOT = iphoneos; 312 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 313 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 314 | }; 315 | name = Debug; 316 | }; 317 | B1D0225B29CB138400B9E20E /* Release */ = { 318 | isa = XCBuildConfiguration; 319 | buildSettings = { 320 | ALWAYS_SEARCH_USER_PATHS = NO; 321 | CLANG_ANALYZER_NONNULL = YES; 322 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 323 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 324 | CLANG_ENABLE_MODULES = YES; 325 | CLANG_ENABLE_OBJC_ARC = YES; 326 | CLANG_ENABLE_OBJC_WEAK = YES; 327 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 328 | CLANG_WARN_BOOL_CONVERSION = YES; 329 | CLANG_WARN_COMMA = YES; 330 | CLANG_WARN_CONSTANT_CONVERSION = YES; 331 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 332 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 333 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 334 | CLANG_WARN_EMPTY_BODY = YES; 335 | CLANG_WARN_ENUM_CONVERSION = YES; 336 | CLANG_WARN_INFINITE_RECURSION = YES; 337 | CLANG_WARN_INT_CONVERSION = YES; 338 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 339 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 340 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 342 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 344 | CLANG_WARN_STRICT_PROTOTYPES = YES; 345 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 346 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 347 | CLANG_WARN_UNREACHABLE_CODE = YES; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | COPY_PHASE_STRIP = NO; 350 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 351 | ENABLE_NS_ASSERTIONS = NO; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu11; 354 | GCC_NO_COMMON_BLOCKS = YES; 355 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 356 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 357 | GCC_WARN_UNDECLARED_SELECTOR = YES; 358 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 359 | GCC_WARN_UNUSED_FUNCTION = YES; 360 | GCC_WARN_UNUSED_VARIABLE = YES; 361 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 362 | MTL_ENABLE_DEBUG_INFO = NO; 363 | MTL_FAST_MATH = YES; 364 | SDKROOT = iphoneos; 365 | SWIFT_COMPILATION_MODE = wholemodule; 366 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 367 | VALIDATE_PRODUCT = YES; 368 | }; 369 | name = Release; 370 | }; 371 | B1D0225D29CB138400B9E20E /* Debug */ = { 372 | isa = XCBuildConfiguration; 373 | buildSettings = { 374 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 375 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 376 | CODE_SIGN_STYLE = Automatic; 377 | CURRENT_PROJECT_VERSION = 1; 378 | DEVELOPMENT_TEAM = 3FHDXJ5CB2; 379 | GENERATE_INFOPLIST_FILE = YES; 380 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 381 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 382 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 383 | INFOPLIST_KEY_UIStatusBarHidden = YES; 384 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 385 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 386 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 387 | LD_RUNPATH_SEARCH_PATHS = ( 388 | "$(inherited)", 389 | "@executable_path/Frameworks", 390 | ); 391 | MARKETING_VERSION = 1.0; 392 | PRODUCT_BUNDLE_IDENTIFIER = com.xqfan.SgButtonDemo; 393 | PRODUCT_NAME = "$(TARGET_NAME)"; 394 | SWIFT_EMIT_LOC_STRINGS = YES; 395 | SWIFT_VERSION = 5.0; 396 | TARGETED_DEVICE_FAMILY = "1,2"; 397 | }; 398 | name = Debug; 399 | }; 400 | B1D0225E29CB138400B9E20E /* Release */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 404 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 405 | CODE_SIGN_STYLE = Automatic; 406 | CURRENT_PROJECT_VERSION = 1; 407 | DEVELOPMENT_TEAM = 3FHDXJ5CB2; 408 | GENERATE_INFOPLIST_FILE = YES; 409 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 410 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 411 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 412 | INFOPLIST_KEY_UIStatusBarHidden = YES; 413 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 414 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 415 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 416 | LD_RUNPATH_SEARCH_PATHS = ( 417 | "$(inherited)", 418 | "@executable_path/Frameworks", 419 | ); 420 | MARKETING_VERSION = 1.0; 421 | PRODUCT_BUNDLE_IDENTIFIER = com.xqfan.SgButtonDemo; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | SWIFT_EMIT_LOC_STRINGS = YES; 424 | SWIFT_VERSION = 5.0; 425 | TARGETED_DEVICE_FAMILY = "1,2"; 426 | }; 427 | name = Release; 428 | }; 429 | /* End XCBuildConfiguration section */ 430 | 431 | /* Begin XCConfigurationList section */ 432 | B1D0224029CB137E00B9E20E /* Build configuration list for PBXProject "SgButtonDemo" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | B1D0225A29CB138400B9E20E /* Debug */, 436 | B1D0225B29CB138400B9E20E /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | B1D0225C29CB138400B9E20E /* Build configuration list for PBXNativeTarget "SgButtonDemo" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | B1D0225D29CB138400B9E20E /* Debug */, 445 | B1D0225E29CB138400B9E20E /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | /* End XCConfigurationList section */ 451 | }; 452 | rootObject = B1D0223D29CB137E00B9E20E /* Project object */; 453 | } 454 | -------------------------------------------------------------------------------- /SgButtonDemoIOS/SgButtonDemoIOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B129DF6C1AA2E7AE0013334E /* back@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF5F1AA2E7AE0013334E /* back@2x.png */; }; 11 | B129DF6D1AA2E7AE0013334E /* back@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF5F1AA2E7AE0013334E /* back@2x.png */; }; 12 | B129DF6E1AA2E7AE0013334E /* back_d@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF601AA2E7AE0013334E /* back_d@2x.png */; }; 13 | B129DF6F1AA2E7AE0013334E /* back_d@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF601AA2E7AE0013334E /* back_d@2x.png */; }; 14 | B129DF701AA2E7AE0013334E /* back_x@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF611AA2E7AE0013334E /* back_x@2x.png */; }; 15 | B129DF711AA2E7AE0013334E /* back_x@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF611AA2E7AE0013334E /* back_x@2x.png */; }; 16 | B129DF721AA2E7AE0013334E /* bkbtn.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF621AA2E7AE0013334E /* bkbtn.png */; }; 17 | B129DF731AA2E7AE0013334E /* bkbtn.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF621AA2E7AE0013334E /* bkbtn.png */; }; 18 | B129DF741AA2E7AE0013334E /* bkbtn_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF631AA2E7AE0013334E /* bkbtn_d.png */; }; 19 | B129DF751AA2E7AE0013334E /* bkbtn_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF631AA2E7AE0013334E /* bkbtn_d.png */; }; 20 | B129DF761AA2E7AE0013334E /* buttons.1.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF651AA2E7AE0013334E /* buttons.1.png */; }; 21 | B129DF771AA2E7AE0013334E /* buttons.1.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF651AA2E7AE0013334E /* buttons.1.png */; }; 22 | B129DF781AA2E7AE0013334E /* buttons.1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF661AA2E7AE0013334E /* buttons.1@2x.png */; }; 23 | B129DF791AA2E7AE0013334E /* buttons.1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF661AA2E7AE0013334E /* buttons.1@2x.png */; }; 24 | B129DF7A1AA2E7AE0013334E /* buttons.1@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF671AA2E7AE0013334E /* buttons.1@3x.png */; }; 25 | B129DF7B1AA2E7AE0013334E /* buttons.1@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF671AA2E7AE0013334E /* buttons.1@3x.png */; }; 26 | B129DF7C1AA2E7AE0013334E /* buttons.plist in Resources */ = {isa = PBXBuildFile; fileRef = B129DF681AA2E7AE0013334E /* buttons.plist */; }; 27 | B129DF7D1AA2E7AE0013334E /* buttons.plist in Resources */ = {isa = PBXBuildFile; fileRef = B129DF681AA2E7AE0013334E /* buttons.plist */; }; 28 | B129DF7E1AA2E7AE0013334E /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B129DF691AA2E7AE0013334E /* Buttons.swift */; }; 29 | B129DF7F1AA2E7AE0013334E /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B129DF691AA2E7AE0013334E /* Buttons.swift */; }; 30 | B129DF801AA2E7AE0013334E /* buy.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF6A1AA2E7AE0013334E /* buy.png */; }; 31 | B129DF811AA2E7AE0013334E /* buy.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF6A1AA2E7AE0013334E /* buy.png */; }; 32 | B129DF821AA2E7AE0013334E /* buy_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF6B1AA2E7AE0013334E /* buy_d.png */; }; 33 | B129DF831AA2E7AE0013334E /* buy_d.png in Resources */ = {isa = PBXBuildFile; fileRef = B129DF6B1AA2E7AE0013334E /* buy_d.png */; }; 34 | B15331551A9FE49A0026FE28 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15331541A9FE49A0026FE28 /* AppDelegate.swift */; }; 35 | B15331591A9FE49A0026FE28 /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15331581A9FE49A0026FE28 /* GameScene.swift */; }; 36 | B153315B1A9FE49A0026FE28 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B153315A1A9FE49A0026FE28 /* GameViewController.swift */; }; 37 | B153315E1A9FE49A0026FE28 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B153315C1A9FE49A0026FE28 /* Main.storyboard */; }; 38 | B15331631A9FE49A0026FE28 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B15331611A9FE49A0026FE28 /* LaunchScreen.xib */; }; 39 | B153316F1A9FE49A0026FE28 /* SgButtonDemoIOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B153316E1A9FE49A0026FE28 /* SgButtonDemoIOSTests.swift */; }; 40 | B15331A41A9FEAEA0026FE28 /* SgButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B153318B1A9FEAEA0026FE28 /* SgButton.swift */; }; 41 | B15331A51A9FEAEA0026FE28 /* SgButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B153318B1A9FEAEA0026FE28 /* SgButton.swift */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXContainerItemProxy section */ 45 | B15331691A9FE49A0026FE28 /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = B15331471A9FE49A0026FE28 /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = B153314E1A9FE49A0026FE28; 50 | remoteInfo = SgButtonDemoIOS; 51 | }; 52 | /* End PBXContainerItemProxy section */ 53 | 54 | /* Begin PBXFileReference section */ 55 | B129DF5F1AA2E7AE0013334E /* back@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back@2x.png"; sourceTree = ""; }; 56 | B129DF601AA2E7AE0013334E /* back_d@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back_d@2x.png"; sourceTree = ""; }; 57 | B129DF611AA2E7AE0013334E /* back_x@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "back_x@2x.png"; sourceTree = ""; }; 58 | B129DF621AA2E7AE0013334E /* bkbtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bkbtn.png; sourceTree = ""; }; 59 | B129DF631AA2E7AE0013334E /* bkbtn_d.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bkbtn_d.png; sourceTree = ""; }; 60 | B129DF651AA2E7AE0013334E /* buttons.1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttons.1.png; sourceTree = ""; }; 61 | B129DF661AA2E7AE0013334E /* buttons.1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttons.1@2x.png"; sourceTree = ""; }; 62 | B129DF671AA2E7AE0013334E /* buttons.1@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttons.1@3x.png"; sourceTree = ""; }; 63 | B129DF681AA2E7AE0013334E /* buttons.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = buttons.plist; sourceTree = ""; }; 64 | B129DF691AA2E7AE0013334E /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = ""; }; 65 | B129DF6A1AA2E7AE0013334E /* buy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buy.png; sourceTree = ""; }; 66 | B129DF6B1AA2E7AE0013334E /* buy_d.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buy_d.png; sourceTree = ""; }; 67 | B153314F1A9FE49A0026FE28 /* SgButtonDemoIOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SgButtonDemoIOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | B15331531A9FE49A0026FE28 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | B15331541A9FE49A0026FE28 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 70 | B15331581A9FE49A0026FE28 /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; }; 71 | B153315A1A9FE49A0026FE28 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; }; 72 | B153315D1A9FE49A0026FE28 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 73 | B15331621A9FE49A0026FE28 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 74 | B15331681A9FE49A0026FE28 /* SgButtonDemoIOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SgButtonDemoIOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 75 | B153316D1A9FE49A0026FE28 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 76 | B153316E1A9FE49A0026FE28 /* SgButtonDemoIOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SgButtonDemoIOSTests.swift; sourceTree = ""; }; 77 | B153318B1A9FEAEA0026FE28 /* SgButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SgButton.swift; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | B153314C1A9FE49A0026FE28 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | B15331651A9FE49A0026FE28 /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | /* End PBXFrameworksBuildPhase section */ 96 | 97 | /* Begin PBXGroup section */ 98 | B129DF5E1AA2E7AE0013334E /* BtnResources */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | B129DF5F1AA2E7AE0013334E /* back@2x.png */, 102 | B129DF601AA2E7AE0013334E /* back_d@2x.png */, 103 | B129DF611AA2E7AE0013334E /* back_x@2x.png */, 104 | B129DF621AA2E7AE0013334E /* bkbtn.png */, 105 | B129DF631AA2E7AE0013334E /* bkbtn_d.png */, 106 | B129DF641AA2E7AE0013334E /* buttons.atlasc */, 107 | B129DF691AA2E7AE0013334E /* Buttons.swift */, 108 | B129DF6A1AA2E7AE0013334E /* buy.png */, 109 | B129DF6B1AA2E7AE0013334E /* buy_d.png */, 110 | ); 111 | name = BtnResources; 112 | path = ../../BtnResources; 113 | sourceTree = ""; 114 | }; 115 | B129DF641AA2E7AE0013334E /* buttons.atlasc */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | B129DF651AA2E7AE0013334E /* buttons.1.png */, 119 | B129DF661AA2E7AE0013334E /* buttons.1@2x.png */, 120 | B129DF671AA2E7AE0013334E /* buttons.1@3x.png */, 121 | B129DF681AA2E7AE0013334E /* buttons.plist */, 122 | ); 123 | path = buttons.atlasc; 124 | sourceTree = ""; 125 | }; 126 | B15331461A9FE49A0026FE28 = { 127 | isa = PBXGroup; 128 | children = ( 129 | B15331511A9FE49A0026FE28 /* SgButtonDemoIOS */, 130 | B153316B1A9FE49A0026FE28 /* SgButtonDemoIOSTests */, 131 | B15331501A9FE49A0026FE28 /* Products */, 132 | ); 133 | sourceTree = ""; 134 | }; 135 | B15331501A9FE49A0026FE28 /* Products */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | B153314F1A9FE49A0026FE28 /* SgButtonDemoIOS.app */, 139 | B15331681A9FE49A0026FE28 /* SgButtonDemoIOSTests.xctest */, 140 | ); 141 | name = Products; 142 | sourceTree = ""; 143 | }; 144 | B15331511A9FE49A0026FE28 /* SgButtonDemoIOS */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | B153318A1A9FEAEA0026FE28 /* SgButton */, 148 | B129DF5E1AA2E7AE0013334E /* BtnResources */, 149 | B15331541A9FE49A0026FE28 /* AppDelegate.swift */, 150 | B15331581A9FE49A0026FE28 /* GameScene.swift */, 151 | B153315A1A9FE49A0026FE28 /* GameViewController.swift */, 152 | B153315C1A9FE49A0026FE28 /* Main.storyboard */, 153 | B15331611A9FE49A0026FE28 /* LaunchScreen.xib */, 154 | B15331521A9FE49A0026FE28 /* Supporting Files */, 155 | ); 156 | path = SgButtonDemoIOS; 157 | sourceTree = ""; 158 | }; 159 | B15331521A9FE49A0026FE28 /* Supporting Files */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | B15331531A9FE49A0026FE28 /* Info.plist */, 163 | ); 164 | name = "Supporting Files"; 165 | sourceTree = ""; 166 | }; 167 | B153316B1A9FE49A0026FE28 /* SgButtonDemoIOSTests */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | B153316E1A9FE49A0026FE28 /* SgButtonDemoIOSTests.swift */, 171 | B153316C1A9FE49A0026FE28 /* Supporting Files */, 172 | ); 173 | path = SgButtonDemoIOSTests; 174 | sourceTree = ""; 175 | }; 176 | B153316C1A9FE49A0026FE28 /* Supporting Files */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | B153316D1A9FE49A0026FE28 /* Info.plist */, 180 | ); 181 | name = "Supporting Files"; 182 | sourceTree = ""; 183 | }; 184 | B153318A1A9FEAEA0026FE28 /* SgButton */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | B153318B1A9FEAEA0026FE28 /* SgButton.swift */, 188 | ); 189 | name = SgButton; 190 | path = ../../SgButton; 191 | sourceTree = ""; 192 | }; 193 | /* End PBXGroup section */ 194 | 195 | /* Begin PBXNativeTarget section */ 196 | B153314E1A9FE49A0026FE28 /* SgButtonDemoIOS */ = { 197 | isa = PBXNativeTarget; 198 | buildConfigurationList = B15331721A9FE49A0026FE28 /* Build configuration list for PBXNativeTarget "SgButtonDemoIOS" */; 199 | buildPhases = ( 200 | B153314B1A9FE49A0026FE28 /* Sources */, 201 | B153314C1A9FE49A0026FE28 /* Frameworks */, 202 | B153314D1A9FE49A0026FE28 /* Resources */, 203 | ); 204 | buildRules = ( 205 | ); 206 | dependencies = ( 207 | ); 208 | name = SgButtonDemoIOS; 209 | productName = SgButtonDemoIOS; 210 | productReference = B153314F1A9FE49A0026FE28 /* SgButtonDemoIOS.app */; 211 | productType = "com.apple.product-type.application"; 212 | }; 213 | B15331671A9FE49A0026FE28 /* SgButtonDemoIOSTests */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = B15331751A9FE49A0026FE28 /* Build configuration list for PBXNativeTarget "SgButtonDemoIOSTests" */; 216 | buildPhases = ( 217 | B15331641A9FE49A0026FE28 /* Sources */, 218 | B15331651A9FE49A0026FE28 /* Frameworks */, 219 | B15331661A9FE49A0026FE28 /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | B153316A1A9FE49A0026FE28 /* PBXTargetDependency */, 225 | ); 226 | name = SgButtonDemoIOSTests; 227 | productName = SgButtonDemoIOSTests; 228 | productReference = B15331681A9FE49A0026FE28 /* SgButtonDemoIOSTests.xctest */; 229 | productType = "com.apple.product-type.bundle.unit-test"; 230 | }; 231 | /* End PBXNativeTarget section */ 232 | 233 | /* Begin PBXProject section */ 234 | B15331471A9FE49A0026FE28 /* Project object */ = { 235 | isa = PBXProject; 236 | attributes = { 237 | LastSwiftMigration = 0730; 238 | LastSwiftUpdateCheck = 0730; 239 | LastUpgradeCheck = 0730; 240 | ORGANIZATIONNAME = Softgaroo; 241 | TargetAttributes = { 242 | B153314E1A9FE49A0026FE28 = { 243 | CreatedOnToolsVersion = 6.1.1; 244 | }; 245 | B15331671A9FE49A0026FE28 = { 246 | CreatedOnToolsVersion = 6.1.1; 247 | TestTargetID = B153314E1A9FE49A0026FE28; 248 | }; 249 | }; 250 | }; 251 | buildConfigurationList = B153314A1A9FE49A0026FE28 /* Build configuration list for PBXProject "SgButtonDemoIOS" */; 252 | compatibilityVersion = "Xcode 3.2"; 253 | developmentRegion = English; 254 | hasScannedForEncodings = 0; 255 | knownRegions = ( 256 | en, 257 | Base, 258 | ); 259 | mainGroup = B15331461A9FE49A0026FE28; 260 | productRefGroup = B15331501A9FE49A0026FE28 /* Products */; 261 | projectDirPath = ""; 262 | projectRoot = ""; 263 | targets = ( 264 | B153314E1A9FE49A0026FE28 /* SgButtonDemoIOS */, 265 | B15331671A9FE49A0026FE28 /* SgButtonDemoIOSTests */, 266 | ); 267 | }; 268 | /* End PBXProject section */ 269 | 270 | /* Begin PBXResourcesBuildPhase section */ 271 | B153314D1A9FE49A0026FE28 /* Resources */ = { 272 | isa = PBXResourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | B15331631A9FE49A0026FE28 /* LaunchScreen.xib in Resources */, 276 | B129DF741AA2E7AE0013334E /* bkbtn_d.png in Resources */, 277 | B129DF801AA2E7AE0013334E /* buy.png in Resources */, 278 | B129DF6E1AA2E7AE0013334E /* back_d@2x.png in Resources */, 279 | B129DF7A1AA2E7AE0013334E /* buttons.1@3x.png in Resources */, 280 | B129DF761AA2E7AE0013334E /* buttons.1.png in Resources */, 281 | B129DF6C1AA2E7AE0013334E /* back@2x.png in Resources */, 282 | B129DF821AA2E7AE0013334E /* buy_d.png in Resources */, 283 | B129DF721AA2E7AE0013334E /* bkbtn.png in Resources */, 284 | B129DF781AA2E7AE0013334E /* buttons.1@2x.png in Resources */, 285 | B129DF701AA2E7AE0013334E /* back_x@2x.png in Resources */, 286 | B153315E1A9FE49A0026FE28 /* Main.storyboard in Resources */, 287 | B129DF7C1AA2E7AE0013334E /* buttons.plist in Resources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | B15331661A9FE49A0026FE28 /* Resources */ = { 292 | isa = PBXResourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | B129DF711AA2E7AE0013334E /* back_x@2x.png in Resources */, 296 | B129DF791AA2E7AE0013334E /* buttons.1@2x.png in Resources */, 297 | B129DF731AA2E7AE0013334E /* bkbtn.png in Resources */, 298 | B129DF6F1AA2E7AE0013334E /* back_d@2x.png in Resources */, 299 | B129DF811AA2E7AE0013334E /* buy.png in Resources */, 300 | B129DF7B1AA2E7AE0013334E /* buttons.1@3x.png in Resources */, 301 | B129DF6D1AA2E7AE0013334E /* back@2x.png in Resources */, 302 | B129DF831AA2E7AE0013334E /* buy_d.png in Resources */, 303 | B129DF771AA2E7AE0013334E /* buttons.1.png in Resources */, 304 | B129DF7D1AA2E7AE0013334E /* buttons.plist in Resources */, 305 | B129DF751AA2E7AE0013334E /* bkbtn_d.png in Resources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | /* End PBXResourcesBuildPhase section */ 310 | 311 | /* Begin PBXSourcesBuildPhase section */ 312 | B153314B1A9FE49A0026FE28 /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | B129DF7E1AA2E7AE0013334E /* Buttons.swift in Sources */, 317 | B15331591A9FE49A0026FE28 /* GameScene.swift in Sources */, 318 | B153315B1A9FE49A0026FE28 /* GameViewController.swift in Sources */, 319 | B15331551A9FE49A0026FE28 /* AppDelegate.swift in Sources */, 320 | B15331A41A9FEAEA0026FE28 /* SgButton.swift in Sources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | B15331641A9FE49A0026FE28 /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | B129DF7F1AA2E7AE0013334E /* Buttons.swift in Sources */, 329 | B153316F1A9FE49A0026FE28 /* SgButtonDemoIOSTests.swift in Sources */, 330 | B15331A51A9FEAEA0026FE28 /* SgButton.swift in Sources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | /* End PBXSourcesBuildPhase section */ 335 | 336 | /* Begin PBXTargetDependency section */ 337 | B153316A1A9FE49A0026FE28 /* PBXTargetDependency */ = { 338 | isa = PBXTargetDependency; 339 | target = B153314E1A9FE49A0026FE28 /* SgButtonDemoIOS */; 340 | targetProxy = B15331691A9FE49A0026FE28 /* PBXContainerItemProxy */; 341 | }; 342 | /* End PBXTargetDependency section */ 343 | 344 | /* Begin PBXVariantGroup section */ 345 | B153315C1A9FE49A0026FE28 /* Main.storyboard */ = { 346 | isa = PBXVariantGroup; 347 | children = ( 348 | B153315D1A9FE49A0026FE28 /* Base */, 349 | ); 350 | name = Main.storyboard; 351 | sourceTree = ""; 352 | }; 353 | B15331611A9FE49A0026FE28 /* LaunchScreen.xib */ = { 354 | isa = PBXVariantGroup; 355 | children = ( 356 | B15331621A9FE49A0026FE28 /* Base */, 357 | ); 358 | name = LaunchScreen.xib; 359 | sourceTree = ""; 360 | }; 361 | /* End PBXVariantGroup section */ 362 | 363 | /* Begin XCBuildConfiguration section */ 364 | B15331701A9FE49A0026FE28 /* Debug */ = { 365 | isa = XCBuildConfiguration; 366 | buildSettings = { 367 | ALWAYS_SEARCH_USER_PATHS = NO; 368 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 369 | CLANG_CXX_LIBRARY = "libc++"; 370 | CLANG_ENABLE_MODULES = YES; 371 | CLANG_ENABLE_OBJC_ARC = YES; 372 | CLANG_WARN_BOOL_CONVERSION = YES; 373 | CLANG_WARN_CONSTANT_CONVERSION = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_EMPTY_BODY = YES; 376 | CLANG_WARN_ENUM_CONVERSION = YES; 377 | CLANG_WARN_INT_CONVERSION = YES; 378 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 379 | CLANG_WARN_UNREACHABLE_CODE = YES; 380 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 381 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 382 | COPY_PHASE_STRIP = NO; 383 | ENABLE_STRICT_OBJC_MSGSEND = YES; 384 | ENABLE_TESTABILITY = YES; 385 | GCC_C_LANGUAGE_STANDARD = gnu99; 386 | GCC_DYNAMIC_NO_PIC = NO; 387 | GCC_OPTIMIZATION_LEVEL = 0; 388 | GCC_PREPROCESSOR_DEFINITIONS = ( 389 | "DEBUG=1", 390 | "$(inherited)", 391 | ); 392 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 394 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 395 | GCC_WARN_UNDECLARED_SELECTOR = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 397 | GCC_WARN_UNUSED_FUNCTION = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 400 | MTL_ENABLE_DEBUG_INFO = YES; 401 | ONLY_ACTIVE_ARCH = YES; 402 | SDKROOT = iphoneos; 403 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 404 | TARGETED_DEVICE_FAMILY = "1,2"; 405 | }; 406 | name = Debug; 407 | }; 408 | B15331711A9FE49A0026FE28 /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | ALWAYS_SEARCH_USER_PATHS = NO; 412 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 413 | CLANG_CXX_LIBRARY = "libc++"; 414 | CLANG_ENABLE_MODULES = YES; 415 | CLANG_ENABLE_OBJC_ARC = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_CONSTANT_CONVERSION = YES; 418 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 419 | CLANG_WARN_EMPTY_BODY = YES; 420 | CLANG_WARN_ENUM_CONVERSION = YES; 421 | CLANG_WARN_INT_CONVERSION = YES; 422 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 423 | CLANG_WARN_UNREACHABLE_CODE = YES; 424 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 425 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 426 | COPY_PHASE_STRIP = YES; 427 | ENABLE_NS_ASSERTIONS = NO; 428 | ENABLE_STRICT_OBJC_MSGSEND = YES; 429 | GCC_C_LANGUAGE_STANDARD = gnu99; 430 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 431 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 432 | GCC_WARN_UNDECLARED_SELECTOR = YES; 433 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 434 | GCC_WARN_UNUSED_FUNCTION = YES; 435 | GCC_WARN_UNUSED_VARIABLE = YES; 436 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 437 | MTL_ENABLE_DEBUG_INFO = NO; 438 | SDKROOT = iphoneos; 439 | TARGETED_DEVICE_FAMILY = "1,2"; 440 | VALIDATE_PRODUCT = YES; 441 | }; 442 | name = Release; 443 | }; 444 | B15331731A9FE49A0026FE28 /* Debug */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | INFOPLIST_FILE = SgButtonDemoIOS/Info.plist; 449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 450 | PRODUCT_BUNDLE_IDENTIFIER = "com.softgaroo.$(PRODUCT_NAME:rfc1034identifier)"; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | }; 453 | name = Debug; 454 | }; 455 | B15331741A9FE49A0026FE28 /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | INFOPLIST_FILE = SgButtonDemoIOS/Info.plist; 460 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 461 | PRODUCT_BUNDLE_IDENTIFIER = "com.softgaroo.$(PRODUCT_NAME:rfc1034identifier)"; 462 | PRODUCT_NAME = "$(TARGET_NAME)"; 463 | }; 464 | name = Release; 465 | }; 466 | B15331761A9FE49A0026FE28 /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | BUNDLE_LOADER = "$(TEST_HOST)"; 470 | FRAMEWORK_SEARCH_PATHS = ( 471 | "$(SDKROOT)/Developer/Library/Frameworks", 472 | "$(inherited)", 473 | ); 474 | GCC_PREPROCESSOR_DEFINITIONS = ( 475 | "DEBUG=1", 476 | "$(inherited)", 477 | ); 478 | INFOPLIST_FILE = SgButtonDemoIOSTests/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 480 | PRODUCT_BUNDLE_IDENTIFIER = "com.softgaroo.$(PRODUCT_NAME:rfc1034identifier)"; 481 | PRODUCT_NAME = "$(TARGET_NAME)"; 482 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SgButtonDemoIOS.app/SgButtonDemoIOS"; 483 | }; 484 | name = Debug; 485 | }; 486 | B15331771A9FE49A0026FE28 /* Release */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | BUNDLE_LOADER = "$(TEST_HOST)"; 490 | FRAMEWORK_SEARCH_PATHS = ( 491 | "$(SDKROOT)/Developer/Library/Frameworks", 492 | "$(inherited)", 493 | ); 494 | INFOPLIST_FILE = SgButtonDemoIOSTests/Info.plist; 495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 496 | PRODUCT_BUNDLE_IDENTIFIER = "com.softgaroo.$(PRODUCT_NAME:rfc1034identifier)"; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SgButtonDemoIOS.app/SgButtonDemoIOS"; 499 | }; 500 | name = Release; 501 | }; 502 | /* End XCBuildConfiguration section */ 503 | 504 | /* Begin XCConfigurationList section */ 505 | B153314A1A9FE49A0026FE28 /* Build configuration list for PBXProject "SgButtonDemoIOS" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | B15331701A9FE49A0026FE28 /* Debug */, 509 | B15331711A9FE49A0026FE28 /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Release; 513 | }; 514 | B15331721A9FE49A0026FE28 /* Build configuration list for PBXNativeTarget "SgButtonDemoIOS" */ = { 515 | isa = XCConfigurationList; 516 | buildConfigurations = ( 517 | B15331731A9FE49A0026FE28 /* Debug */, 518 | B15331741A9FE49A0026FE28 /* Release */, 519 | ); 520 | defaultConfigurationIsVisible = 0; 521 | defaultConfigurationName = Release; 522 | }; 523 | B15331751A9FE49A0026FE28 /* Build configuration list for PBXNativeTarget "SgButtonDemoIOSTests" */ = { 524 | isa = XCConfigurationList; 525 | buildConfigurations = ( 526 | B15331761A9FE49A0026FE28 /* Debug */, 527 | B15331771A9FE49A0026FE28 /* Release */, 528 | ); 529 | defaultConfigurationIsVisible = 0; 530 | defaultConfigurationName = Release; 531 | }; 532 | /* End XCConfigurationList section */ 533 | }; 534 | rootObject = B15331471A9FE49A0026FE28 /* Project object */; 535 | } 536 | --------------------------------------------------------------------------------