From ea49c7202cb5d843a278e263d1522ffad9296c97 Mon Sep 17 00:00:00 2001 From: Marius Horga Date: Wed, 25 May 2016 13:46:57 +0300 Subject: [PATCH] initial commit --- .gitignore | 1 + README.md | 16 + ch01/chapter01.xcodeproj/project.pbxproj | 280 +++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 18776 bytes .../xcschemes/chapter01.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch01/chapter01/AppDelegate.swift | 26 + .../AppIcon.appiconset/Contents.json | 58 ++ ch01/chapter01/Base.lproj/Main.storyboard | 695 ++++++++++++++++++ ch01/chapter01/Info.plist | 34 + ch01/chapter01/ViewController.swift | 24 + ch02/chapter02.xcodeproj/project.pbxproj | 280 +++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 14020 bytes .../xcschemes/chapter02.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch02/chapter02/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 58 ++ ch02/chapter02/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch02/chapter02/Info.plist | 34 + ch02/chapter02/MetalView.swift | 34 + ch03/chapter03.xcodeproj/project.pbxproj | 285 +++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 17515 bytes .../xcschemes/chapter03.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch03/chapter03/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 58 ++ ch03/chapter03/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch03/chapter03/Info.plist | 34 + ch03/chapter03/MetalView.swift | 50 ++ ch03/chapter03/Shaders.metal | 22 + ch04/chapter04.xcodeproj/project.pbxproj | 289 ++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 14141 bytes .../xcschemes/chapter04.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch04/chapter04/AppDelegate.swift | 26 + .../AppIcon.appiconset/Contents.json | 58 ++ ch04/chapter04/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch04/chapter04/Info.plist | 34 + ch04/chapter04/MetalView.swift | 68 ++ ch04/chapter04/Shaders.metal | 23 + ch04/chapter04/ViewController.swift | 27 + ch05/chapter05.xcodeproj/project.pbxproj | 288 ++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 24557 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + .../xcschemes/chapter05.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch05/chapter05/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 58 ++ ch05/chapter05/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch05/chapter05/Info.plist | 34 + ch05/chapter05/MetalView.swift | 123 ++++ ch05/chapter05/Shaders.metal | 34 + ch06/chapter06.xcodeproj/project.pbxproj | 281 +++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 16131 bytes .../xcschemes/chapter06.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch06/chapter06/AppDelegate.swift | 14 + .../AppIcon.appiconset/Contents.json | 58 ++ ch06/chapter06/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch06/chapter06/Info.plist | 34 + ch06/chapter06/MetalView.swift | 44 ++ ch07/chapter07.xcodeproj/project.pbxproj | 289 ++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 14862 bytes .../xcschemes/chapter07.xcscheme | 91 +++ .../xcschemes/xcschememanagement.plist | 22 + ch07/chapter07/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 58 ++ ch07/chapter07/Base.lproj/Main.storyboard | 682 +++++++++++++++++ ch07/chapter07/Info.plist | 34 + ch07/chapter07/MathUtils.swift | 62 ++ ch07/chapter07/MetalView.swift | 66 ++ ch07/chapter07/Shaders.metal | 34 + ch08/chapter08.playground/Contents.swift | 8 + .../Resources/Shaders.metal | 25 + .../Sources/MathUtils.swift | 59 ++ .../Sources/MetalView.swift | 69 ++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 14980 bytes ch08/chapter08.playground/timeline.xctimeline | 6 + ch09/chapter09.playground/Contents.swift | 8 + .../Resources/Shaders.metal | 25 + .../Sources/MathUtils.swift | 63 ++ .../Sources/MetalView.swift | 100 +++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 24161 bytes ch09/chapter09.playground/timeline.xctimeline | 6 + ch10/chapter10.playground/Contents.swift | 8 + .../Resources/Shaders.metal | 23 + .../Sources/MetalView.swift | 46 ++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 16567 bytes ch10/chapter10.playground/timeline.xctimeline | 6 + ch11/chapter11.playground/Contents.swift | 8 + .../Resources/Shaders.metal | 58 ++ .../Sources/MetalView.swift | 56 ++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 18466 bytes ch11/chapter11.playground/timeline.xctimeline | 6 + ch12/chapter12.playground/Contents.swift | 8 + .../Resources/Shaders.metal | 28 + .../Sources/MetalView.swift | 71 ++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 19598 bytes ch12/chapter12.playground/timeline.xctimeline | 6 + 116 files changed, 9762 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 ch01/chapter01.xcodeproj/project.pbxproj create mode 100644 ch01/chapter01.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch01/chapter01.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter01.xcscheme create mode 100644 ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch01/chapter01/AppDelegate.swift create mode 100644 ch01/chapter01/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch01/chapter01/Base.lproj/Main.storyboard create mode 100644 ch01/chapter01/Info.plist create mode 100644 ch01/chapter01/ViewController.swift create mode 100644 ch02/chapter02.xcodeproj/project.pbxproj create mode 100644 ch02/chapter02.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch02/chapter02.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch02/chapter02.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter02.xcscheme create mode 100644 ch02/chapter02.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch02/chapter02/AppDelegate.swift create mode 100644 ch02/chapter02/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch02/chapter02/Base.lproj/Main.storyboard create mode 100644 ch02/chapter02/Info.plist create mode 100644 ch02/chapter02/MetalView.swift create mode 100644 ch03/chapter03.xcodeproj/project.pbxproj create mode 100644 ch03/chapter03.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch03/chapter03.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme create mode 100644 ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch03/chapter03/AppDelegate.swift create mode 100644 ch03/chapter03/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch03/chapter03/Base.lproj/Main.storyboard create mode 100644 ch03/chapter03/Info.plist create mode 100644 ch03/chapter03/MetalView.swift create mode 100644 ch03/chapter03/Shaders.metal create mode 100644 ch04/chapter04.xcodeproj/project.pbxproj create mode 100644 ch04/chapter04.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme create mode 100644 ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch04/chapter04/AppDelegate.swift create mode 100644 ch04/chapter04/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch04/chapter04/Base.lproj/Main.storyboard create mode 100644 ch04/chapter04/Info.plist create mode 100644 ch04/chapter04/MetalView.swift create mode 100644 ch04/chapter04/Shaders.metal create mode 100644 ch04/chapter04/ViewController.swift create mode 100644 ch05/chapter05.xcodeproj/project.pbxproj create mode 100644 ch05/chapter05.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch05/chapter05.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme create mode 100644 ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch05/chapter05/AppDelegate.swift create mode 100644 ch05/chapter05/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch05/chapter05/Base.lproj/Main.storyboard create mode 100644 ch05/chapter05/Info.plist create mode 100644 ch05/chapter05/MetalView.swift create mode 100644 ch05/chapter05/Shaders.metal create mode 100644 ch06/chapter06.xcodeproj/project.pbxproj create mode 100644 ch06/chapter06.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch06/chapter06.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme create mode 100644 ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch06/chapter06/AppDelegate.swift create mode 100644 ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch06/chapter06/Base.lproj/Main.storyboard create mode 100644 ch06/chapter06/Info.plist create mode 100644 ch06/chapter06/MetalView.swift create mode 100644 ch07/chapter07.xcodeproj/project.pbxproj create mode 100644 ch07/chapter07.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ch07/chapter07.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch07/chapter07.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter07.xcscheme create mode 100644 ch07/chapter07.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ch07/chapter07/AppDelegate.swift create mode 100644 ch07/chapter07/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ch07/chapter07/Base.lproj/Main.storyboard create mode 100644 ch07/chapter07/Info.plist create mode 100644 ch07/chapter07/MathUtils.swift create mode 100644 ch07/chapter07/MetalView.swift create mode 100644 ch07/chapter07/Shaders.metal create mode 100644 ch08/chapter08.playground/Contents.swift create mode 100644 ch08/chapter08.playground/Resources/Shaders.metal create mode 100644 ch08/chapter08.playground/Sources/MathUtils.swift create mode 100644 ch08/chapter08.playground/Sources/MetalView.swift create mode 100644 ch08/chapter08.playground/contents.xcplayground create mode 100644 ch08/chapter08.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 ch08/chapter08.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch08/chapter08.playground/timeline.xctimeline create mode 100644 ch09/chapter09.playground/Contents.swift create mode 100755 ch09/chapter09.playground/Resources/Shaders.metal create mode 100755 ch09/chapter09.playground/Sources/MathUtils.swift create mode 100755 ch09/chapter09.playground/Sources/MetalView.swift create mode 100644 ch09/chapter09.playground/contents.xcplayground create mode 100755 ch09/chapter09.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100755 ch09/chapter09.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch09/chapter09.playground/timeline.xctimeline create mode 100755 ch10/chapter10.playground/Contents.swift create mode 100755 ch10/chapter10.playground/Resources/Shaders.metal create mode 100755 ch10/chapter10.playground/Sources/MetalView.swift create mode 100755 ch10/chapter10.playground/contents.xcplayground create mode 100755 ch10/chapter10.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100755 ch10/chapter10.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100755 ch10/chapter10.playground/timeline.xctimeline create mode 100644 ch11/chapter11.playground/Contents.swift create mode 100755 ch11/chapter11.playground/Resources/Shaders.metal create mode 100755 ch11/chapter11.playground/Sources/MetalView.swift create mode 100644 ch11/chapter11.playground/contents.xcplayground create mode 100755 ch11/chapter11.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100755 ch11/chapter11.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch11/chapter11.playground/timeline.xctimeline create mode 100644 ch12/chapter12.playground/Contents.swift create mode 100755 ch12/chapter12.playground/Resources/Shaders.metal create mode 100755 ch12/chapter12.playground/Sources/MetalView.swift create mode 100644 ch12/chapter12.playground/contents.xcplayground create mode 100755 ch12/chapter12.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100755 ch12/chapter12.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ch12/chapter12.playground/timeline.xctimeline diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..c6d03ea --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Metal + +Repository to accompany the following blog posts: +- [Introducing the Metal framework](http://mhorga.org/2016/01/04/introducing-the-metal-framework.html) +- [Using MetalKit part 1](http://mhorga.org/2016/01/11/using-metalkit-part-1.html) +- [Using MetalKit part 2](http://mhorga.org/2016/01/18/using-metalkit-part-2.html) +- [Using MetalKit part 3](http://mhorga.org/2016/01/25/using-metalkit-part-3.html) +- [Using MetalKit part 4](http://mhorga.org/2016/02/01/using-metalkit-part-4.html) +- [Using MetalKit part 5](http://mhorga.org/2016/02/08/using-metalkit-part-5.html) +- [Using MetalKit part 6](http://mhorga.org/2016/02/15/using-metalkit-part-6.html) +- [Using MetalKit part 7](http://mhorga.org/2016/02/29/using-metalkit-part-7.html) +- [Using MetalKit part 8](http://mhorga.org/2016/03/07/using-metalkit-part-8.html) +- [Using MetalKit part 9](http://mhorga.org/2016/04/18/using-metalkit-part-9.html) +- [Using MetalKit part 10](http://mhorga.org/2016/05/02/using-metalkit-part-10.html) +- [Using MetalKit part 11](http://mhorga.org/2016/05/10/using-metalkit-part-11.html) +- [Using MetalKit part 12](http://mhorga.org/2016/05/18/using-metalkit-part-12.html) \ No newline at end of file diff --git a/ch01/chapter01.xcodeproj/project.pbxproj b/ch01/chapter01.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2d5df56 --- /dev/null +++ b/ch01/chapter01.xcodeproj/project.pbxproj @@ -0,0 +1,280 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 29400C7D1C3AEE1300345568 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29400C7C1C3AEE1300345568 /* AppDelegate.swift */; }; + 29400C7F1C3AEE1300345568 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29400C7E1C3AEE1300345568 /* ViewController.swift */; }; + 29400C811C3AEE1300345568 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29400C801C3AEE1300345568 /* Assets.xcassets */; }; + 29400C841C3AEE1300345568 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29400C821C3AEE1300345568 /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 29400C791C3AEE1300345568 /* chapter01.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter01.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29400C7C1C3AEE1300345568 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29400C7E1C3AEE1300345568 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 29400C801C3AEE1300345568 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29400C831C3AEE1300345568 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29400C851C3AEE1300345568 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29400C761C3AEE1300345568 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29400C701C3AEE1300345568 = { + isa = PBXGroup; + children = ( + 29400C7B1C3AEE1300345568 /* chapter01 */, + 29400C7A1C3AEE1300345568 /* Products */, + ); + sourceTree = ""; + }; + 29400C7A1C3AEE1300345568 /* Products */ = { + isa = PBXGroup; + children = ( + 29400C791C3AEE1300345568 /* chapter01.app */, + ); + name = Products; + sourceTree = ""; + }; + 29400C7B1C3AEE1300345568 /* chapter01 */ = { + isa = PBXGroup; + children = ( + 29400C7E1C3AEE1300345568 /* ViewController.swift */, + 29400C801C3AEE1300345568 /* Assets.xcassets */, + 29400C821C3AEE1300345568 /* Main.storyboard */, + 29400C851C3AEE1300345568 /* Info.plist */, + 29400C7C1C3AEE1300345568 /* AppDelegate.swift */, + ); + path = chapter01; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29400C781C3AEE1300345568 /* chapter01 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29400C881C3AEE1300345568 /* Build configuration list for PBXNativeTarget "chapter01" */; + buildPhases = ( + 29400C751C3AEE1300345568 /* Sources */, + 29400C761C3AEE1300345568 /* Frameworks */, + 29400C771C3AEE1300345568 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter01; + productName = chapter01; + productReference = 29400C791C3AEE1300345568 /* chapter01.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29400C711C3AEE1300345568 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29400C781C3AEE1300345568 = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 29400C741C3AEE1300345568 /* Build configuration list for PBXProject "chapter01" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29400C701C3AEE1300345568; + productRefGroup = 29400C7A1C3AEE1300345568 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29400C781C3AEE1300345568 /* chapter01 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29400C771C3AEE1300345568 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29400C811C3AEE1300345568 /* Assets.xcassets in Resources */, + 29400C841C3AEE1300345568 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29400C751C3AEE1300345568 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29400C7F1C3AEE1300345568 /* ViewController.swift in Sources */, + 29400C7D1C3AEE1300345568 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29400C821C3AEE1300345568 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29400C831C3AEE1300345568 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29400C861C3AEE1300345568 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29400C871C3AEE1300345568 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29400C891C3AEE1300345568 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter01/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter01; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29400C8A1C3AEE1300345568 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter01/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter01; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29400C741C3AEE1300345568 /* Build configuration list for PBXProject "chapter01" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29400C861C3AEE1300345568 /* Debug */, + 29400C871C3AEE1300345568 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29400C881C3AEE1300345568 /* Build configuration list for PBXNativeTarget "chapter01" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29400C891C3AEE1300345568 /* Debug */, + 29400C8A1C3AEE1300345568 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29400C711C3AEE1300345568 /* Project object */; +} diff --git a/ch01/chapter01.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch01/chapter01.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a9cba61 --- /dev/null +++ b/ch01/chapter01.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch01/chapter01.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch01/chapter01.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..18e3b2b0c68b7b24567c3efdd9c9379238c67e1c GIT binary patch literal 18776 zcmd6O33yY*+W*X1(!EX6(zH#JZt0dbOPjRm#?}_JP@vFKc4BBl3A9Z~Qg&pH3yLBL zBCaT1*g<4fL=Z$a5s^(~ae<47Afkeba@FrWIZfLLa{a#lcfb2@pQlaE%$a%TU4QR8 zGh-TRZBCb7e*$4dAsR7=MIuq0D1NAFlGWj~+3Sa@>|@4Tt6a`uDvP6PoDCjVs9g32 zDZ;atu9x61kPq@jp(qS>LCGiur6M&-L+MC^v`B~a$cXY#J}O5QXfUcoL(ot(3=Kyk z&`2~2HKIvqGMa*>qG@P4nt^7b2hl9_FnSC2-Bj8kwbR^v2m!Z|n>=iz+Z4Hx5HxHm4v{qP_>9FM>w@hChRkHs~39G-wD zVh5g#XJLXlJO@94pTy7LMfh2~1iyk;;#GJxUW3=;-S}O+2fv5+;(d5OK7bG6llWtN z3V(u6<1_dyK8G*hukbbeExw6=#6RJm@ooH1{2Trq|3T4|59LcqscmQu^9HPj|* zGqr`_>OOZTJ;={|H{x|Hrm_opAAE%X?=ims-u^jNxvcG51ok)A})pb5>< zPttSgr|5a~eEJ!BG5sRFly0S$(HrQE^d@>Uy@lRR@1hUT2kH0eL-Ysq3Hl`cF@1_Y zOP{AN(Ep&X(%;b6=x^y8^v?{-_%Z%WFcZRrGGR;v6UitTC8K82m~=+NXc--&X9}3E zOgE-G(}U^B6f*sp0ZbV)kQv2{X3We4rk1H=>X~WGgUl@EVdfF$ab^zl6f=)`k$H)E znOVZT!Zb52%qnIzvxa$td6U`3yv1y1-ez_%dzkl_z05)8B=a$Iiur^&&3wvy#$05+ zWWHy9U~VusnID;-n13?AF~2i^urwROidhLOWkcC8Hj0(A$!rRn%BtBkHl5964XlyP zVsqJEY;X2H_I|d6?Z@_KE7-xTg&o6IvDK`V9n03Tb!^tl(b~k&7{eV5pe#m~p zo@URmXW1{=OY9Z)TlRPM4-pb!szF4FL?SSiD$A%Z)b}>& zHN7%Sxf)|eQEyGI!BDKp&dAO#&g`wv?rF*~i^EEadkwKWCO8``Rn}sARb!pC-sPD% z94S%K3M4}jC=x{>If_OK!V(ejA-=?q_>+JYC4) z2!4E9eYJgZg=I{k#Zls{v^i~KYOSN&8+tn|byl-D4jv3}R9hX^>UM(Qog#a^%VDpr z1>|BBE4x?&|9WbSy)sRjoGg8jCL_yWEH>!%#k~rRzGiXw^y&Ka*c|=L z^w{YcMk9PS<(g*BJm!{a1~N1OI|E3_F_eX}kqPAt7X(@l{1_^Hv^qiVJsl3q)Mn_A zJG6iK0JrD&^N6Sb-G`D^qpqkM>W+G#o~RHNp<>hv^(ImhO2SAN5>8|!f<%%iB43T} z2Ql?QeNiduhx&u?%FsX(4Zel_I-L-yEcGs-qqEd9)!yhbi#31Axxp@5t<5!+AF>?6oU77ioh*#q zKCUpGm!!RzUu<>SYU;g47|9P)Y#q~BQ^SkhL#i;D&FbWJ4aVqgtF@L{T;oOvUrQ}x ztnD^78rgV0n$ZKug2tdKRE?}?EUH1{h=M3d42dOiB%UM?6-gw}aXgv;oaA}g2Q{FH z$bp_WTg~Ob(`t*O8kWMd+_N%%&AeFnXF_kV-%0@z2;a*a$JD_9!#j;74uv<`C~yxX z@K@p)w38TkU(o5z`>gf0M(6Naw@@n_R;x$n2;xxE(xoItP~1n*qh@hv|MGr~E(;iT zu?;NFUT<+sZ9$Kq*(i5p|MHG!o-rOrPoShGG>530(32#M=To9EcbgLZ6}LPC%ts6O z0iGu5O=uy}kd%sk7F)fibuoGoNn6l!=y~)4(Gnfex1g6mR7*$(2xkcIAXB}j1D3n2 z<)GX3HSUk?6odMh#a+DnT5AD(SwTGB&+oI^>#Q!vRKdPmc>8W8nIyzR)C#nocc&}S zDzqA{L2J=E^cpb`BgrD!#6)sP?h5oe+JH8qO=vUPg0_-8l23|BIk}%ykijHnB(K56 z7MG=BYJ+uzK$DwV@UuPLK#&)Jw|1Gu62Y{frNm{e>+g29kseonmo~Ylt=AM#RvvG5 z_|y@ew!wo+LFf&QV`^>areT{Y0 z{kCdr&)V7&r?ZilR^p#tDsPjQ_ge`)-!71JpExOODDR}RvNC24pKi!Bq{n7vKfajTT9ermO zM*}4t8V1vXow$c6v)CNX=zEm=FZy^0xxo`cO8I$*RgJSWfDH8+p2l15#{Pe9{0$cH zJNg47j7Lvlt0U^gMHox+Km1A z;r@32QIq&!XR9u?TdGr1&ElkXRq1PUX$7a?Az54Qw#g#UrQg{ju>}3WgUK-# zr*#DUcUWsdc_B9){}SV0)>GPr*^@VFU=pd5)sTC`*635_JGMtPcBgv>%9FG&Q3MZ1$q?(K+H6&$dsdcOy0t_2u zs~PA1G+c21?l36s0z7PwPwm0WGfg_q;HS}GE!JT@F_Q;~g^Xzh@6rbwkqW#^38{i` z4539{397*RMnIp|$$b2D4zf(HwA8x&MU;1Io3|*hvNr%MjrD4DzixN9K&Pr4wg!Mf zeDwC};vSuM&;r{EkYQ@YrAX`dOS1*@jsq1&3KI0m{qu%G?0m;s6&eI z&I9gu1a-3E@uS=Efg8=XU>lETJww*wdVZaC#MOlDr14(sbn@$T;YKovOzl|b6g=IF zrWtr9nM|etO`t-8O(gVqB-TxnXVQo8qh9aK#*dL{WI7*_Lf|bAK;rRILXVNVyxyIQ z=cA-%{1gC~nMB=;pT-NwgJc%KX18q0>`ogGg5taVabS{XzQywBnEOQ51uZlSSlN z@Gp!1qv$2?+ZB(heB9{8n3+9u=ydp-9;=_(39aBy@n`59`26$aRq{N53q)QK+{HhT zp&4JqUy>KdOC9d%GQPsw;n(EFCcF*A2kt3ZNCO60oshzGc#Ph5htN<2YFlG>O!aW? zI{uy?;ydzk6aIlLAt}Rcoig$iuVCdpg0{%sSPzEKU~#ydp|k!FevTt|_{X;({QpXp zLZELlOK|KI%@kf+e$uq-DPpHDect$kMIM&<;Dt2-I_!(;3z1T zEGK+LpaU0V<>YF!px}{}+YSsUKPu?YZjA~?eJC+m32yC8QY4HR3P^(rBdgl=l9Ev| z|H}2C*Qq!vo=Tt+@J=cTGN;w#HL?MITgV$ErA<4jR7!g{yQXxM9>q|ZWDQvhcD;@i zL3Y5~S2z~31AW%aNVj z-U_W#TtZ7kgOC;8(M0wDDci}ukEwB#4JH^*O`vLFk}AqhHBb}LwV|*jQd{k?)>ncn zfhx<0Dt_F07Z1w7Bs?j^UjgzFc8ASVn}M13kiB9|-tOd8DJSJ>ll!}5M`yWD<>fw& znoi9iJIOm_SG(MW1Wd@cJlRgCRLCRq$J{dC{b!kXN`Qn^$7|`-)3A6ux`r{jM&1L8 z_Yz3mpm0n*%Ztehyb?-`)C<&$;Lrivv?q{Wl{IhKG*d6}dCA}H?nZjl66zJRIN@*1 z&`iC`kN$VMdTh6eYT+Xb4~D5$a)2*C@rzsmfRI{Ats)1>2kl^mT1&0(4DP7csSV_P za)=a_CG;TT&RCAxN^Sd7*X_{tF!+ET^-H~azC*nW2#(rC?IuUaN6pk8>OFFl9CO1} zPm!U$jtQFP73|s@wC!2@-{|65{QJ~Vl(d{WM14RVraq*OP#=-wsY&^EgykA zU+B)4=LcDMoH9G&?%okzX$~Q0$REc?z?crLd z@*?#Gbpc76sPp7Z6ZH>r)`Q1|Y^|rWbJwq^uR$fK%j8@Wb%lHiP`cfrc^LOC1$d+x z-JrgMs>5f^)OYaVGx$v@^Yr+c`lWroU&$Aw$kXr}^}A5#1Riz-w#=+t2y6Px_OM1% zG~*e7X30O=2cUgve-C+d0J+#6hUj2g3=QZ8DQ%)9uH16%SJkjd_%55+6b=-4q13_VT0Fud30B=_qxHP*E=R{FUa#Rw{e*+qI-jY z=wiAT`JVjH%vaSRX&2IVcP>4kzIJMx;_yLA*Z_gFJEpzW4QHTa2)gLiqx;?Q*WWG# z{Y7QWL-_!D2%r+Wj2=i2qRZ(DdN5r{ej-1UTjUq=E4fYnxdN%^Vf1i%1U-@-MURG6 z{l?+t9A3rYH#mHT!)M(FS_tfz&|nAn>U3{c@u<=)j%usg3;cH1d7S{ep(^7XDeP*M zSBRJ&h<4H+m&K~)26 z(qr7h<{EH0LNI!P2u~|dgNF;_=sGCF&^CHJ-bvSz-^m}Og~OwW-q^rX`sX^ASD*GbL0S2lSUcJ+ zYy@0jb^Q6|awy|W9b<Sy#U9t&}pHj4}HiL>si zXeISy?OOK{56^55(X&xf3;i(t2>mFBSq_Uh?9+mc^yBm#QpI6k4*T((Q^I=8Wu+zM z73N;WB^3h(nag{X_A06<8PMO{x7RR;CU4i=70uK9gIKUlz=|y83dD!Y{+XX7Ox?14L3n&)~iSWg< z)|codJZE3#a8MKd3Wr0yIol#|HrOoAyC-Mc-F!zWS38AI2pd36Jaa9l*YKLTf?i3l zqE~ZR%wY+Kr5p}zrPtEy=-24=91i2KlEX0^PT^TBNxW>3tlIOB_~lII)?&OqFmriEJV%m4dV@1?l|7Dquf_zD~n_io#2I{w)6%`g{5Z9v45G z&gXC;hkJ7vs??pFALA>SXqs6(>YluXT8_;HurM)GKi1B>T^($Wx;J1vdoLYE{4bJE zCP>t#fA4Izk?wipL#Yl6oYERkqfJ^FV}hC zXklQ3S^U40@Czr7m>5O{o|B1X;+S{_%qfe**&H@;IH#3KWRmz&35RnzoaZit_Zr09Nm;Xfs2ZVFEYq;~=|mbHnZTVro{+7pThZVCw^n^{#`AWom#b8;ARFxGzst zshg_2?+a0Ba=UP#LT$|9YiJ&t?2HSBV;Y!=jDvAI6R2M6|GDoGl`kZ00IM` zHG#vkIK0r?56u*Ge}Gv$@SaBX*FJ$qz}i|KG3fZSBU)z%4(tGX%tOLF1I^;nd(LxL zu=n?-cubh0+$^rT=M?`Pm-_c+o-52e_+L5J4u90~=^it*xsmzIB3`~vGYgo7%rhJw z!r`GD9>(F}t<1B`Gt6_$^Bf)lUpYLA!w>Lw80o=8{j7Cktd0&m0hmZ4v_XuAWMC3( zD?r6Lp`@?_zPA@vyyFRfzN)auQa{P!-u~^V^}AsO^D4j!W+{h9l91s;$KI!@9jM8j zTjDmIBa%P$!Au5>+O^42Q<2BZS_`u!XdV5*SLfp4PSJIJ?@R;W`cj7_+xBA2A;?$C%?BZh)^Gc5vAB9}@K$Uesqf zJQ3Dcmszgq)1Vnx?KuO;e9oNbMg0YboqtEv9u2v~T;-Sk6?2*Snz_Q^Mh;Kn@MI28 z;U#>H`Ifovmhe;#Ln`^;zfZ!vU^CKVjk$(4!T!t(_7?LC^DBp^b9e>^yW(Dg?NIkS zWy~TLd&!t(SU*@O%d#TYhlQk+aG2xpLmYm%6&u+AHjoYC)73{f{3r)|>HpW(3>H#S z*vTF{?7U41wYK*U+OnSu?oHN1$&u{L%*hnqRv!r@j}cPF`a^3xsW?9uoJ zcA~e4UF;;NRkPruRy48TqgDzvUH(+4aH{W)3OYN3g>y11*_rHv>@1eB9QzRaFbhV$ zn!{^2yq3f3IQ$xip_T&SZNo}-Hk5E<*g5PI?33(V1bOmCsCxn?+{EF{9ENDO6}}e@ z6E?8Ri~A0@IeXRGYWPb55UGX7#ZX77vX(f9*x-1Ym9L+Kb#Cw!N+8V^9=rGQTu>i` zvykl%g+Y2->TI=B;mlg+0r+E9wfwQTJ7xs0QRRSo>4;97>1J_!^(0rdn+Z^7*;r$#w#Ni|D#UgeiyOk$>6T6uO z>FwY!l#||RVc%fiWML7zIJ}#~@A9N4-9d*JrEn}4wpLvri?n-pEVNWjD7V7qt#HpE z_1?XOIo#Vr2|auTj8lbT6DbsXr!v3G?z`Js_Ol1rgB*U3!+SZr50aN2!Z>JP>|l4* z*dxXx?D4z3e}X;9e$3$m9EMTe=ie9h7}21-yAW}X{o*czfS0yMhdt1TpMBv7-EfzjrxsosVybI7%L^N=$=L(ss?r z&p#kAC>ZXRv~g0ndIGiFo-R1(I|kI;30Hao2|cX5v8u{yg?+^15~+V^c;sC!B{he2 zAq-)gWf5>s$d3e6_Al=Z+wah`$X;uAoKPrZ{A1(d6X1EdZJHHk9oxIsQsad0yc0_3 zktA?l5+vrY8G(Ijp#)NEEuRWkC+Y^5@PidXJ?U6da!TsmF3hw|*qownzb$h-UE{CS z>4AnJ;{Za#%G|V+^LL&K^+-$;e;6*);32X(Qw`sbpLN9hLs&eXUbrr={(p=FzU*D)@sC1S4N0fm>Axa4j zxQICm&YsUhFQAvvD{$qq1ua7>&?>kg@Fv;~hv<*OarE=(B3!P#j4>8r30$I#!zwrr zYs3Y(1g=c>$7OghT$g+RTj82yBc6um6U*m-YF}2QBdE8p;Je^WQv%ah?4MHmJc#e9!*CZeee-Ke}DTM;ty1-h#tW>OH<3 ze8w&I7xq{9d&})PPH^}nhfi@BKAhlPNc_ERT{yz=FFFBP;Me(s3*Mg3%Ng;V%3V|W znDZ}s^4AgEJ&%cK6d+ zgGEC`!$c!Q4I+ogC7L9fBAO&hvf2ce(Eh-<7_reK+|Y^!>>9Q{OAT*L<)0{@{Dl_a{H4 zUz(rRPw!{&%kne%75J6-mH7?wtMIGz8|7#Av-nl{S^XCHt@7LL_rBj@zaxG}{XX-% z=6Buid%qigKl=Ub_lw_ce}Df#|6qTyztlg>KiogUKgvJZ-{9Zhe~kZw{xAEl^xx@! z$p3`@$Nr!ApYcEE|E2#|{$KlF^}ptSJ-|O8BcOXgO+Z7y)PP31Z4&pgR+Big1De3f|dp?3)&v^UeNWRo53-` zn&8Uds^AI1lY^%QPY<3MJUe)9@PgnMgO>!q8r&4TEqGt>k>I1j$AeD>p9=mW_(Jf- z;7h@mgRcbN2>va^HzYPh6OtX06OtEF5YjE=zL1iTz9IcW280X@v4_kJSs!vBsT zkP{*2LoS9~3i&$ZYREM)7Sm#}I8@w493hSpM~n61TyZyX4{@QmSUgZ%DIO{wE;frT z;wrIK>=e%y&lf*0UM5~GUMqf0yh*%8{Dyd&c#rr4@k#MT@m29H@on*M5+tD{j3h!5 zCrOf|NYs*aNv@=uq=%$Xa-XC`(pSFd&s(#_JX(l@1VNe@a7Ne@epNRLX7OHWEqNl!~J zNq-0p3XKcx8ag7hCUi#VoX~}#i$WKNJ|FsGXiMm_&=sMpLf3?@3q25eJ@mJ*#4v4` zDXd4>;IJWK!@@>{jS4e|jSH&_vxiL#bB2+yhr=EXdpzuku(@Gd!}f&j3p)^YDC}_9 zk+3se*e=0cbW~hyN0OTgJ$IWPY*$S%fTEmMTk=X=FNChRh(#k`>E(%kG!;k(J8&%gSVf zWEC=tY`m;iRxfLiIb_piGi9@6oa|xQqq2Fj=VY(QHp#Zg-jHpRZI|tk?UNmr9g!WC z9haSyU65UrU6Ngv{Sgru5gZ|okVZsDq(-DgXd-kG1rgmMdPEdPJQ49+#0wEGMJ$O} z94lN57*%o8z9F|Wn!hxCL>G;ugoX#4U?k5w|+->$sodev3!(bi61&C_W@!8s8;e7M~M8B7R2vqWC58 zOXFMOm&dP)%b7Yzl;AZ{*MHlz$Elc=$|koVR*u* zga;C;5^59d366xugeeKr5|$;LP|>P%Rj#T))lJn?Rjlf*8lb9B4N(nOja1oG^{R;~ zmujkNhH93IQ_WX3tM;jmsLrX*t1ha(QhlSkuKGcBQ}v_j_r%b|=){=B_(WA=R$}+W z!o*&Q_b2vEoRhdP@zuoE#1)CF6W1qhOx&EfHE~Dcdx@tLFCS)Q^gWo^o9 zDX*t&OgWr#GnGnJry5cVQcF??r4CLVnmQtNbZSlN_|&>od+NkgXX?DvEvb7_ucqEi z{Y~w!4pnzi%hZu-xmu-8R;$(NYMnYmou@8R_g9ZlSF6XW$EnAwYt@bFDeCF!nd(_; zPW^=X8TC^2D)k!mI`w+>2K8I&9qL``ch!5<`_&(*PpdDeud8pVZ>xV#!)Z)fP?|U` zG%Y+WGEJVAlBP~ePt&D6oc46u!n8$c&!t^TyOH)|+RtgfrazEgmu^p=nC?n{H~mQZ zC+TO?KTAKKelh)8`giF!(tk?-CH=NWrb*Kb)Qs0SHIp<`HPbb-HP2`kYhKX2ta(+_ zq}id_r#Y@Ur}EuLG1_HBic{2XSJVc&ucGgFX<>L%(Q)N#5;bdTwt(9PAY)NRr2)a};2r`xZ4Uw2&hvF^0)obGeodEGae@Z`3KVQE<|B8Nvezks`{&oE({oDGT`rZ2X^!xP(^9aK`D3 z8<|m=iJ98WtjwIu{LF5dJu>@dR%Ti<>oe_{4VjM2S(%S#KAAZ$b3x{!%q5viGg~s3 zXRgXzles_htN|OM3<-uLL#iRokZmY3^fr_jN(}=H0}XYCX@-Xlvkh|$a}Dzi&l_Gc zykclFv>KKhHW+poP8ohT`Whw12&3GnG{zYdj9O!^vDi4!ILKIT9Bdq8v>L}5Cm8FE z4aNtJj~kygE;p_+t~IVVZZvK&zG>WU+-W>wJZ3y${MdNfc+U8_@q+Q9@sja7ikXlTl3$^- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..f5ae71c --- /dev/null +++ b/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter01.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29400C781C3AEE1300345568 + + primary + + + + + diff --git a/ch01/chapter01/AppDelegate.swift b/ch01/chapter01/AppDelegate.swift new file mode 100644 index 0000000..99b058d --- /dev/null +++ b/ch01/chapter01/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// AppDelegate.swift +// chapter01 +// +// Created by Marius on 1/4/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + + + func applicationDidFinishLaunching(aNotification: NSNotification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(aNotification: NSNotification) { + // Insert code here to tear down your application + } + + +} + diff --git a/ch01/chapter01/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch01/chapter01/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch01/chapter01/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch01/chapter01/Base.lproj/Main.storyboard b/ch01/chapter01/Base.lproj/Main.storyboard new file mode 100644 index 0000000..51664cd --- /dev/null +++ b/ch01/chapter01/Base.lproj/Main.storyboard @@ -0,0 +1,695 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch01/chapter01/Info.plist b/ch01/chapter01/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch01/chapter01/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch01/chapter01/ViewController.swift b/ch01/chapter01/ViewController.swift new file mode 100644 index 0000000..65fd44c --- /dev/null +++ b/ch01/chapter01/ViewController.swift @@ -0,0 +1,24 @@ +// +// ViewController.swift +// chapter01 +// +// Created by Marius on 1/4/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa // contains Metal + +class ViewController: NSViewController { + + @IBOutlet weak var label: NSTextField! + + override func viewDidLoad() { + super.viewDidLoad() + + if let device = MTLCreateSystemDefaultDevice() { + label.stringValue = "Your GPU name is:\n\(device.name!)" + } else { + label.stringValue = "Your GPU does not support Metal!" + } + } +} diff --git a/ch02/chapter02.xcodeproj/project.pbxproj b/ch02/chapter02.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c91e5c5 --- /dev/null +++ b/ch02/chapter02.xcodeproj/project.pbxproj @@ -0,0 +1,280 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 29E74AD11C4159D60023A39A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E74AD01C4159D60023A39A /* AppDelegate.swift */; }; + 29E74AD51C4159D60023A39A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29E74AD41C4159D60023A39A /* Assets.xcassets */; }; + 29E74AD81C4159D60023A39A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29E74AD61C4159D60023A39A /* Main.storyboard */; }; + 29E74AE01C415A020023A39A /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E74ADF1C415A020023A39A /* MetalView.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 29E74ACD1C4159D60023A39A /* chapter02.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter02.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29E74AD01C4159D60023A39A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29E74AD41C4159D60023A39A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29E74AD71C4159D60023A39A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29E74AD91C4159D60023A39A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 29E74ADF1C415A020023A39A /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29E74ACA1C4159D60023A39A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29E74AC41C4159D60023A39A = { + isa = PBXGroup; + children = ( + 29E74ACF1C4159D60023A39A /* chapter02 */, + 29E74ACE1C4159D60023A39A /* Products */, + ); + sourceTree = ""; + }; + 29E74ACE1C4159D60023A39A /* Products */ = { + isa = PBXGroup; + children = ( + 29E74ACD1C4159D60023A39A /* chapter02.app */, + ); + name = Products; + sourceTree = ""; + }; + 29E74ACF1C4159D60023A39A /* chapter02 */ = { + isa = PBXGroup; + children = ( + 29E74ADF1C415A020023A39A /* MetalView.swift */, + 29E74AD61C4159D60023A39A /* Main.storyboard */, + 29E74AD41C4159D60023A39A /* Assets.xcassets */, + 29E74AD91C4159D60023A39A /* Info.plist */, + 29E74AD01C4159D60023A39A /* AppDelegate.swift */, + ); + path = chapter02; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29E74ACC1C4159D60023A39A /* chapter02 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29E74ADC1C4159D60023A39A /* Build configuration list for PBXNativeTarget "chapter02" */; + buildPhases = ( + 29E74AC91C4159D60023A39A /* Sources */, + 29E74ACA1C4159D60023A39A /* Frameworks */, + 29E74ACB1C4159D60023A39A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter02; + productName = chapter02; + productReference = 29E74ACD1C4159D60023A39A /* chapter02.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29E74AC51C4159D60023A39A /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29E74ACC1C4159D60023A39A = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 29E74AC81C4159D60023A39A /* Build configuration list for PBXProject "chapter02" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29E74AC41C4159D60023A39A; + productRefGroup = 29E74ACE1C4159D60023A39A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29E74ACC1C4159D60023A39A /* chapter02 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29E74ACB1C4159D60023A39A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29E74AD51C4159D60023A39A /* Assets.xcassets in Resources */, + 29E74AD81C4159D60023A39A /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29E74AC91C4159D60023A39A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29E74AE01C415A020023A39A /* MetalView.swift in Sources */, + 29E74AD11C4159D60023A39A /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29E74AD61C4159D60023A39A /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29E74AD71C4159D60023A39A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29E74ADA1C4159D60023A39A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29E74ADB1C4159D60023A39A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29E74ADD1C4159D60023A39A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter02/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter02; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29E74ADE1C4159D60023A39A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter02/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter02; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29E74AC81C4159D60023A39A /* Build configuration list for PBXProject "chapter02" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29E74ADA1C4159D60023A39A /* Debug */, + 29E74ADB1C4159D60023A39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29E74ADC1C4159D60023A39A /* Build configuration list for PBXNativeTarget "chapter02" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29E74ADD1C4159D60023A39A /* Debug */, + 29E74ADE1C4159D60023A39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29E74AC51C4159D60023A39A /* Project object */; +} diff --git a/ch02/chapter02.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch02/chapter02.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..9a3f0c0 --- /dev/null +++ b/ch02/chapter02.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch02/chapter02.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch02/chapter02.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..e571953582ee938d05f774f15767fd88f8cd55fb GIT binary patch literal 14020 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 jPiCK!Jtey)yEc1fc3XBwcGplWPsG36b + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch02/chapter02.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch02/chapter02.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..107843d --- /dev/null +++ b/ch02/chapter02.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter02.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29E74ACC1C4159D60023A39A + + primary + + + + + diff --git a/ch02/chapter02/AppDelegate.swift b/ch02/chapter02/AppDelegate.swift new file mode 100644 index 0000000..79d0a15 --- /dev/null +++ b/ch02/chapter02/AppDelegate.swift @@ -0,0 +1,13 @@ +// +// AppDelegate.swift +// chapter02 +// +// Created by Marius on 1/9/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { +} diff --git a/ch02/chapter02/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch02/chapter02/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch02/chapter02/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch02/chapter02/Base.lproj/Main.storyboard b/ch02/chapter02/Base.lproj/Main.storyboard new file mode 100644 index 0000000..325a85d --- /dev/null +++ b/ch02/chapter02/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch02/chapter02/Info.plist b/ch02/chapter02/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch02/chapter02/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch02/chapter02/MetalView.swift b/ch02/chapter02/MetalView.swift new file mode 100644 index 0000000..631d998 --- /dev/null +++ b/ch02/chapter02/MetalView.swift @@ -0,0 +1,34 @@ +// +// MetalView.swift +// chapter02 +// +// Created by Marius on 1/9/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import MetalKit + +class MetalView: MTKView { + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + + render() + } + + func render() { + let device = MTLCreateSystemDefaultDevice()! + self.device = device + let rpd = MTLRenderPassDescriptor() + let bleen = MTLClearColor(red: 0, green: 0.5, blue: 0.5, alpha: 1) + rpd.colorAttachments[0].texture = currentDrawable!.texture + rpd.colorAttachments[0].clearColor = bleen + rpd.colorAttachments[0].loadAction = .Clear + let commandQueue = device.newCommandQueue() + let commandBuffer = commandQueue.commandBuffer() + let encoder = commandBuffer.renderCommandEncoderWithDescriptor(rpd) + encoder.endEncoding() + commandBuffer.presentDrawable(currentDrawable!) + commandBuffer.commit() + } +} diff --git a/ch03/chapter03.xcodeproj/project.pbxproj b/ch03/chapter03.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ed33bc4 --- /dev/null +++ b/ch03/chapter03.xcodeproj/project.pbxproj @@ -0,0 +1,285 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 294BD6211C4D1FD7009CF449 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294BD6201C4D1FD7009CF449 /* MetalView.swift */; }; + 29CB59901C4461EA0004DB55 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29CB598F1C4461EA0004DB55 /* AppDelegate.swift */; }; + 29CB59941C4461EA0004DB55 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29CB59931C4461EA0004DB55 /* Assets.xcassets */; }; + 29CB59971C4461EA0004DB55 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29CB59951C4461EA0004DB55 /* Main.storyboard */; }; + 29CB599F1C44665B0004DB55 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 29CB599E1C44665B0004DB55 /* Shaders.metal */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 294BD6201C4D1FD7009CF449 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; + 29CB598C1C4461EA0004DB55 /* chapter03.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter03.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29CB598F1C4461EA0004DB55 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29CB59931C4461EA0004DB55 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29CB59961C4461EA0004DB55 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29CB59981C4461EA0004DB55 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 29CB599E1C44665B0004DB55 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29CB59891C4461E90004DB55 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29CB59831C4461E90004DB55 = { + isa = PBXGroup; + children = ( + 29CB598E1C4461EA0004DB55 /* chapter03 */, + 29CB598D1C4461EA0004DB55 /* Products */, + ); + sourceTree = ""; + }; + 29CB598D1C4461EA0004DB55 /* Products */ = { + isa = PBXGroup; + children = ( + 29CB598C1C4461EA0004DB55 /* chapter03.app */, + ); + name = Products; + sourceTree = ""; + }; + 29CB598E1C4461EA0004DB55 /* chapter03 */ = { + isa = PBXGroup; + children = ( + 294BD6201C4D1FD7009CF449 /* MetalView.swift */, + 29CB599E1C44665B0004DB55 /* Shaders.metal */, + 29CB59951C4461EA0004DB55 /* Main.storyboard */, + 29CB59931C4461EA0004DB55 /* Assets.xcassets */, + 29CB59981C4461EA0004DB55 /* Info.plist */, + 29CB598F1C4461EA0004DB55 /* AppDelegate.swift */, + ); + path = chapter03; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29CB598B1C4461E90004DB55 /* chapter03 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29CB599B1C4461EA0004DB55 /* Build configuration list for PBXNativeTarget "chapter03" */; + buildPhases = ( + 29CB59881C4461E90004DB55 /* Sources */, + 29CB59891C4461E90004DB55 /* Frameworks */, + 29CB598A1C4461E90004DB55 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter03; + productName = chapter03; + productReference = 29CB598C1C4461EA0004DB55 /* chapter03.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29CB59841C4461E90004DB55 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29CB598B1C4461E90004DB55 = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 29CB59871C4461E90004DB55 /* Build configuration list for PBXProject "chapter03" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29CB59831C4461E90004DB55; + productRefGroup = 29CB598D1C4461EA0004DB55 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29CB598B1C4461E90004DB55 /* chapter03 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29CB598A1C4461E90004DB55 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29CB59941C4461EA0004DB55 /* Assets.xcassets in Resources */, + 29CB59971C4461EA0004DB55 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29CB59881C4461E90004DB55 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 294BD6211C4D1FD7009CF449 /* MetalView.swift in Sources */, + 29CB599F1C44665B0004DB55 /* Shaders.metal in Sources */, + 29CB59901C4461EA0004DB55 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29CB59951C4461EA0004DB55 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29CB59961C4461EA0004DB55 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29CB59991C4461EA0004DB55 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29CB599A1C4461EA0004DB55 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29CB599C1C4461EA0004DB55 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter03/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter03; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29CB599D1C4461EA0004DB55 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter03/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter03; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29CB59871C4461E90004DB55 /* Build configuration list for PBXProject "chapter03" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29CB59991C4461EA0004DB55 /* Debug */, + 29CB599A1C4461EA0004DB55 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29CB599B1C4461EA0004DB55 /* Build configuration list for PBXNativeTarget "chapter03" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29CB599C1C4461EA0004DB55 /* Debug */, + 29CB599D1C4461EA0004DB55 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29CB59841C4461E90004DB55 /* Project object */; +} diff --git a/ch03/chapter03.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch03/chapter03.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..7cddba2 --- /dev/null +++ b/ch03/chapter03.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch03/chapter03.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch03/chapter03.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..b5d75a4dcf7d61c8ad876002d367a51be950f289 GIT binary patch literal 17515 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
_i?{@pv4M$MbkX2RoUaf|A&2Jg(;P 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 literal 0 HcmV?d00001 diff --git a/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme new file mode 100644 index 0000000..6ec6aa7 --- /dev/null +++ b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d621961 --- /dev/null +++ b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter03.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29CB598B1C4461E90004DB55 + + primary + + + + + diff --git a/ch03/chapter03/AppDelegate.swift b/ch03/chapter03/AppDelegate.swift new file mode 100644 index 0000000..cc40090 --- /dev/null +++ b/ch03/chapter03/AppDelegate.swift @@ -0,0 +1,13 @@ +// +// AppDelegate.swift +// chapter03 +// +// Created by Marius on 1/12/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { +} diff --git a/ch03/chapter03/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch03/chapter03/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch03/chapter03/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch03/chapter03/Base.lproj/Main.storyboard b/ch03/chapter03/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f33a444 --- /dev/null +++ b/ch03/chapter03/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch03/chapter03/Info.plist b/ch03/chapter03/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch03/chapter03/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch03/chapter03/MetalView.swift b/ch03/chapter03/MetalView.swift new file mode 100644 index 0000000..2dc500b --- /dev/null +++ b/ch03/chapter03/MetalView.swift @@ -0,0 +1,50 @@ +// +// MetalView.swift +// chapter03 +// +// Created by Marius on 1/12/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import MetalKit + +class MetalView: MTKView { + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + render() + } + + func render() { + device = MTLCreateSystemDefaultDevice() + let vertex_data:[Float] = [-1.0, -1.0, 0.0, 1.0, + 1.0, -1.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0] + let data_size = vertex_data.count * sizeof(Float) + let vertex_buffer = device!.newBufferWithBytes(vertex_data, length: data_size, options: []) + let library = device!.newDefaultLibrary()! + let vertex_func = library.newFunctionWithName("vertex_func") + let frag_func = library.newFunctionWithName("fragment_func") + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vertex_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + var rps: MTLRenderPipelineState! = nil + do { + try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let error { + self.print("\(error)") + } + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0, 0.5, 0.5, 1.0) + let command_buffer = device!.newCommandQueue().commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } +} diff --git a/ch03/chapter03/Shaders.metal b/ch03/chapter03/Shaders.metal new file mode 100644 index 0000000..dd09adb --- /dev/null +++ b/ch03/chapter03/Shaders.metal @@ -0,0 +1,22 @@ +// +// Shaders.metal +// chapter03 +// +// Created by Marius on 1/12/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]]) { + return vertices[vid]; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return float4(0.7, 1, 1, 1); +} diff --git a/ch04/chapter04.xcodeproj/project.pbxproj b/ch04/chapter04.xcodeproj/project.pbxproj new file mode 100644 index 0000000..760ab6c --- /dev/null +++ b/ch04/chapter04.xcodeproj/project.pbxproj @@ -0,0 +1,289 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 29C87D411C56E93A005F4615 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C87D401C56E93A005F4615 /* AppDelegate.swift */; }; + 29C87D431C56E93A005F4615 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C87D421C56E93A005F4615 /* ViewController.swift */; }; + 29C87D451C56E93A005F4615 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29C87D441C56E93A005F4615 /* Assets.xcassets */; }; + 29C87D481C56E93B005F4615 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29C87D461C56E93B005F4615 /* Main.storyboard */; }; + 29C87D501C56E9C2005F4615 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 29C87D4F1C56E9C2005F4615 /* Shaders.metal */; }; + 29C87D521C56E9DE005F4615 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C87D511C56E9DE005F4615 /* MetalView.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 29C87D3D1C56E93A005F4615 /* chapter04.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter04.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29C87D401C56E93A005F4615 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29C87D421C56E93A005F4615 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 29C87D441C56E93A005F4615 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29C87D471C56E93B005F4615 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29C87D491C56E93B005F4615 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 29C87D4F1C56E9C2005F4615 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; + 29C87D511C56E9DE005F4615 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29C87D3A1C56E93A005F4615 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29C87D341C56E93A005F4615 = { + isa = PBXGroup; + children = ( + 29C87D3F1C56E93A005F4615 /* chapter04 */, + 29C87D3E1C56E93A005F4615 /* Products */, + ); + sourceTree = ""; + }; + 29C87D3E1C56E93A005F4615 /* Products */ = { + isa = PBXGroup; + children = ( + 29C87D3D1C56E93A005F4615 /* chapter04.app */, + ); + name = Products; + sourceTree = ""; + }; + 29C87D3F1C56E93A005F4615 /* chapter04 */ = { + isa = PBXGroup; + children = ( + 29C87D511C56E9DE005F4615 /* MetalView.swift */, + 29C87D4F1C56E9C2005F4615 /* Shaders.metal */, + 29C87D441C56E93A005F4615 /* Assets.xcassets */, + 29C87D421C56E93A005F4615 /* ViewController.swift */, + 29C87D461C56E93B005F4615 /* Main.storyboard */, + 29C87D491C56E93B005F4615 /* Info.plist */, + 29C87D401C56E93A005F4615 /* AppDelegate.swift */, + ); + path = chapter04; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29C87D3C1C56E93A005F4615 /* chapter04 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29C87D4C1C56E93B005F4615 /* Build configuration list for PBXNativeTarget "chapter04" */; + buildPhases = ( + 29C87D391C56E93A005F4615 /* Sources */, + 29C87D3A1C56E93A005F4615 /* Frameworks */, + 29C87D3B1C56E93A005F4615 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter04; + productName = chapter04; + productReference = 29C87D3D1C56E93A005F4615 /* chapter04.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29C87D351C56E93A005F4615 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29C87D3C1C56E93A005F4615 = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 29C87D381C56E93A005F4615 /* Build configuration list for PBXProject "chapter04" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29C87D341C56E93A005F4615; + productRefGroup = 29C87D3E1C56E93A005F4615 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29C87D3C1C56E93A005F4615 /* chapter04 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29C87D3B1C56E93A005F4615 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29C87D451C56E93A005F4615 /* Assets.xcassets in Resources */, + 29C87D481C56E93B005F4615 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29C87D391C56E93A005F4615 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29C87D521C56E9DE005F4615 /* MetalView.swift in Sources */, + 29C87D501C56E9C2005F4615 /* Shaders.metal in Sources */, + 29C87D431C56E93A005F4615 /* ViewController.swift in Sources */, + 29C87D411C56E93A005F4615 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29C87D461C56E93B005F4615 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29C87D471C56E93B005F4615 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29C87D4A1C56E93B005F4615 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29C87D4B1C56E93B005F4615 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29C87D4D1C56E93B005F4615 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter04/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter04; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29C87D4E1C56E93B005F4615 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter04/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter04; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29C87D381C56E93A005F4615 /* Build configuration list for PBXProject "chapter04" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29C87D4A1C56E93B005F4615 /* Debug */, + 29C87D4B1C56E93B005F4615 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29C87D4C1C56E93B005F4615 /* Build configuration list for PBXNativeTarget "chapter04" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29C87D4D1C56E93B005F4615 /* Debug */, + 29C87D4E1C56E93B005F4615 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29C87D351C56E93A005F4615 /* Project object */; +} diff --git a/ch04/chapter04.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch04/chapter04.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..97a56d9 --- /dev/null +++ b/ch04/chapter04.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..0ea0b23e4e873a2b41f57268a698fdba0a7acbf3 GIT binary patch literal 14141 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 literal 0 HcmV?d00001 diff --git a/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme new file mode 100644 index 0000000..a541f24 --- /dev/null +++ b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..65aa13b --- /dev/null +++ b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter04.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29C87D3C1C56E93A005F4615 + + primary + + + + + diff --git a/ch04/chapter04/AppDelegate.swift b/ch04/chapter04/AppDelegate.swift new file mode 100644 index 0000000..d94af3b --- /dev/null +++ b/ch04/chapter04/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// AppDelegate.swift +// chapter04 +// +// Created by Marius on 1/26/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + + + func applicationDidFinishLaunching(aNotification: NSNotification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(aNotification: NSNotification) { + // Insert code here to tear down your application + } + + +} + diff --git a/ch04/chapter04/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch04/chapter04/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch04/chapter04/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch04/chapter04/Base.lproj/Main.storyboard b/ch04/chapter04/Base.lproj/Main.storyboard new file mode 100644 index 0000000..4b8d6f1 --- /dev/null +++ b/ch04/chapter04/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch04/chapter04/Info.plist b/ch04/chapter04/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch04/chapter04/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch04/chapter04/MetalView.swift b/ch04/chapter04/MetalView.swift new file mode 100644 index 0000000..847b46e --- /dev/null +++ b/ch04/chapter04/MetalView.swift @@ -0,0 +1,68 @@ +// +// MetalView.swift +// chapter04 +// +// Created by Marius on 1/26/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import MetalKit + +class MetalView: MTKView { + + var vertex_buffer: MTLBuffer! + var rps: MTLRenderPipelineState! = nil + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + render() + } + + func render() { + device = MTLCreateSystemDefaultDevice() + createBuffer() + registerShaders() + sendToGPU() + } + + struct Vertex { + var position: vector_float4 + var color: vector_float4 + }; + + func createBuffer() { + let vertex_data = [Vertex(position: [-1.0, -1.0, 0.0, 1.0], color: [1, 0, 0, 1]), + Vertex(position: [ 1.0, -1.0, 0.0, 1.0], color: [0, 1, 0, 1]), + Vertex(position: [ 0.0, 1.0, 0.0, 1.0], color: [0, 0, 1, 1])] + vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) + } + + func registerShaders() { + let library = device!.newDefaultLibrary()! + let vertex_func = library.newFunctionWithName("vertex_func") + let frag_func = library.newFunctionWithName("fragment_func") + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vertex_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + do { + try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let error { + self.print("\(error)") + } + } + + func sendToGPU() { + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let command_buffer = device!.newCommandQueue().commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } +} diff --git a/ch04/chapter04/Shaders.metal b/ch04/chapter04/Shaders.metal new file mode 100644 index 0000000..87188e5 --- /dev/null +++ b/ch04/chapter04/Shaders.metal @@ -0,0 +1,23 @@ +// +// Shaders.metal +// chapter04 +// +// Created by Marius on 1/26/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]]) { + return vertices[vid]; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return vert.color; +} diff --git a/ch04/chapter04/ViewController.swift b/ch04/chapter04/ViewController.swift new file mode 100644 index 0000000..d8740a2 --- /dev/null +++ b/ch04/chapter04/ViewController.swift @@ -0,0 +1,27 @@ +// +// ViewController.swift +// chapter04 +// +// Created by Marius on 1/26/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +class ViewController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override var representedObject: AnyObject? { + didSet { + // Update the view, if already loaded. + } + } + + +} + diff --git a/ch05/chapter05.xcodeproj/project.pbxproj b/ch05/chapter05.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4ffaaea --- /dev/null +++ b/ch05/chapter05.xcodeproj/project.pbxproj @@ -0,0 +1,288 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 298037231C62437900FBBC6A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298037221C62437900FBBC6A /* AppDelegate.swift */; }; + 298037271C62437900FBBC6A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 298037261C62437900FBBC6A /* Assets.xcassets */; }; + 2980372A1C62437900FBBC6A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 298037281C62437900FBBC6A /* Main.storyboard */; }; + 298037321C6243CB00FBBC6A /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298037311C6243CB00FBBC6A /* MetalView.swift */; }; + 298037341C62440400FBBC6A /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 298037331C62440400FBBC6A /* Shaders.metal */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2980371F1C62437900FBBC6A /* chapter05.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter05.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 298037221C62437900FBBC6A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 298037261C62437900FBBC6A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 298037291C62437900FBBC6A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2980372B1C62437900FBBC6A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 298037311C6243CB00FBBC6A /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; + 298037331C62440400FBBC6A /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2980371C1C62437900FBBC6A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 298037161C62437900FBBC6A = { + isa = PBXGroup; + children = ( + 298037211C62437900FBBC6A /* chapter05 */, + 298037201C62437900FBBC6A /* Products */, + ); + sourceTree = ""; + }; + 298037201C62437900FBBC6A /* Products */ = { + isa = PBXGroup; + children = ( + 2980371F1C62437900FBBC6A /* chapter05.app */, + ); + name = Products; + sourceTree = ""; + }; + 298037211C62437900FBBC6A /* chapter05 */ = { + isa = PBXGroup; + children = ( + 298037311C6243CB00FBBC6A /* MetalView.swift */, + 298037331C62440400FBBC6A /* Shaders.metal */, + 298037261C62437900FBBC6A /* Assets.xcassets */, + 298037281C62437900FBBC6A /* Main.storyboard */, + 2980372B1C62437900FBBC6A /* Info.plist */, + 298037221C62437900FBBC6A /* AppDelegate.swift */, + ); + path = chapter05; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2980371E1C62437900FBBC6A /* chapter05 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2980372E1C62437900FBBC6A /* Build configuration list for PBXNativeTarget "chapter05" */; + buildPhases = ( + 2980371B1C62437900FBBC6A /* Sources */, + 2980371C1C62437900FBBC6A /* Frameworks */, + 2980371D1C62437900FBBC6A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter05; + productName = chapter05; + productReference = 2980371F1C62437900FBBC6A /* chapter05.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 298037171C62437900FBBC6A /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 2980371E1C62437900FBBC6A = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 2980371A1C62437900FBBC6A /* Build configuration list for PBXProject "chapter05" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 298037161C62437900FBBC6A; + productRefGroup = 298037201C62437900FBBC6A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2980371E1C62437900FBBC6A /* chapter05 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2980371D1C62437900FBBC6A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 298037271C62437900FBBC6A /* Assets.xcassets in Resources */, + 2980372A1C62437900FBBC6A /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2980371B1C62437900FBBC6A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 298037341C62440400FBBC6A /* Shaders.metal in Sources */, + 298037321C6243CB00FBBC6A /* MetalView.swift in Sources */, + 298037231C62437900FBBC6A /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 298037281C62437900FBBC6A /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 298037291C62437900FBBC6A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2980372C1C62437900FBBC6A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2980372D1C62437900FBBC6A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 2980372F1C62437900FBBC6A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter05/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter05; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 298037301C62437900FBBC6A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter05/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter05; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2980371A1C62437900FBBC6A /* Build configuration list for PBXProject "chapter05" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2980372C1C62437900FBBC6A /* Debug */, + 2980372D1C62437900FBBC6A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2980372E1C62437900FBBC6A /* Build configuration list for PBXNativeTarget "chapter05" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2980372F1C62437900FBBC6A /* Debug */, + 298037301C62437900FBBC6A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 298037171C62437900FBBC6A /* Project object */; +} diff --git a/ch05/chapter05.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch05/chapter05.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..61afa29 --- /dev/null +++ b/ch05/chapter05.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch05/chapter05.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch05/chapter05.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..d5df0befe731d91dc6b101348ba43a3736e6cccb GIT binary patch literal 24557 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 + + diff --git a/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme new file mode 100644 index 0000000..1ad0d75 --- /dev/null +++ b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..9b6e229 --- /dev/null +++ b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter05.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 2980371E1C62437900FBBC6A + + primary + + + + + diff --git a/ch05/chapter05/AppDelegate.swift b/ch05/chapter05/AppDelegate.swift new file mode 100644 index 0000000..3d4d50a --- /dev/null +++ b/ch05/chapter05/AppDelegate.swift @@ -0,0 +1,13 @@ +// +// AppDelegate.swift +// chapter05 +// +// Created by Marius on 2/3/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { +} diff --git a/ch05/chapter05/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch05/chapter05/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch05/chapter05/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch05/chapter05/Base.lproj/Main.storyboard b/ch05/chapter05/Base.lproj/Main.storyboard new file mode 100644 index 0000000..1ed57e4 --- /dev/null +++ b/ch05/chapter05/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch05/chapter05/Info.plist b/ch05/chapter05/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch05/chapter05/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch05/chapter05/MetalView.swift b/ch05/chapter05/MetalView.swift new file mode 100644 index 0000000..cae788e --- /dev/null +++ b/ch05/chapter05/MetalView.swift @@ -0,0 +1,123 @@ +// +// MetalView.swift +// chapter05 +// +// Created by Marius on 2/3/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import MetalKit + +class MetalView: MTKView { + + var vertex_buffer: MTLBuffer! + var uniform_buffer: MTLBuffer! + var rps: MTLRenderPipelineState! = nil + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + render() + } + + func render() { + device = MTLCreateSystemDefaultDevice() + createBuffers() + registerShaders() + sendToGPU() + } + + struct Vertex { + var position: vector_float4 + var color: vector_float4 + } + + struct Matrix { + var m: [Float] + + init() { + m = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + + func translationMatrix(var matrix: Matrix, _ position: float3) -> Matrix { + matrix.m[12] = position.x + matrix.m[13] = position.y + matrix.m[14] = position.z + return matrix + } + + func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + matrix.m[0] = scale + matrix.m[5] = scale + matrix.m[10] = scale + matrix.m[15] = 1.0 + return matrix + } + + func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + matrix.m[0] = cos(rot.y) * cos(rot.z) + matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) + matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) + matrix.m[1] = cos(rot.y) * sin(rot.z) + matrix.m[5] = cos(rot.x) * cos(rot.z) + sin(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[9] = -cos(rot.z) * sin(rot.x) + cos(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[2] = -sin(rot.y) + matrix.m[6] = cos(rot.y) * sin(rot.x) + matrix.m[10] = cos(rot.x) * cos(rot.y) + matrix.m[15] = 1.0 + return matrix + } + + func modelMatrix(var matrix: Matrix) -> Matrix { + matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) + matrix = scalingMatrix(matrix, 0.25) + matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) + return matrix + } + } + + func createBuffers() { + let vertex_data = [ + Vertex(position: [-1.0, -1.0, 0.0, 1.0], color: [1, 0, 0, 1]), + Vertex(position: [ 1.0, -1.0, 0.0, 1.0], color: [0, 1, 0, 1]), + Vertex(position: [ 0.0, 1.0, 0.0, 1.0], color: [0, 0, 1, 1]) + ] + vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) + uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) + let bufferPointer = uniform_buffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + } + + func registerShaders() { + let library = device!.newDefaultLibrary()! + let vertex_func = library.newFunctionWithName("vertex_func") + let frag_func = library.newFunctionWithName("fragment_func") + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vertex_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + do { + try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let error { + self.print("\(error)") + } + } + + func sendToGPU() { + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let command_buffer = device!.newCommandQueue().commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) + command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } +} diff --git a/ch05/chapter05/Shaders.metal b/ch05/chapter05/Shaders.metal new file mode 100644 index 0000000..a223380 --- /dev/null +++ b/ch05/chapter05/Shaders.metal @@ -0,0 +1,34 @@ +// +// Shaders.metal +// chapter05 +// +// Created by Marius on 2/3/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +struct Uniforms { + float4x4 modelMatrix; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], + constant Uniforms &uniforms [[buffer(1)]], + uint vid [[vertex_id]]) { + float4x4 matrix = uniforms.modelMatrix; + Vertex in = vertices[vid]; + Vertex out; + out.position = matrix * float4(in.position); + out.color = in.color; + return out; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return vert.color; +} diff --git a/ch06/chapter06.xcodeproj/project.pbxproj b/ch06/chapter06.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d5b5d90 --- /dev/null +++ b/ch06/chapter06.xcodeproj/project.pbxproj @@ -0,0 +1,281 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 292765421C6BDE3400094CA9 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 292765411C6BDE3400094CA9 /* MetalView.swift */; }; + 29DB1AF61C6BDDD500BCC31B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */; }; + 29DB1AFA1C6BDDD500BCC31B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */; }; + 29DB1AFD1C6BDDD500BCC31B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 292765411C6BDE3400094CA9 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; + 29DB1AF21C6BDDD500BCC31B /* chapter06.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter06.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29DB1AFC1C6BDDD500BCC31B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29DB1AFE1C6BDDD500BCC31B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29DB1AEF1C6BDDD500BCC31B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29DB1AE91C6BDDD400BCC31B = { + isa = PBXGroup; + children = ( + 29DB1AF41C6BDDD500BCC31B /* chapter06 */, + 29DB1AF31C6BDDD500BCC31B /* Products */, + ); + sourceTree = ""; + }; + 29DB1AF31C6BDDD500BCC31B /* Products */ = { + isa = PBXGroup; + children = ( + 29DB1AF21C6BDDD500BCC31B /* chapter06.app */, + ); + name = Products; + sourceTree = ""; + }; + 29DB1AF41C6BDDD500BCC31B /* chapter06 */ = { + isa = PBXGroup; + children = ( + 292765411C6BDE3400094CA9 /* MetalView.swift */, + 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */, + 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */, + 29DB1AFE1C6BDDD500BCC31B /* Info.plist */, + 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */, + ); + path = chapter06; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29DB1AF11C6BDDD500BCC31B /* chapter06 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29DB1B011C6BDDD500BCC31B /* Build configuration list for PBXNativeTarget "chapter06" */; + buildPhases = ( + 29DB1AEE1C6BDDD500BCC31B /* Sources */, + 29DB1AEF1C6BDDD500BCC31B /* Frameworks */, + 29DB1AF01C6BDDD500BCC31B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter06; + productName = chapter06; + productReference = 29DB1AF21C6BDDD500BCC31B /* chapter06.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29DB1AEA1C6BDDD400BCC31B /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29DB1AF11C6BDDD500BCC31B = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 29DB1AED1C6BDDD400BCC31B /* Build configuration list for PBXProject "chapter06" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29DB1AE91C6BDDD400BCC31B; + productRefGroup = 29DB1AF31C6BDDD500BCC31B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29DB1AF11C6BDDD500BCC31B /* chapter06 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29DB1AF01C6BDDD500BCC31B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29DB1AFA1C6BDDD500BCC31B /* Assets.xcassets in Resources */, + 29DB1AFD1C6BDDD500BCC31B /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29DB1AEE1C6BDDD500BCC31B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 292765421C6BDE3400094CA9 /* MetalView.swift in Sources */, + 29DB1AF61C6BDDD500BCC31B /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29DB1AFC1C6BDDD500BCC31B /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29DB1AFF1C6BDDD500BCC31B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29DB1B001C6BDDD500BCC31B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29DB1B021C6BDDD500BCC31B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter06/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter06; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29DB1B031C6BDDD500BCC31B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter06/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter06; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29DB1AED1C6BDDD400BCC31B /* Build configuration list for PBXProject "chapter06" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29DB1AFF1C6BDDD500BCC31B /* Debug */, + 29DB1B001C6BDDD500BCC31B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29DB1B011C6BDDD500BCC31B /* Build configuration list for PBXNativeTarget "chapter06" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29DB1B021C6BDDD500BCC31B /* Debug */, + 29DB1B031C6BDDD500BCC31B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29DB1AEA1C6BDDD400BCC31B /* Project object */; +} diff --git a/ch06/chapter06.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch06/chapter06.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..8002602 --- /dev/null +++ b/ch06/chapter06.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch06/chapter06.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch06/chapter06.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..b174838decb42b20cabeb9e84eddc8efbcdd903a GIT binary patch literal 16131 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 a%&W_5&s&stzF7PaBL0;W2G&G*p8o+d8v-8y literal 0 HcmV?d00001 diff --git a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme new file mode 100644 index 0000000..d92b1b7 --- /dev/null +++ b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8e90fc7 --- /dev/null +++ b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter06.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29DB1AF11C6BDDD500BCC31B + + primary + + + + + diff --git a/ch06/chapter06/AppDelegate.swift b/ch06/chapter06/AppDelegate.swift new file mode 100644 index 0000000..247cfb6 --- /dev/null +++ b/ch06/chapter06/AppDelegate.swift @@ -0,0 +1,14 @@ +// +// AppDelegate.swift +// chapter06 +// +// Created by Marius on 2/10/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + +} diff --git a/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch06/chapter06/Base.lproj/Main.storyboard b/ch06/chapter06/Base.lproj/Main.storyboard new file mode 100644 index 0000000..46163bb --- /dev/null +++ b/ch06/chapter06/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch06/chapter06/Info.plist b/ch06/chapter06/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch06/chapter06/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch06/chapter06/MetalView.swift b/ch06/chapter06/MetalView.swift new file mode 100644 index 0000000..33682be --- /dev/null +++ b/ch06/chapter06/MetalView.swift @@ -0,0 +1,44 @@ +// +// MetalView.swift +// chapter06 +// +// Created by Marius on 2/10/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +class MetalView: NSView { + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + render() + } + + override class func layerClass() -> AnyClass { + return CAMetalLayer.self + } + + var metalLayer: CAMetalLayer { + return layer as! CAMetalLayer + } + + func render() { + let device = MTLCreateSystemDefaultDevice()! + metalLayer.device = device + metalLayer.pixelFormat = .BGRA8Unorm + let drawable = metalLayer.nextDrawable() + let texture = drawable!.texture + let rpd = MTLRenderPassDescriptor() + rpd.colorAttachments[0].texture = texture + rpd.colorAttachments[0].loadAction = .Clear + rpd.colorAttachments[0].storeAction = .Store + rpd.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 0, blue: 0, alpha: 1) + let commandQueue = device.newCommandQueue() + let commandBuffer = commandQueue.commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(rpd) + commandEncoder.endEncoding() + commandBuffer.presentDrawable(drawable!) + commandBuffer.commit() + } +} diff --git a/ch07/chapter07.xcodeproj/project.pbxproj b/ch07/chapter07.xcodeproj/project.pbxproj new file mode 100644 index 0000000..bc672e5 --- /dev/null +++ b/ch07/chapter07.xcodeproj/project.pbxproj @@ -0,0 +1,289 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 29B186261C84FF5800E9C0AA /* MathUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B186251C84FF5800E9C0AA /* MathUtils.swift */; }; + 29D8782A1C84D2B0007B5F17 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29D878291C84D2B0007B5F17 /* AppDelegate.swift */; }; + 29D8782E1C84D2B0007B5F17 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */; }; + 29D878311C84D2B0007B5F17 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29D8782F1C84D2B0007B5F17 /* Main.storyboard */; }; + 29D878391C84D309007B5F17 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29D878381C84D309007B5F17 /* MetalView.swift */; }; + 29D8783B1C84D335007B5F17 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 29D8783A1C84D335007B5F17 /* Shaders.metal */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 29B186251C84FF5800E9C0AA /* MathUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MathUtils.swift; sourceTree = ""; }; + 29D878261C84D2B0007B5F17 /* chapter07.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter07.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29D878291C84D2B0007B5F17 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29D878301C84D2B0007B5F17 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 29D878321C84D2B0007B5F17 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 29D878381C84D309007B5F17 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; + 29D8783A1C84D335007B5F17 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29D878231C84D2B0007B5F17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29D8781D1C84D2B0007B5F17 = { + isa = PBXGroup; + children = ( + 29D878281C84D2B0007B5F17 /* chapter07 */, + 29D878271C84D2B0007B5F17 /* Products */, + ); + sourceTree = ""; + }; + 29D878271C84D2B0007B5F17 /* Products */ = { + isa = PBXGroup; + children = ( + 29D878261C84D2B0007B5F17 /* chapter07.app */, + ); + name = Products; + sourceTree = ""; + }; + 29D878281C84D2B0007B5F17 /* chapter07 */ = { + isa = PBXGroup; + children = ( + 29D878381C84D309007B5F17 /* MetalView.swift */, + 29B186251C84FF5800E9C0AA /* MathUtils.swift */, + 29D8783A1C84D335007B5F17 /* Shaders.metal */, + 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */, + 29D8782F1C84D2B0007B5F17 /* Main.storyboard */, + 29D878321C84D2B0007B5F17 /* Info.plist */, + 29D878291C84D2B0007B5F17 /* AppDelegate.swift */, + ); + path = chapter07; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29D878251C84D2B0007B5F17 /* chapter07 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29D878351C84D2B0007B5F17 /* Build configuration list for PBXNativeTarget "chapter07" */; + buildPhases = ( + 29D878221C84D2B0007B5F17 /* Sources */, + 29D878231C84D2B0007B5F17 /* Frameworks */, + 29D878241C84D2B0007B5F17 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = chapter07; + productName = chapter07; + productReference = 29D878261C84D2B0007B5F17 /* chapter07.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29D8781E1C84D2B0007B5F17 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 29D878251C84D2B0007B5F17 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 29D878211C84D2B0007B5F17 /* Build configuration list for PBXProject "chapter07" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29D8781D1C84D2B0007B5F17; + productRefGroup = 29D878271C84D2B0007B5F17 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29D878251C84D2B0007B5F17 /* chapter07 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29D878241C84D2B0007B5F17 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29D8782E1C84D2B0007B5F17 /* Assets.xcassets in Resources */, + 29D878311C84D2B0007B5F17 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29D878221C84D2B0007B5F17 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29D8783B1C84D335007B5F17 /* Shaders.metal in Sources */, + 29B186261C84FF5800E9C0AA /* MathUtils.swift in Sources */, + 29D878391C84D309007B5F17 /* MetalView.swift in Sources */, + 29D8782A1C84D2B0007B5F17 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 29D8782F1C84D2B0007B5F17 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 29D878301C84D2B0007B5F17 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29D878331C84D2B0007B5F17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29D878341C84D2B0007B5F17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 29D878361C84D2B0007B5F17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter07/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter07; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 29D878371C84D2B0007B5F17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = chapter07/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter07; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29D878211C84D2B0007B5F17 /* Build configuration list for PBXProject "chapter07" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29D878331C84D2B0007B5F17 /* Debug */, + 29D878341C84D2B0007B5F17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29D878351C84D2B0007B5F17 /* Build configuration list for PBXNativeTarget "chapter07" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29D878361C84D2B0007B5F17 /* Debug */, + 29D878371C84D2B0007B5F17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29D8781E1C84D2B0007B5F17 /* Project object */; +} diff --git a/ch07/chapter07.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ch07/chapter07.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..92da390 --- /dev/null +++ b/ch07/chapter07.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch07/chapter07.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch07/chapter07.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..4118b493aa3470c7a114e07688642fe7cfe766f3 GIT binary patch literal 14862 zcmeHu2XxbA_wX}*P180_Gn#ayi#DSTB;5-I+EUO8El5f!Wt6l{+d$gXBn8TRf*>j? zI1q6l9ZUrm;y~QuzzGP7z9@pCxKLcktN!mVzb0*jSAGBIJLfy!IiEeY$usVApS$mU zE)5+HyW5kMbqHZZ5JemcK_c!EZda{#uFd7PJKJlu&W72xMvr@{*6M0(wZm|=*5m9@ zAbicn2jsXFg(5LhqG+T-29%C6kP!_R)Pb%-U1$Ybjn<&s(cNe{x(D^4t!NwCfp(&Y&|~Ov^b~p)y@Xyx zZ=iS35%eB9hCV`Hpws9}^c6aT38t9CAy|Y%u^5NpaID5LI2Om@c&xz*I1wk|A=rRT zI2-5VVmus=#G`Nt9*ZmRcsvnbiD%%MxE{~KR@{c$u@iUTtFQ+zzzZ?M*W&B&^>`J& z0pEt#;@k0hd?((ByYVJ`AHE+ygrC4q;yw5U{33n{@5gWB_wf7pDE>0}0(Nt#Iuagq*l z6>$+anMbZ8*OOJ`267|0iL54T$erXaayPk$^pY)PE7?UJCA-OEK9F3fhvw2eT1-b!3!Or1>2x}ST4@7qrY&?1boctE~Sj#KyRcs z(baSfy_w!ZZ>9IrjkKHg(4F)F`XGIX?xj!DXXvx^b@~Q10cQ2H4VQsXPI~zOOZ0#QZ!D^I*^jlC2ibZiK9%)blN@O8S#6p>vg|ToJu>~cg6f^`d zh(TJUV-mKDJqoyluvj*U&8nA;91OqO+A!ML?r}LC4x6jKU`$q7PF7j5DYu}!6cEfQ zH5Hc^XaS=(&&vLP@q!PR7Q*_r}q2Z43h%Z3d; zQ`kLl?BsU)Rh_nqCb*`(*$!yPl3{siqX(?Y#Ua+q;sRJyJDrXOtE<9YV|Uvd9Dq>l zz?`+AY|xaSh?!_O(r-suC>!OVT$G3MQ2{DMMW~oXGAWBC|$9*xRb43IO9tzT$Yez`&R$JA5j2*{t<46OX8$(?KMg?6EuSo-Tfw1#GdW#%`M@01N;VKm-vs2t>Kf zZEtB0f-s#2Q*LYMY-!=C?8i?y%x-h@tOXcj?GD>StEaVIrY?26!4X*7Jp$V9@zyS9 zr>9;PRcZ5B9XvR*d!D`76Xqwa1Kwi!t6etWtU5rzN@tU;-U664 zSzS#$U3o$aNP-5{2u@1)Zs}}jgVlAyH{V8?5_Xi^nysArQ!Jk$re#Hk(E_v(4p@X1qa|=iC-S0Y=xVgQ z7M!u8$z^M=>9E3Y&$LD!Zo8+ts{>9PP12A6?a&}kUz*&=hSg;HbwxJga^Z~R1-HSG&?mEGuw}Yvx6+YTP z3=#mX0TKcZ_VyMZyopx3s|WR<-oIH>TVJ%VD_; z)ypnv21Os9nVC7+4FaDD@&>|~33g)+1ag^;tyzWes~?lhKPkL$_!H>KdYQ7krrOU+ zzZmqOJv<36HYM!bi=M8RrT>|^10)TW${zF#5AGkY57v(7KtH??JI+PRSpf)jAwz<& z>_cn2(L7M6ECH$4(EfUv0gwtvSCB;wR^J}?51qj%XQysOs<_M_iw|0lEN2k<`nfCq4tUD}O4WFy$D>PpaD|Ln); zBvSOEhL!P3EyQ8pp>upV^gTL@en3B>pU}_f7dD!e zvoUNeyNq4VDz>0s(RuW5^cxs}KQLlfuyJfMn+|$EgUw{Krt{9O-0HFN_HmkklMh=6 zBmR>#f)@xfNmafuD9*0~7n#%e=f=zjTg>NA19oVde-3mMG^V4o!C`L{ysF9V>~uBS z`Y($kunZ~sumne9DUM>}StYAt6Z)_mE07LHvx)3Vi0~{tCt@cG{=*Nu+OPW%h5l)( zKWrM^YIRwG1+Gcf_7>ZW%k53JQir3$?e65crTfz+OFzGYccqm+wE`c1`u;EL7UmWX zOUW+ID_ktDU6@x0U$PeaGyo^#l<8HLfGl+N;AGT0$h+WFoF;e|HjUK?&cMfgoDQZP zXJ8{9%BHYdHuX=YU9jYSi#f=g_7C9#pAoGKHlji1QZS5D1E#KCrVluwadwYc5D!01 z%@!YbMuV3+h)YofE<-Cs$d3+dcR) z)GLf#fyV*wt1OkB9^NMpkf#@4!4pWJKqbgOu3`-=3u2sw3$u8t4og{BoCBW9%=%z~r7}omXRZ_{1wdc(z}-ER9ZI%n~%|+wOEh*ye6@**hSX2Jut}E%8C; z^;w{r3$5K4uo$=#&jTZe=Q3wEp3gdX+~nZE0ypPl47adx5nkGZ7vm-DDmIsO`7iCo z%aNi7FT+>3WOJ3Ocn(91AOdH zOFxFCH?r!qlJ<>3D^KE6NZ*4$#h{*m3vZewfN?Q9*pV>A94|ANnflQ<6rf%WWOwh?r* z5B>+4;L8nT=666QWoz;YKcAoQnP9(Tm;{blAiw_(LN3Oq{V)f~g5MwtQU&gQOgpdX z;LQ2#G;pz?L&|K;PFKGi!VUo>A5~jMSMvV1)BR^?{Z}O+BorySiHP0VO~mXjzibGm zq}0tr@-LMTDToA#WOsLyD0UBeiKrm<-q1r-@L>b|%$gWvVsr9~ zhoux|>? zce-B(Nj@nIoKeI!4V-Zaxim;y$tY3^AbeJhl(8-S!cWHFrM+Y1 zJs?TE#T7Cu@C%y2ihf}Zn$7#)BtGD5e4e++=X$gA^1$~N78fpt@CFKl#KVWEF;Hyt zhp1#eVGyE{F0z0uB#X#mvV<&UkFm$u6YNR0hdssiZb4eIj9g8YlNIC|vJx)$v=?W2 zajqAadU2B%+kARj22`2T;k37V+`ifvMAx8V@%=T6L7}UAtkVVIg?qYCLbEis+W0zM zwD5IOXFK>#AeAp)ua{+wx4J!}ooyWs8vq>05rl1J5Xdz7HbOZHk}~kTU<~{kFI4h? z(6NFg2o8{V9Q#x?(SUhPk*2a;=^%4SCgV4lgRTxNIRa(?=4BRe6~BHPJ* zJ8HXh^@dy}U%t;FuL3;y_rJV*BNw|kzvKwcy-u{YUU>}~c=A94DL4X(%Ln#d~zl+t+7vo%#aJI34Q+8q5?FNZ5@1#3`I zUhNDZB-~`8({1N7(n@Pb+Nd)EMs*88rH7^DWo7p(^g+lv$RYABIn3T=huIO9RoB`+ z&osZrl(nF}uD1CyljBNL@x1c7vZ8WRR+TA#p2bg-56QoRt@Ov_6P`%N+0kxtf_)e) zKA-!<=Yx9L@c&kP%=7t5881EllfNWqczS+Cz9!$0Z`r@tG4>JrxQ~2Cz9(nN59~Pm zl6}Q~;<=O_q!EGwn}xh{Jk&tVZod3H7dQvr{31&yx@>dp&Q5o=)zxC_uM&^upFl3Y z+%KAb1LCh2!Ezzh@~f|aNWF04VBr2Mo+rNnEd`JFJNu;H<53LZ9wn5r6YTSVx1%B& z29Ae@QZYNpKJB65G=hD`PW^+J9iBG^h!K<|4Cqx_iLGR?pQ8$@3OY_rW7rq$v@g0` z+3H&g72yl-=5rx55nKpOVqdeYLv#pK@}QnaQ)wF2Qr%RyFEs+0WoOv8>>Kvu-&gT2 zur>qYk_id>@`K^tpYr;tN;Bv%@V3-QhqCY3_dV1^&Fn1ufz7HB7*Zp!;-c6O1XsQk zh330?{y|j=P@pZ1hUUu<9q95ns^pYSoqa*3%@CHFg(Gprp%jjrYPRG!( z^fLAf`<4Bh{qDuci-{L=UM%ur@itmPub|`Tcv?xT=ma{EUg^c*Uaat9wHL>GagrCO zda=%nGrV|MkkZl`pVFSImzDjuN}E~Q(NPZEgoh!UQ0*DyOXxHo-1GHvY@TnL&#Siy z-Y`0S%GwP``jkz0D1dsd0j(*4)uQFlddXe4KweJIkD%ZFV=! z$+UFA14>)wczc5j-Z3(LZ-w*tw=Vv09{*hT$x5%Y@*>I?ErfVBfiGq7qf5oh^`_}kyB$X^w@2Llw!IDY_F@-EItFn6B|D%ivT;W32^k3@#9B*dxyzydOFDv=4H78J?yHIbO0$5rvEB+g>K|Hs# z`XtcY#=mL~=D0_I7Xq*5e*^CVGn@Gzfp!T%L+fQ@{%fGTXbnVP7ZPBJ06Xlz6?%B? z<BKSUwkrCxds#1V8Ey_znkE4(BZ7Mx{_Xtbo6>Jj`Cs|o8-lEKAiZ! zR(M{1;G4Baw%77S(VU#T#kC7_a&r0lsNYN6M%TktE-0SUJLz3;jeERU>4g$HTtmfX z@ow>KU*3eU=?n9UvkL%Xc5&|FsSES+`LcFF0A??R8rel)Zll`)=KWqAZWaq@Mz$Q(mn1VgnB;y&tub zpU%z~0QpC`YK5 z@UKV01M)xs)lVW$!D*0UE2re5ITfeoVz^i?j)RCK&x`ZDxWJ1Gy|~DWi@kWb7hkfK zOMvo-j!WiJxFK9B(t7cwP)q0Mj41@2t zH`*%PQ|$0~VdDe&=)n{Ih#f*eVc7Rd=7EeG-rxg+0+6xRHoKz>-t-0o;H%CK{?P<- z%E99mZm?^OE+|4w8|2UHWvNYbJxxBGOb%!=aF`mQR?!KW-*Dg8R;SxjBSZreXF`lp z=5)@1+%`LFShk;vxm+RC9=JR%p97MWdGTm3F7M@vxMB{-HpYt^ytt7!URhAS3a)kZ z*F_-Uwsf}f4H*KbEVdTDDGO-B_ZkInnb6VSD#ACb1W#4lJr3bff-AvGH*uw088@0M z=KzJVUR>$L5O_}Z;;Dheg}a;^&!b+!UBQj>;>*1FaxbpvGL;;S68tHLXPKOKhN*Cq+k4%7wyQ z%T2%7U1o4IIfw+RycljY5wxj9fP=0~ne40m_}OUV>=)ZVo14Qqycne1;>FecexZJk zCJny`5-x7;MSzf(x%pfdJK)7NUOa`(>c7JQZZV4BmT*h?C%qt2d z=u}H*W24OmCHjMMMYvKOcah%1o@f>0SV&JyEVKiLv51-~%UB5LVdZG2!|6Jdn3Noz zG9)z(#x3>*HaN9;ti#&khVQ%$N-NO|gqKIk_-;Z_Pcxq<*n~)aas>~p%;{)4pf{vv zT&yjo|G=Jf<3M-IFjKfWGYfE-(hBt%xS0jYHlZ!hbNnE58$X9$fj;B+pbg?A z`V4)JF?1Hop_h0F)e+4^uo~9s2AwWfAj0b3hoAY`vDuVlDn20$6e2@ z@>z;HFP;X*!i%SS@r=!2GH&8lb8F!DO+Ldh(~CjttX>QspbrA<>|d+8&_DJ!ivTS! z>wHU0u;B}`Mf@U*r;G2@{F{}0*Me{50d74g;+@=Gyx8-7Onij)$GNi+v0e=Ce9)@J z-NS7V=wj>P?%_)c@@i+3wJXKyNy*L`o?DbsS}8j{V3d5N7OodB?M9KHVnTxnw*{;+ z)C?}8<=lO=g#8<;1HMW@GZYTG2IU3ZLqeF{^8Zu8|6Q7X5$)t2<#tc@wchv?G!CW0 zKN!e|PTf&d39aXPYKAuR5;_LBQvr3FiF6XJhNkjcpoM%Vw2nVachTMSarz{EitdNz z@wezZ^dNng9-;5k54Z$wC^rEt`9|(3?g)31JI9^pe&hZK!67sxBqTH>EF>Z%G9)!b z8=?5)e3o(aeh2(_fg%pGog_MU(39*H&4cQuUB;;hs&mxg1S(Gix5seZ}5><<8 zM75$i(R9&F(JWDes7W+W)FoOdS}a;B@`|n&tq`pgT_;*4x?S{uXs_sy=p)gOp|PRE zLPv#847G(W4ZSn;?$8aP8$)|S_k_L}xz{M+#F!hem>Mr1@-BBnH{mFOiVNv0%Qk}JuVSS4MOn6Yx2?3Fwtc~0_zPDfvwDx#YCu=SUiv6qyrQ73qka zA9+*cU6Fl}n@woklripmi9_FNw-LMNq0*hmp&qj z&q>cqe~Su@%8D8hH74rHC`;7js3}piqMD=TM0ujFkGeVP&Zv8$?v3h>dOYf-s5hhD zjye!^DC%(3M^VS4PDFhgbt>wMsPARrGLE|HCpjg?(4yFxZzRwbJ# zYnQE(?UcPNdt3I7?4ayp*$LUFvd?9wWnamWJWMW?%j61qw0wwMFHe^n<(cwqd9FNP zK3ZNQua~#VJLL=Hi{wk>SIbw(SIV!G-zvXbzDd4IzDK@S{+j#^`CIY>@udLZ(nCq7~_iY(;^hNHJV-siHzrrI@Igq?n?Zs+gvjp=eQbC>AT0 zDV8g)QLIwjs93GIS<$PwU-5+EDaF%@=M*m}UQ)cNIH-76aYXUH;xomUimw&lDt=J> zr1(YgtKz(pQ_7WUWvnt@nXDY5OjGKVX5}Ty5@ngPTv?$Ur>s;?P&O*BQEpT2R=%Ko zN%^w!Rpox=8_KtoA1aS2KURLCJgNLl`ML6RG>(=Hd& za@AN>g=(CtQdOs#p{iFksG3yGDz|E`YQAcrYO!jm>IT(n)y=BgRJW_{P;F9eR&7yj zQ|(qgq1vN*TJ@~zdDVW^0o5VZVby!8qpDM?uTapqx>gj5$x>0RY&sICs?dlHo)#^3swd!^1_391kjp`nCpL(DAWQ-;z zFJ?qcNlaNxdCZkDvtk-znqrz`T4QF%IAYpk7RM}&@y0BVSs8PE%#AT?Vs44q7PBwr zV9e>*#MsQ(D`Ka_&WxQE+Ys9nJ14d+)){+MtUGo`?5Q|eTw+{GTxy&y&JdRoR}fbe zH$3jrxa;HA#cho1iR+8o9Je*@p}0rl9*uh}?uocPaYy35jF-n7;|t@5$6p#hD!w#+ zbbNh$YkX(?l6V%sEPi?XHSw$CZ;rn;er^1^`1SF9@ejto7XMxRubL2zRHM?wXyP;) zO`;}UldBo28K)Vqsnkr+OxM(FtePfGv!+$kshOwg(k#?Gu6arGrsi$U0nH)JVa-RH zyH35_=N+ z5;rGqP28UNdE$48zbDb8kfhKgNs=^4mZV6EOG-(~Pa2hUc~WbVGii0wrlg0H9!c7j zv^(jAq{B(?B^^!rFzHy*@uZVUr;<)5eVvSwX|gCeELoBqm8?isCC4Ufk`t4S$-|P( z$yv#r$;*ekvOndGArV7jhr|y_7?PA)liHYSOKnM=ow_6S$<(J( zpH6))^|!R}G)bB?O`bL>tv=0~)|l3uwli%{+TOHh(w>JVhe)kj8>dasCTml*L$zjY zwl-H=pe@o`vqqKK z_2v4p`U?FxeYJjuezxANpR4cEFVZj7U#nlGze&GFf2)42euI9C{z3g-{XYGx`q%Yu z=?~~X&>zzu*PqaTrvF_3o&Hxts6l2>7@`eoL#$zlL2ED=G7Q5EW<#N&)KF=tGt4l| zGBg^R4XuW`24=X?u))x6=re3FY&YyMJZN~tu-ovm;WfkShBpoG7!DbZ7>*h~G#oR0 zZaAARNl!~JO0P_}r7uapKK+68-RX~|?@K?Jel-1G=^v+`NI#wab^4j~v*|x(q-TuI zn4V$F=*Vzq%+2V^Sd_6e!<%ta#@dWKGVaRQkg+LaYsP&UJ2M{4c;6Um%r#zW9Br&L z))}qFCS!|nw(%;X$2iZpz_`e`!no3Sqw!8-x3SN-#kk%0ka3ssG2@fQr;INdUojpq zeq{X2_=WK+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch07/chapter07.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch07/chapter07.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..f85199c --- /dev/null +++ b/ch07/chapter07.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + chapter07.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29D878251C84D2B0007B5F17 + + primary + + + + + diff --git a/ch07/chapter07/AppDelegate.swift b/ch07/chapter07/AppDelegate.swift new file mode 100644 index 0000000..b124b06 --- /dev/null +++ b/ch07/chapter07/AppDelegate.swift @@ -0,0 +1,13 @@ +// +// AppDelegate.swift +// chapter07 +// +// Created by Marius on 2/29/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { +} diff --git a/ch07/chapter07/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch07/chapter07/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/ch07/chapter07/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ch07/chapter07/Base.lproj/Main.storyboard b/ch07/chapter07/Base.lproj/Main.storyboard new file mode 100644 index 0000000..3d10714 --- /dev/null +++ b/ch07/chapter07/Base.lproj/Main.storyboard @@ -0,0 +1,682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ch07/chapter07/Info.plist b/ch07/chapter07/Info.plist new file mode 100644 index 0000000..69d1345 --- /dev/null +++ b/ch07/chapter07/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Marius Horga. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/ch07/chapter07/MathUtils.swift b/ch07/chapter07/MathUtils.swift new file mode 100644 index 0000000..58b4ed4 --- /dev/null +++ b/ch07/chapter07/MathUtils.swift @@ -0,0 +1,62 @@ +// +// MathUtils.swift +// chapter07 +// +// Created by Marius on 3/1/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import simd + +struct Vertex { + var position: vector_float4 + var color: vector_float4 +} + +struct Matrix { + var m: [Float] + + init() { + m = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + + func translationMatrix(var matrix: Matrix, _ position: float3) -> Matrix { + matrix.m[12] = position.x + matrix.m[13] = position.y + matrix.m[14] = position.z + return matrix + } + + func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + matrix.m[0] = scale + matrix.m[5] = scale + matrix.m[10] = scale + matrix.m[15] = 1.0 + return matrix + } + + func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + matrix.m[0] = cos(rot.y) * cos(rot.z) + matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) + matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) + matrix.m[1] = cos(rot.y) * sin(rot.z) + matrix.m[5] = cos(rot.x) * cos(rot.z) + sin(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[9] = -cos(rot.z) * sin(rot.x) + cos(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[2] = -sin(rot.y) + matrix.m[6] = cos(rot.y) * sin(rot.x) + matrix.m[10] = cos(rot.x) * cos(rot.y) + matrix.m[15] = 1.0 + return matrix + } + + func modelMatrix(var matrix: Matrix) -> Matrix { + matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) + matrix = scalingMatrix(matrix, 0.25) + matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) + return matrix + } +} diff --git a/ch07/chapter07/MetalView.swift b/ch07/chapter07/MetalView.swift new file mode 100644 index 0000000..a042c98 --- /dev/null +++ b/ch07/chapter07/MetalView.swift @@ -0,0 +1,66 @@ +// +// MetalView.swift +// chapter07 +// +// Created by Marius on 2/29/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +import MetalKit + +class MetalView: MTKView { + + var vertex_buffer: MTLBuffer! + var uniform_buffer: MTLBuffer! + var rps: MTLRenderPipelineState! = nil + + required init(coder: NSCoder) { + super.init(coder: coder) + device = MTLCreateSystemDefaultDevice() + createBuffers() + registerShaders() + } + + override func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let command_buffer = device!.newCommandQueue().commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) + command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } + + func createBuffers() { + let vertex_data = [ + Vertex(position: [-1.0, -1.0, 0.0, 1.0], color: [1, 0, 0, 1]), + Vertex(position: [ 1.0, -1.0, 0.0, 1.0], color: [0, 1, 0, 1]), + Vertex(position: [ 0.0, 1.0, 0.0, 1.0], color: [0, 0, 1, 1]) + ] + vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) + uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) + let bufferPointer = uniform_buffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + } + + func registerShaders() { + let library = device!.newDefaultLibrary()! + let vertex_func = library.newFunctionWithName("vertex_func") + let frag_func = library.newFunctionWithName("fragment_func") + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vertex_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + do { + try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let error { + self.print("\(error)") + } + } +} diff --git a/ch07/chapter07/Shaders.metal b/ch07/chapter07/Shaders.metal new file mode 100644 index 0000000..2223ad6 --- /dev/null +++ b/ch07/chapter07/Shaders.metal @@ -0,0 +1,34 @@ +// +// Shaders.metal +// chapter07 +// +// Created by Marius on 2/29/16. +// Copyright © 2016 Marius Horga. All rights reserved. +// + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +struct Uniforms { + float4x4 modelMatrix; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], + constant Uniforms &uniforms [[buffer(1)]], + uint vid [[vertex_id]]) { + float4x4 matrix = uniforms.modelMatrix; + Vertex in = vertices[vid]; + Vertex out; + out.position = matrix * float4(in.position); + out.color = in.color; + return out; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return vert.color; +} diff --git a/ch08/chapter08.playground/Contents.swift b/ch08/chapter08.playground/Contents.swift new file mode 100644 index 0000000..96ca6ff --- /dev/null +++ b/ch08/chapter08.playground/Contents.swift @@ -0,0 +1,8 @@ + +import Cocoa +import XCPlayground + +let device = MTLCreateSystemDefaultDevice()! +let frame = NSRect(x: 0, y: 0, width: 300, height: 300) +let view = MetalView(frame: frame, device: device) +XCPlaygroundPage.currentPage.liveView = view diff --git a/ch08/chapter08.playground/Resources/Shaders.metal b/ch08/chapter08.playground/Resources/Shaders.metal new file mode 100644 index 0000000..a9bad7e --- /dev/null +++ b/ch08/chapter08.playground/Resources/Shaders.metal @@ -0,0 +1,25 @@ + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +struct Uniforms { + float4x4 modelMatrix; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], constant Uniforms &uniforms [[buffer(1)]], uint vid [[vertex_id]]) { + float4x4 matrix = uniforms.modelMatrix; + Vertex in = vertices[vid]; + Vertex out; + out.position = matrix * float4(in.position); + out.color = in.color; + return out; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return vert.color; +} diff --git a/ch08/chapter08.playground/Sources/MathUtils.swift b/ch08/chapter08.playground/Sources/MathUtils.swift new file mode 100644 index 0000000..cc13d82 --- /dev/null +++ b/ch08/chapter08.playground/Sources/MathUtils.swift @@ -0,0 +1,59 @@ + +import simd + +struct Vertex { + var position: vector_float4 + var color: vector_float4 + init(pos: vector_float4, col: vector_float4) { + position = pos + color = col + } +} + +struct Matrix { + var m: [Float] + + init() { + m = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + + func translationMatrix(var matrix: Matrix, _ position: float3) -> Matrix { + matrix.m[12] = position.x + matrix.m[13] = position.y + matrix.m[14] = position.z + return matrix + } + + func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + matrix.m[0] = scale + matrix.m[5] = scale + matrix.m[10] = scale + matrix.m[15] = 1.0 + return matrix + } + + func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + matrix.m[0] = cos(rot.y) * cos(rot.z) + matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) + matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) + matrix.m[1] = cos(rot.y) * sin(rot.z) + matrix.m[5] = cos(rot.x) * cos(rot.z) + sin(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[9] = -cos(rot.z) * sin(rot.x) + cos(rot.x) * sin(rot.y) * sin(rot.z) + matrix.m[2] = -sin(rot.y) + matrix.m[6] = cos(rot.y) * sin(rot.x) + matrix.m[10] = cos(rot.x) * cos(rot.y) + matrix.m[15] = 1.0 + return matrix + } + + func modelMatrix(var matrix: Matrix) -> Matrix { + matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) + matrix = scalingMatrix(matrix, 0.25) + matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) + return matrix + } +} diff --git a/ch08/chapter08.playground/Sources/MetalView.swift b/ch08/chapter08.playground/Sources/MetalView.swift new file mode 100644 index 0000000..9305067 --- /dev/null +++ b/ch08/chapter08.playground/Sources/MetalView.swift @@ -0,0 +1,69 @@ + +import MetalKit + +public class MetalView: MTKView { + + var vertex_buffer: MTLBuffer! + var uniform_buffer: MTLBuffer! + var rps: MTLRenderPipelineState! = nil + + required public init(coder: NSCoder) { + super.init(coder: coder) + } + + override public init(frame frameRect: CGRect, device: MTLDevice?) { + super.init(frame: frameRect, device: device) + createBuffers() + registerShaders() + } + + override public func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let command_buffer = device!.newCommandQueue().commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) + command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } + + func createBuffers() { + let vertex_data = [ + Vertex(pos: [-1.0, -1.0, 0.0, 1.0], col: [1, 0, 0, 1]), + Vertex(pos: [ 1.0, -1.0, 0.0, 1.0], col: [0, 1, 0, 1]), + Vertex(pos: [ 0.0, 1.0, 0.0, 1.0], col: [0, 0, 1, 1]) + ] + vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) + uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) + let bufferPointer = uniform_buffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + } + + func registerShaders() { + let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let input: String? + let library: MTLLibrary + let vert_func: MTLFunction + let frag_func: MTLFunction + do { + input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) + library = try device!.newLibraryWithSource(input!, options: nil) + //print(library.functionNames) + vert_func = library.newFunctionWithName("vertex_func")! + frag_func = library.newFunctionWithName("fragment_func")! + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vert_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + rps = try device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let e { + Swift.print("\(e)") + } + } +} diff --git a/ch08/chapter08.playground/contents.xcplayground b/ch08/chapter08.playground/contents.xcplayground new file mode 100644 index 0000000..06828af --- /dev/null +++ b/ch08/chapter08.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch08/chapter08.playground/playground.xcworkspace/contents.xcworkspacedata b/ch08/chapter08.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ch08/chapter08.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch08/chapter08.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch08/chapter08.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..4b12b70ee54fcc35f0dcf5400cbe4f928aeff114 GIT binary patch literal 14980 zcmd6O30#y_7x!HrTv%s=VP=?N7GU-n76B1A6x?zL6;~W!gi&B{W>Cn;`qT=69cGn1M0--s*kduMham^4xpRJ@+jCbMCp9 z(%LGQ*O!|55r6;z3>Xjw+A&`;XNr@iIXzyNyQVnFT{_uW=JSqDa(K!rUG#BLlFwZ$ z0&wo?O+q*gvQ4~exN@X1O|iQpb(4##b6v5 z4;;V=szD8KgE`<{a35F*9t2ClGVmx^4pxE3K{Hqb)`O?OGvHb90@w^*1G~U(@H%({ zyb1mV_JF43b+!kf=|E~;AZ$D+yY;MTj9%a8+--64-di*;34=S z{0JU~N8rcsC_Dx~fuF-u@GE!$eh)9gAK)eU3;Y#@p?0V}>VQ-z5vh>|X^{>kp=6YT z^vHnB$d1xcChClGQCBn&4MKy_5Hu7GL!(eJnt)1>3r$8-P!;l^X=plXL@b(z9zYMF zhtVVG3A7qDp$+J1v=Kdn_M*4YKJ+$v2fd5-qxaAO^gcR>K0qhXXXqsQ9Gybnp$q7H zbP@f4uAr;vI=X=|?tleYh(%bA6*vKFu?`!t33tMoI16XvTs#O5#zXK>JPZ%Vg}4Zh zz)m~~SKvzQ!d~pd_4sZ)6W@bp_yxQfzlgWv9e5{x z4Znf+;sf}7d=MYS$M9+VB|d|{!sqaHd;|Z6Z!&;^3}P_DFddj^M$E_s7O$I$l{PZ^n1R^{+|n?V$aCWzo>AOJ$bkbB6i5`m3VDYb4_jnA7`=5tM>t>q;G zWyqL59!Isa&~>M?W!NEJU`CL(9+-d`Sb!DSfE}cg2og;ML_{Pcj>HrBhaiIrwiCz% zSs2L-Su7UcKZk~MJ#)@!{e&+ z+Vh>>DHNsbWtEOvpVO1t*;ZTSXsGbG>uSmmfi55ybOqhU_!U({c`f#Tbb3b&E~M*h zrp?`p2Nw?Ev9B#xy?72{N(AYXTvg7$G_SoaoxVIBVTmC7Pp)K;)90vavx>IF2J*zj zB|@kUQ1ecAP4Zd2?mADI(@J&a^h}}#_lNx6O5I+_kM!F4hLJAkbQ@2xN0p{iT)-{$Yun|>VF(qQZBtZ{lcqbTH9=pUFmrG*zxY~60JtUt>{O3UKPr*x}!l)1h2 zX{olfw3eqnho{2n>sH@6t0b$F)lpkp<+Qfx)mCi7c(KL)PsHZ%RgUnvs=WWG*g~23 zZ;5RrFE;7_L~NXq7dgGYe^hLtO#HXRHkKEgjEYVB-*(c$&gseNsePzt{gZOLm5cvG zaDI%Q07@ndE*w37ia``gPDK;7R&V0hqKf)8%|7BtPo^Uni>1|1`{a-_d=ZrY0jK{%b-GM72P#E%R@)$@^&oDlvM9p zFm6U#W=1EAIxQnBr?Ervj7}Mu7IkW)ANJk?`$`1jAn@h8XqxS=q0FuUZ-KW#_i=*@ zTb~8i{w_Gkt$jau4;%pRlWwFt=|Os~1s{MzbnPFJJkpDE-n^d-4ej0?Wn3D5QMlSHnfJx~d?w`E8NlX!-T$>>&wzB>8&{Fj3236Lp$apegElh*yl%r0hgiNF)9RH|Z?q8asx9Nkd7thE_=Y2D1{2{KHkj5odC7f@F}2O51U{!Tm#p_ zb?`~Jp3Ek5$Xqgy%qRDf`_{t^@M*XaM8jszuE_ml0SoJBhCYWkt=tJ*6^t)8@s*+y zLHD+0u_8xlZ+DH)JEdjzw)QIM+{v1jm)9#JEh{T8 zGe3u#DJ3w(Lo-old9b_|LWi2ErR^mC>09R+QRA9g=j>ljt7NW8E;_Fuk#^@RT+Z85 zED^{!g8VXy-0rGUho`@{C0U?8(c0!H?G@4_ok6ia$D;0>)@V`B$jPFpot=}_7{u*Y z;lJos0&a&p;7<4&+y!^T*WnxRP4WO)NFF4M$YQdDEG5gxLmS{8poVY3eeiAg4t0?I z@ICS{74akFQPND_rH*ohe9SpYT%OlUEB%f@3D7&x(crG5g+~Epv#`=VeXwJitHMEx zgJbCfD!74;QfC!~8*UYWa%G4-x$1_?*N{i6fra!G!N(b$pInd>*LI84LrBmfovWhe zHWWC9{PbN;FJ~)sSRcB(9ZFN+@${>I*TxML09sPLU6C(ftHtkqQGTXt1e7p#Fm~g+5PRnXk^{Y~d7j zL^O5SfWlD(ibPQ;8pR+15+V^7Dv6_pG44)=^XLEcdUF8^#%mw^u_^L#?w!5X(JiNxS`Prqo-82FY<<=`+rA{Uz~R zxhWBdXj`y5yIGm(jWk`S=K#ovOsmOe9x9OqS!s6OQn4s> z`qt1VHqf0`mFX9M_tci|+|Ue=MorECJgd#~9RBlP&{sEvycOoqB8O( z`4`!Jn zEr{%>9^DxvFoV3)O5koZ(@!8kaTb~#z%4X~>?gT?Bbg7<)}VXQedvDj9yv%p4B`}8 zh!(fS7PJH{B?rj+oU}NM52}(wO$6a9;v zCO@+R%)MC+Yt0g>|LXl)@PQH=dY4z;zGMX`QdN#@L1tbqjAp zIig-4%~oh)?s0nQ2R`lQpemGCdLBbh#KzF%od*22esu_aOgA#~W0W|N z@`P37mnN(xzj6ym_8VYJ8u&-n)Uqg?gi|;I$>e$y){`3~w`h>VRTF46V>=M7!4_=A zHu4*}$wIIOr@}ororREdGbINI#*i7gAmA*dNhjSJsP#)U1Mb)=H@9T8a z%A%)%*C6hUE;r#E79w&Xz*twDPd6&K8}5#K;GQ@S_rkqdh*`+6FpP!mSlFJ09az|L zJubj~a9`Yy{tm!*urQp35iAt2P{RKySeQU^$I+PO%y;-4oY{=^v&b{g?ST2qF)bVA zHvULWC76qFx#nPc*i6%pK#;smnG3`%Mt{ZG|*kfBiMx2<#PEx-=msZTkB&k zeWQ6`{g6q4v8`<^l(JC7LOBbCEQ~7=*n=r=h^+J798FtrZxhUb{l-+s8PhZtim5T- z27D*wyB{^^#xbokjo^8p=D}Hb?1({JNt(wGOfc(Dc3O>slBbr=j~ME3d7AMo(EZ=^ z5zoBo|M?Klq0`UB^YDC-Ikvpz&Iq-D(Y`>@nuYN!lo7favQ45k`sa`N{R}U_572@$ z-M<9n8PG*DUdZuzyC(n0MR;+Ez(4~|h;Uoi9U7dP@e+>QpYHz`4&j3LM({kYghB=4 zSLAX|k&m%ZMJ|LS@!46~G&f7n3Fc<_alD$txF=YsZo*A0)bKce`@JGw$HDoNcs&cX zEKF_%^r!K&A?W-Z-o!#33zH~52g5SO^hF`~yam4;GHM%sg@q|B)N^jg<+^Q?16|M2 z{9qt}0i4@~cZXz;_)Yw;&kKjY%Sar`Mh z!NN2aQvAH6 zg;^}jW?^R*(y-Bmg}E&3x*lJ_KjN$SC;Iy{pm||87ItT04;IqMLH`EOD@*_11p;wM zAn;#_YEcRk#x;2^A27j53OgOFunGE%lek|-s;gTLi!@j)BFfr(IGb3OqeCDw* zKNw9J2@^*hgo$NguO|Exl?LY^q8h$%L~}MSx|MKusc7ZwcA31|z@4#GxoVuo0B;G5 zileAxVL=m<$ihA(cZ{n|1x_2pZtkq!pUC#623J8V&9)-`=GUz#39|8gMo%Is9I~)K zSAXul$bN%n@S(K)!8-tVEwud0H&g3jEG!&IuyAA`0+04DzLHzKi-n_t@sz3J;wcM@`S97gPrp^6jE4(*EF9Ys;Qq$F zyH?_VC!jDMe?S@QUr8gklDkQ5QW;KRVJQoJN0|GV`{^VLm{RYaR5}H@1wUUE}jt$<%=a;*Wy#ShvR&*iCY%Kxg!_u&k}F zmoX3Vx_*>}l`Jd|=(@r$p~pB0tzeFav^l!W==BPK)jQMRsQt^M!w9kx{Za^w+y0l&1DuduQ9ve zQEnhk-U1Gj=`01Xc@ zG}wlsVbB@)Y>PR@d{QFN(|jP9wuaQxLk+B%InE_pf3~}Sh7-(ZB?8@_n4y_D$x;6^ zUHt+%MMVvp=>ZVU!(s*(-r;O;mitZ6>G^>9ia9%i-%1fk|D8YvwDgv6CcUTI1Ka5p z^ImjQHUf{s4qQgBl~1Nyh#G2t^YC-@!uVdA)VzcD)9c~~Y36YPpTwu=h4C}^EWIEu zVbUmUR?_Ru|rme&K2KKN0>#_?O{dg?}6VUHJFmKSanQdPfY6D2s4L zR7AKUrbJXnxFe=Ucq8f}=11HYu^?h$#G;5L5z8VTj(9ZUv51us8zMGFJR7ko;-^R^ zvR!0{$neOak>evvA{~)sksBhnMsACIHF8H36D5oiN5w`-qb5dGN4cY>MtP&QN9~Jx zCu)DxfoMszCR!Jr9IcP8if)LW5#1O)Gy1LQkD^aRpNu{geLDI~^o8h)(U+pHL|=`* z79)=764NiHHl`tFZp^%xMKQ}`HpOg>c{Ao<%(0l`F(+b9#+-^d7jr)5Ld?aOOEFgj zF@h{XzMx7_C%9WMSFlvDQt-H7wV+wBR`9G~li&rxi-MN~FAH`H-WD7boDh5^_*!sI za9(gh@RQ(Y!LNcFf}27pOc3@K4ih#AX9@2YE)zBhpB6qNd`|ehaI6 z7xxkO6Ausb4(uL9$(&wblOE*imNViJ2Nne%j zkiI6}E&Wh>So*Q_nDn^xg!H8Jl=QUpjPz_gh!@8v#t(@vjb9wUHvYx<*W=%e|0Mow z{JHq^@!!Y)5PwSFHp~waWF%4a$wmEz0f6oyuLx*OhN74=N8UKUN-7ey03f z`GxXJ=c^p;D?6RT`CD)mc@b8lW1e8muZ*jZlqJjaF5u>Qv3DO{%@B zeX4g<`&9>22UUkuAE}P0j;cOUeX6>w`cd_h>KD~@)o+O~5hu1w?3fst7?UVW)F<{# zEJ`d*Y)G7)_(RP76E&rpa!s|yqw#5`Y3em|H1}y1XclUgY97)&qFJtK)@;;l)9lpj(!8$OtJ$Y{ zN3&mZL~~MeUh}=?2hA1DRn0Z6T5Hv&YSXou+H7r(w!8KY?Qm_8cBFQ+cA~aS>(o|i zCu<+pKBwKQeP4S>dszFi_Dk($?N#m1+UwezI;0EJb6(S9Cw=e%4*r{gxDw6rChY5+}tbNt0wriliP%^q)+U zs*>2GWl3w2wk91)I-GPg>3Gs-NvD#<$qC7c$=c+kQoNDW9gCN%=bE z+m!G0j9#dh=%sqOUa3#iXXv}?^Yr=pzWV<9k@~Uv@%j>dxxPX_Szo1}rk|-_pkJ(C zs((oTn0}RhwZ2)uMZZ(OOTS!DH|lRvWe%4jPUbJ~f;)oHAT6 z+%N(oHnuZ%G)5X@j3T4Pm}Jx&O-8FR)tF(-G-ey~jYEx7j5CcZjIS8?7>^sjHhyC~ zXFP9$CdSm>6mE(%#hBtvN|V~8GbNkSO_`?7rd(5ZQ%}&9CrUy)mOiN6w zOmCRpH61m5Vme{^-1Ln(+AKB8%}R5kxwE;zJkUJEJls6OJkDHVc9_e}lgw_j$6RNg zZk}ykYJS+f+`Q8Kgt^(g&is`5W%H}%o#x%mLSjJl>TFNX{7PrM?@mW~QY|C8By_Thxm6i>b zXDpj6FIc{^T(rupDOQ8kWVKqetU1=M*6!93)=AbG)`zUmTVJ$pwZ3BAVLfd9%zDQ9 zgH2*n+qAZ1o55zb^|bZ2^|AH04YUoh72C$zCfFw0s%^D4kFCx&(>CAsknK_13fn5% zR@*DK?Y7r!yKQgV4%j}hePlag``&iR_M`2Z?H4DR!gXVz=4T?0xM0 z?E~#Y?8EFu_VM;oyVG82pKPCQzti4mC-!^nbL>m(57{5JudqLEUv1xD-)#TXekwI0 rRg&5zwMVKmwI+3HsyDSRbzbU%)Fu966`~g!xF6 + + + + diff --git a/ch09/chapter09.playground/Contents.swift b/ch09/chapter09.playground/Contents.swift new file mode 100644 index 0000000..96ca6ff --- /dev/null +++ b/ch09/chapter09.playground/Contents.swift @@ -0,0 +1,8 @@ + +import Cocoa +import XCPlayground + +let device = MTLCreateSystemDefaultDevice()! +let frame = NSRect(x: 0, y: 0, width: 300, height: 300) +let view = MetalView(frame: frame, device: device) +XCPlaygroundPage.currentPage.liveView = view diff --git a/ch09/chapter09.playground/Resources/Shaders.metal b/ch09/chapter09.playground/Resources/Shaders.metal new file mode 100755 index 0000000..e52b42e --- /dev/null +++ b/ch09/chapter09.playground/Resources/Shaders.metal @@ -0,0 +1,25 @@ + +#include +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +struct Uniforms { + float4x4 modelViewProjectionMatrix; +}; + +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], constant Uniforms &uniforms [[buffer(1)]], uint vid [[vertex_id]]) { + float4x4 matrix = uniforms.modelViewProjectionMatrix; + Vertex in = vertices[vid]; + Vertex out; + out.position = matrix * float4(in.position); + out.color = in.color; + return out; +} + +fragment float4 fragment_func(Vertex vert [[stage_in]]) { + return vert.color; +} diff --git a/ch09/chapter09.playground/Sources/MathUtils.swift b/ch09/chapter09.playground/Sources/MathUtils.swift new file mode 100755 index 0000000..81ef738 --- /dev/null +++ b/ch09/chapter09.playground/Sources/MathUtils.swift @@ -0,0 +1,63 @@ + +import simd + +struct Vertex { + var position: vector_float4 + var color: vector_float4 + init(pos: vector_float4, col: vector_float4) { + position = pos + color = col + } +} + +struct Uniforms { + var modelViewProjectionMatrix: matrix_float4x4 +} + +func translationMatrix(position: float3) -> matrix_float4x4 { + let X = vector_float4(1, 0, 0, 0) + let Y = vector_float4(0, 1, 0, 0) + let Z = vector_float4(0, 0, 1, 0) + let W = vector_float4(position.x, position.y, position.z, 1) + return matrix_float4x4(columns:(X, Y, Z, W)) +} + +func scalingMatrix(scale: Float) -> matrix_float4x4 { + let X = vector_float4(scale, 0, 0, 0) + let Y = vector_float4(0, scale, 0, 0) + let Z = vector_float4(0, 0, scale, 0) + let W = vector_float4(0, 0, 0, 1) + return matrix_float4x4(columns:(X, Y, Z, W)) +} + +func rotationMatrix(angle: Float, _ axis: vector_float3) -> matrix_float4x4 { + var X = vector_float4(0, 0, 0, 0) + X.x = axis.x * axis.x + (1 - axis.x * axis.x) * cos(angle) + X.y = axis.x * axis.y * (1 - cos(angle)) - axis.z * sin(angle) + X.z = axis.x * axis.z * (1 - cos(angle)) + axis.y * sin(angle) + X.w = 0.0 + var Y = vector_float4(0, 0, 0, 0) + Y.x = axis.x * axis.y * (1 - cos(angle)) + axis.z * sin(angle) + Y.y = axis.y * axis.y + (1 - axis.y * axis.y) * cos(angle) + Y.z = axis.y * axis.z * (1 - cos(angle)) - axis.x * sin(angle) + Y.w = 0.0 + var Z = vector_float4(0, 0, 0, 0) + Z.x = axis.x * axis.z * (1 - cos(angle)) - axis.y * sin(angle) + Z.y = axis.y * axis.z * (1 - cos(angle)) + axis.x * sin(angle) + Z.z = axis.z * axis.z + (1 - axis.z * axis.z) * cos(angle) + Z.w = 0.0 + let W = vector_float4(0, 0, 0, 1) + return matrix_float4x4(columns:(X, Y, Z, W)) +} + +func projectionMatrix(near: Float, far: Float, aspect: Float, fovy: Float) -> matrix_float4x4 { + let scaleY = 1 / tan(fovy * 0.5) + let scaleX = scaleY / aspect + let scaleZ = -(far + near) / (far - near) + let scaleW = -2 * far * near / (far - near) + let X = vector_float4(scaleX, 0, 0, 0) + let Y = vector_float4(0, scaleY, 0, 0) + let Z = vector_float4(0, 0, scaleZ, -1) + let W = vector_float4(0, 0, scaleW, 0) + return matrix_float4x4(columns:(X, Y, Z, W)) +} diff --git a/ch09/chapter09.playground/Sources/MetalView.swift b/ch09/chapter09.playground/Sources/MetalView.swift new file mode 100755 index 0000000..27e9042 --- /dev/null +++ b/ch09/chapter09.playground/Sources/MetalView.swift @@ -0,0 +1,100 @@ + +import MetalKit + +public class MetalView: MTKView { + + var vertex_buffer: MTLBuffer! + var uniform_buffer: MTLBuffer! + var index_buffer: MTLBuffer! + var dss: MTLDepthStencilState! + var rps: MTLRenderPipelineState! + var commandQueue: MTLCommandQueue! + var rotation: Float = 0 + + required public init(coder: NSCoder) { + super.init(coder: coder) + } + + override public init(frame frameRect: CGRect, device: MTLDevice?) { + super.init(frame: frameRect, device: device) + createBuffers() + createPipeline() + } + + func createBuffers() { + let vertex_data = [ + Vertex(pos: [-1.0, -1.0, 1.0, 1.0], col: [1, 1, 1, 1]), + Vertex(pos: [ 1.0, -1.0, 1.0, 1.0], col: [1, 0, 0, 1]), + Vertex(pos: [ 1.0, 1.0, 1.0, 1.0], col: [1, 1, 0, 1]), + Vertex(pos: [-1.0, 1.0, 1.0, 1.0], col: [0, 1, 0, 1]), + Vertex(pos: [-1.0, -1.0, -1.0, 1.0], col: [0, 0, 1, 1]), + Vertex(pos: [ 1.0, -1.0, -1.0, 1.0], col: [1, 0, 1, 1]), + Vertex(pos: [ 1.0, 1.0, -1.0, 1.0], col: [0, 0, 0, 1]), + Vertex(pos: [-1.0, 1.0, -1.0, 1.0], col: [0, 1, 1, 1]) + ] + let index_data: [UInt16] = [ + 0, 1, 2, 2, 3, 0, // front + 1, 5, 6, 6, 2, 1, // right + 3, 2, 6, 6, 7, 3, // top + 4, 5, 1, 1, 0, 4, // bottom + 4, 0, 3, 3, 7, 4, // left + 7, 6, 5, 5, 4, 7, // back + ] + vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * vertex_data.count, options: []) + index_buffer = device!.newBufferWithBytes(index_data, length: sizeof(UInt16) * index_data.count , options: []) + uniform_buffer = device!.newBufferWithLength(sizeof(matrix_float4x4), options: []) + } + + func createPipeline() { + do { + let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) + let library = try device!.newLibraryWithSource(input, options: nil) + let vert_func = library.newFunctionWithName("vertex_func")! + let frag_func = library.newFunctionWithName("fragment_func")! + let rpld = MTLRenderPipelineDescriptor() + rpld.vertexFunction = vert_func + rpld.fragmentFunction = frag_func + rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + rps = try device!.newRenderPipelineStateWithDescriptor(rpld) + } catch let e { + Swift.print("\(e)") + } + commandQueue = device?.newCommandQueue() + } + + func update() { + let scaled = scalingMatrix(0.5) + rotation += 1 / 100 * Float(M_PI) / 4 + let rotatedY = rotationMatrix(rotation, float3(0, 1, 0)) + let rotatedX = rotationMatrix(Float(M_PI) / 4, float3(1, 0, 0)) + let modelMatrix = matrix_multiply(matrix_multiply(rotatedX, rotatedY), scaled) + let cameraPosition = vector_float3(0, 0, -3) + let viewMatrix = translationMatrix(cameraPosition) + let aspect = Float(drawableSize.width / drawableSize.height) + let projMatrix = projectionMatrix(0, far: 10, aspect: aspect, fovy: 1) + let modelViewProjectionMatrix = matrix_multiply(projMatrix, matrix_multiply(viewMatrix, modelMatrix)) + let bufferPointer = uniform_buffer.contents() + var uniforms = Uniforms(modelViewProjectionMatrix: modelViewProjectionMatrix) + memcpy(bufferPointer, &uniforms, sizeof(Uniforms)) + } + + override public func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + update() + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.3, 0.5, 0.5, 1.0) + let command_buffer = commandQueue.commandBuffer() + let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) + command_encoder.setRenderPipelineState(rps) + command_encoder.setFrontFacingWinding(.CounterClockwise) + command_encoder.setCullMode(.Back) + command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) + command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) + command_encoder.drawIndexedPrimitives(.Triangle, indexCount: index_buffer.length / sizeof(UInt16), indexType: MTLIndexType.UInt16, indexBuffer: index_buffer, indexBufferOffset: 0) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } +} diff --git a/ch09/chapter09.playground/contents.xcplayground b/ch09/chapter09.playground/contents.xcplayground new file mode 100644 index 0000000..06828af --- /dev/null +++ b/ch09/chapter09.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch09/chapter09.playground/playground.xcworkspace/contents.xcworkspacedata b/ch09/chapter09.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/ch09/chapter09.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch09/chapter09.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch09/chapter09.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000000000000000000000000000000000000..6294b51a5384da980209f0281e9d4a149eb835ae GIT binary patch literal 24161 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 + + + + diff --git a/ch10/chapter10.playground/Contents.swift b/ch10/chapter10.playground/Contents.swift new file mode 100755 index 0000000..96ca6ff --- /dev/null +++ b/ch10/chapter10.playground/Contents.swift @@ -0,0 +1,8 @@ + +import Cocoa +import XCPlayground + +let device = MTLCreateSystemDefaultDevice()! +let frame = NSRect(x: 0, y: 0, width: 300, height: 300) +let view = MetalView(frame: frame, device: device) +XCPlaygroundPage.currentPage.liveView = view diff --git a/ch10/chapter10.playground/Resources/Shaders.metal b/ch10/chapter10.playground/Resources/Shaders.metal new file mode 100755 index 0000000..66302ca --- /dev/null +++ b/ch10/chapter10.playground/Resources/Shaders.metal @@ -0,0 +1,23 @@ + +#include +using namespace metal; + +float dist(float2 point, float2 center, float radius) +{ + return length(point - center) - radius; +} + +kernel void compute(texture2d output [[texture(0)]], + uint2 gid [[thread_position_in_grid]]) +{ + int width = output.get_width(); + int height = output.get_height(); + float red = float(gid.x) / float(width); + float green = float(gid.y) / float(height); + float2 uv = float2(gid) / float2(width, height); + uv = uv * 2.0 - 1.0; + float distToCircle = dist(uv, float2(0), 0.5); + float distToCircle2 = dist(uv, float2(-0.1, 0.1), 0.5); + bool inside = distToCircle2 < 0; + output.write(inside ? float4(0) : float4(1, 0.7, 0, 1) * (1 - distToCircle), gid); +} \ No newline at end of file diff --git a/ch10/chapter10.playground/Sources/MetalView.swift b/ch10/chapter10.playground/Sources/MetalView.swift new file mode 100755 index 0000000..6cbc65c --- /dev/null +++ b/ch10/chapter10.playground/Sources/MetalView.swift @@ -0,0 +1,46 @@ + +import MetalKit + +public class MetalView: MTKView { + + var queue: MTLCommandQueue! = nil + var cps: MTLComputePipelineState! = nil + + required public init(coder: NSCoder) { + super.init(coder: coder) + } + + override public init(frame frameRect: CGRect, device: MTLDevice?) { + super.init(frame: frameRect, device: device) + registerShaders() + } + + override public func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + if let drawable = currentDrawable { + let command_buffer = queue.commandBuffer() + let command_encoder = command_buffer.computeCommandEncoder() + command_encoder.setComputePipelineState(cps) + command_encoder.setTexture(drawable.texture, atIndex: 0) + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } + + func registerShaders() { + queue = device!.newCommandQueue() + let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + do { + let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) + let library = try device!.newLibraryWithSource(input, options: nil) + let kernel = library.newFunctionWithName("compute")! + cps = try device!.newComputePipelineStateWithFunction(kernel) + } catch let e { + Swift.print("\(e)") + } + } +} diff --git a/ch10/chapter10.playground/contents.xcplayground b/ch10/chapter10.playground/contents.xcplayground new file mode 100755 index 0000000..06828af --- /dev/null +++ b/ch10/chapter10.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch10/chapter10.playground/playground.xcworkspace/contents.xcworkspacedata b/ch10/chapter10.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/ch10/chapter10.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch10/chapter10.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch10/chapter10.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000000000000000000000000000000000000..b0371a6e8797b8d4ce9f83f00151cbe0082ec193 GIT binary patch literal 16567 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 P3Vt$+f}f$^nbZFtQ2z&= literal 0 HcmV?d00001 diff --git a/ch10/chapter10.playground/timeline.xctimeline b/ch10/chapter10.playground/timeline.xctimeline new file mode 100755 index 0000000..bf468af --- /dev/null +++ b/ch10/chapter10.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/ch11/chapter11.playground/Contents.swift b/ch11/chapter11.playground/Contents.swift new file mode 100644 index 0000000..00f436f --- /dev/null +++ b/ch11/chapter11.playground/Contents.swift @@ -0,0 +1,8 @@ + +import Cocoa +import XCPlayground + +let device = MTLCreateSystemDefaultDevice()! +let frame = NSRect(x:0, y:0, width:300, height:300) +let view = MetalView(frame: frame, device: device) +XCPlaygroundPage.currentPage.liveView = view diff --git a/ch11/chapter11.playground/Resources/Shaders.metal b/ch11/chapter11.playground/Resources/Shaders.metal new file mode 100755 index 0000000..bfafc95 --- /dev/null +++ b/ch11/chapter11.playground/Resources/Shaders.metal @@ -0,0 +1,58 @@ + +#include + +using namespace metal; + +float distToCircle(float2 point, float2 center, float radius) +{ + return length(point - center) - radius; +} + +float smootherstep(float e1, float e2, float x) +{ + x = clamp((x - e1) / (e2 - e1), 0.0, 1.0); + return x * x * x * (x * (x * 6 - 15) + 10); +} + +kernel void compute(texture2d output [[texture(0)]], + uint2 gid [[thread_position_in_grid]]) +{ + int width = output.get_width(); + int height = output.get_height(); + float2 uv = float2(gid) / float2(width, height); + +// //uncomment this code block for the 1st part of the tutorial and comment out the others +// uv = uv * 2.0 - 1.0; +// float distance = distToCircle(uv, float2(0), 0.5); +// float xMax = width/height; +// float4 sun = float4(1, 0.7, 0, 1) * (1 - distance); +// float4 planet = float4(0); +// float radius = 0.5; +// float m = smootherstep(radius - 0.005, radius + 0.005, length(uv - float2(xMax-1, 0))); +// float4 pixel = mix(planet, sun, m); +// output.write(pixel, gid); + +// // uncomment this code block for the 2nd part of the tutorial and comment out the others +// float3 color = float3(0.7); +// if(fmod(uv.x, 0.1) < 0.005 || fmod(uv.y, 0.1) < 0.005) color = float3(0,0,1); +// float2 uv_ext = uv * 2.0 - 1.0; +// if(abs(uv_ext.x) < 0.02 || abs(uv_ext.y) < 0.02) color = float3(1, 0, 0); +// if(abs(uv_ext.x - uv_ext.y) < 0.02 || abs(uv_ext.x + uv_ext.y) < 0.02) color = float3(0, 1, 0); +// output.write(float4(color, 1), gid); + + // uncomment this code block for the 3rd part of the tutorial and comment out the others + float2 cc = 1.1*float2( 0.5*cos(0.1) - 0.25*cos(0.2), 0.5*sin(0.1) - 0.25*sin(0.2) ); + float4 dmin = float4(1000.0); + float2 z = (-1.0 + 2.0*uv)*float2(1.7,1.0); + for( int i=0; i<64; i++ ) { + z = cc + float2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ); + dmin=min(dmin, float4(abs(0.0+z.y + 0.5*sin(z.x)), abs(1.0+z.x + 0.5*sin(z.y)), dot(z,z), length( fract(z)-0.5) ) ); + } + float3 color = float3( dmin.w ); + color = mix( color, float3(1.00,0.80,0.60), min(1.0,pow(dmin.x*0.25,0.20)) ); + color = mix( color, float3(0.72,0.70,0.60), min(1.0,pow(dmin.y*0.50,0.50)) ); + color = mix( color, float3(1.00,1.00,1.00), 1.0-min(1.0,pow(dmin.z*1.00,0.15) )); + color = 1.25*color*color; + color *= 0.5 + 0.5*pow(16.0*uv.x*(1.0-uv.x)*uv.y*(1.0-uv.y),0.15); + output.write(float4(color, 1), gid); +} diff --git a/ch11/chapter11.playground/Sources/MetalView.swift b/ch11/chapter11.playground/Sources/MetalView.swift new file mode 100755 index 0000000..425569a --- /dev/null +++ b/ch11/chapter11.playground/Sources/MetalView.swift @@ -0,0 +1,56 @@ + +import MetalKit + +public class MetalView: MTKView { + + var queue: MTLCommandQueue! = nil + var cps: MTLComputePipelineState! = nil + + var shader = + "#include \n" + + "using namespace metal;" + + "kernel void compute(texture2d output [[texture(0)]]," + + " uint2 gid [[thread_position_in_grid]])" + + "{" + + " output.write(float4(1, 1, 0, 1), gid);" + + "}" + + required public init(coder: NSCoder) { + super.init(coder: coder) + } + + override public init(frame frameRect: CGRect, device: MTLDevice?) { + super.init(frame: frameRect, device: device) + registerShaders() + } + + override public func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + if let drawable = currentDrawable { + let command_buffer = queue.commandBuffer() + let command_encoder = command_buffer.computeCommandEncoder() + command_encoder.setComputePipelineState(cps) + command_encoder.setTexture(drawable.texture, atIndex: 0) + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + command_encoder.endEncoding() + command_buffer.presentDrawable(drawable) + command_buffer.commit() + } + } + + func registerShaders() { + queue = device!.newCommandQueue() + let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + do { + let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) + let library = try device!.newLibraryWithSource(input, options: nil) +// let library = try device!.newLibraryWithSource(shader, options: nil) + let kernel = library.newFunctionWithName("compute")! + cps = try device!.newComputePipelineStateWithFunction(kernel) + } catch let e { + Swift.print("\(e)") + } + } +} diff --git a/ch11/chapter11.playground/contents.xcplayground b/ch11/chapter11.playground/contents.xcplayground new file mode 100644 index 0000000..06828af --- /dev/null +++ b/ch11/chapter11.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch11/chapter11.playground/playground.xcworkspace/contents.xcworkspacedata b/ch11/chapter11.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/ch11/chapter11.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch11/chapter11.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch11/chapter11.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000000000000000000000000000000000000..f4c9511657e57e18cf265a284e8735a79b65f256 GIT binary patch literal 18466 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 w?X>N-9kLy@eP%mpJ7YU*`^I*`cC}|j�bae?0&Qg8NJV!2J#U?iv6809+NU3IG5A literal 0 HcmV?d00001 diff --git a/ch11/chapter11.playground/timeline.xctimeline b/ch11/chapter11.playground/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/ch11/chapter11.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/ch12/chapter12.playground/Contents.swift b/ch12/chapter12.playground/Contents.swift new file mode 100644 index 0000000..9faf781 --- /dev/null +++ b/ch12/chapter12.playground/Contents.swift @@ -0,0 +1,8 @@ + +import Cocoa +import XCPlayground + +let device = MTLCreateSystemDefaultDevice()! +let frame = NSRect(x:0, y:0, width:300, height:300) +let metalView = MetalView(frame: frame, device: device) +XCPlaygroundPage.currentPage.liveView = metalView diff --git a/ch12/chapter12.playground/Resources/Shaders.metal b/ch12/chapter12.playground/Resources/Shaders.metal new file mode 100755 index 0000000..556aea3 --- /dev/null +++ b/ch12/chapter12.playground/Resources/Shaders.metal @@ -0,0 +1,28 @@ + +#include + +using namespace metal; + +kernel void compute(texture2d output [[texture(0)]], + constant float &timer [[buffer(1)]], + constant float2 &mouse [[buffer(2)]], + uint2 gid [[thread_position_in_grid]]) +{ + int width = output.get_width(); + int height = output.get_height(); + float2 uv = float2(gid) / float2(width, height); + float2 cc = 1.1*float2( 0.5*cos(0.1*timer) - 0.25*cos(0.2*timer), 0.5*sin(0.1*timer) - 0.25*sin(0.2*timer) ); + float4 dmin = float4(1000.0); + float2 z = (-1.0 + 2.0*uv)*float2(1.7,1.0); + for( int i=0; i<64; i++ ) { + z = cc + float2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ); + dmin=min(dmin, float4(abs(0.0+z.y + 0.5*sin(z.x)), abs(1.0+z.x + 0.5*sin(z.y)), dot(z,z), length( fract(z)-0.5) ) ); + } + float3 color = float3(mouse.x - mouse.y); + color = mix( color, float3(1.00,0.80,0.60), min(1.0,pow(dmin.x*0.25,0.20)) ); + color = mix( color, float3(0.72,0.70,0.60), min(1.0,pow(dmin.y*0.50,0.50)) ); + color = mix( color, float3(1.00,1.00,1.00), 1.0-min(1.0,pow(dmin.z*1.00,0.15) )); + color = 1.25*color*color; + color *= 0.5 + 0.5*pow(16.0*uv.x*(1.0-uv.x)*uv.y*(1.0-uv.y),0.15); + output.write(float4(color, 1), gid); +} diff --git a/ch12/chapter12.playground/Sources/MetalView.swift b/ch12/chapter12.playground/Sources/MetalView.swift new file mode 100755 index 0000000..37c8100 --- /dev/null +++ b/ch12/chapter12.playground/Sources/MetalView.swift @@ -0,0 +1,71 @@ + +import MetalKit + +public class MetalView: MTKView, NSWindowDelegate { + + var queue: MTLCommandQueue! = nil + var cps: MTLComputePipelineState! = nil + var timer: Float = 0 + var timerBuffer: MTLBuffer! + var mouseBuffer: MTLBuffer! + var pos: NSPoint! + + override public func mouseDown(event: NSEvent) { + pos = convertPointToLayer(convertPoint(event.locationInWindow, fromView: nil)) + let scale = layer!.contentsScale + pos.x *= scale + pos.y *= scale + } + + required public init(coder: NSCoder) { + super.init(coder: coder) + } + + override public init(frame frameRect: CGRect, device: MTLDevice?) { + super.init(frame: frameRect, device: device) + registerShaders() + } + + override public func drawRect(dirtyRect: NSRect) { + super.drawRect(dirtyRect) + if let drawable = currentDrawable { + let commandBuffer = queue.commandBuffer() + let commandEncoder = commandBuffer.computeCommandEncoder() + commandEncoder.setComputePipelineState(cps) + commandEncoder.setTexture(drawable.texture, atIndex: 0) + commandEncoder.setBuffer(mouseBuffer, offset: 0, atIndex: 2) + commandEncoder.setBuffer(timerBuffer, offset: 0, atIndex: 1) + update() + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + commandEncoder.endEncoding() + commandBuffer.presentDrawable(drawable) + commandBuffer.commit() + } + + } + + func update() { + timer += 0.01 + var bufferPointer = timerBuffer.contents() + memcpy(bufferPointer, &timer, sizeof(Float)) + bufferPointer = mouseBuffer.contents() + memcpy(bufferPointer, &pos, sizeof(NSPoint)) + } + + func registerShaders() { + queue = device!.newCommandQueue() + let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + do { + let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) + let library = try device!.newLibraryWithSource(input, options: nil) + let kernel = library.newFunctionWithName("compute")! + cps = try device!.newComputePipelineStateWithFunction(kernel) + } catch let e { + Swift.print("\(e)") + } + timerBuffer = device!.newBufferWithLength(sizeof(Float), options: []) + mouseBuffer = device!.newBufferWithLength(sizeof(NSPoint), options: []) + } +} diff --git a/ch12/chapter12.playground/contents.xcplayground b/ch12/chapter12.playground/contents.xcplayground new file mode 100644 index 0000000..06828af --- /dev/null +++ b/ch12/chapter12.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch12/chapter12.playground/playground.xcworkspace/contents.xcworkspacedata b/ch12/chapter12.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/ch12/chapter12.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch12/chapter12.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch12/chapter12.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100755 index 0000000000000000000000000000000000000000..746466e82019d519fd70aecdb7dddfa1aea64aae GIT binary patch literal 19598 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 literal 0 HcmV?d00001 diff --git a/ch12/chapter12.playground/timeline.xctimeline b/ch12/chapter12.playground/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/ch12/chapter12.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + +