diff --git a/objc/02-ClearScreen/ClearScreen.xcodeproj/project.pbxproj b/objc/02-ClearScreen/ClearScreen.xcodeproj/project.pbxproj
index 97237cc..12a907f 100644
--- a/objc/02-ClearScreen/ClearScreen.xcodeproj/project.pbxproj
+++ b/objc/02-ClearScreen/ClearScreen.xcodeproj/project.pbxproj
@@ -110,7 +110,7 @@
833FBB9B1BBE0B0E001EFE4D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0900;
+ LastUpgradeCheck = 0940;
ORGANIZATIONNAME = "Metal by Example";
TargetAttributes = {
833FBBA21BBE0B0E001EFE4D = {
@@ -195,12 +195,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -247,12 +249,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
diff --git a/objc/02-ClearScreen/ClearScreen.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objc/02-ClearScreen/ClearScreen.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/objc/02-ClearScreen/ClearScreen.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/objc/02-ClearScreen/ClearScreen.xcodeproj/xcshareddata/xcschemes/ClearScreen.xcscheme b/objc/02-ClearScreen/ClearScreen.xcodeproj/xcshareddata/xcschemes/ClearScreen.xcscheme
index 03bae38..2ed7c45 100644
--- a/objc/02-ClearScreen/ClearScreen.xcodeproj/xcshareddata/xcschemes/ClearScreen.xcscheme
+++ b/objc/02-ClearScreen/ClearScreen.xcodeproj/xcshareddata/xcschemes/ClearScreen.xcscheme
@@ -1,6 +1,6 @@
@@ -46,7 +45,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.pbxproj b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.pbxproj
index d393a58..8f06fcb 100644
--- a/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.pbxproj
+++ b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.pbxproj
@@ -113,7 +113,7 @@
83E2D75C1BD188110006DDD8 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0900;
+ LastUpgradeCheck = 0940;
ORGANIZATIONNAME = "Metal by Example";
TargetAttributes = {
83E2D7631BD188110006DDD8 = {
@@ -199,12 +199,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -251,12 +253,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -289,7 +293,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- INFOPLIST_FILE = "DrawingIn2D/Info.plist";
+ INFOPLIST_FILE = DrawingIn2D/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.metalbyexample.-2-DrawingIn2D";
@@ -301,7 +305,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- INFOPLIST_FILE = "DrawingIn2D/Info.plist";
+ INFOPLIST_FILE = DrawingIn2D/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.metalbyexample.-2-DrawingIn2D";
diff --git a/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/xcshareddata/xcschemes/DrawingIn2D.xcscheme b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/xcshareddata/xcschemes/DrawingIn2D.xcscheme
index fc08a89..d38cb48 100644
--- a/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/xcshareddata/xcschemes/DrawingIn2D.xcscheme
+++ b/objc/03-DrawingIn2D/DrawingIn2D.xcodeproj/xcshareddata/xcschemes/DrawingIn2D.xcscheme
@@ -1,6 +1,6 @@
@@ -46,7 +45,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.h b/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.h
new file mode 100644
index 0000000..c6cc122
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.h
@@ -0,0 +1,15 @@
+//
+// AppDelegate.h
+// DrawingIn3D-Mac
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import
+
+@interface AppDelegate : NSObject
+
+
+@end
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.m b/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.m
new file mode 100644
index 0000000..694bd25
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/AppDelegate.m
@@ -0,0 +1,27 @@
+//
+// AppDelegate.m
+// DrawingIn3D-Mac
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+ // Insert code here to initialize your application
+}
+
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+ // Insert code here to tear down your application
+}
+
+
+@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2db2b1c
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/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/objc/04-DrawingIn3D/DrawingIn3D-Mac/Assets.xcassets/Contents.json b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/Base.lproj/Main.storyboard b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..13538fe
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Base.lproj/Main.storyboard
@@ -0,0 +1,718 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/DrawingIn3D_Mac.entitlements b/objc/04-DrawingIn3D/DrawingIn3D-Mac/DrawingIn3D_Mac.entitlements
new file mode 100644
index 0000000..f2ef3ae
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/DrawingIn3D_Mac.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.files.user-selected.read-only
+
+
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/Info.plist b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Info.plist
new file mode 100644
index 0000000..7dd54bb
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ Copyright © 2018 Metal by Example. All rights reserved.
+ NSMainStoryboardFile
+ Main
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.h b/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.h
new file mode 100644
index 0000000..f291345
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.h
@@ -0,0 +1,15 @@
+//
+// MBEMetalViewMac.h
+// DrawingIn3D-Mac
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+@import Cocoa;
+
+#import "MBEMetalView.h"
+
+@interface MBEMetalViewMac : MBEMetalView
+
+@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.m b/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.m
new file mode 100644
index 0000000..66bacd8
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/MBEMetalViewMac.m
@@ -0,0 +1,72 @@
+//
+// MBEMetalViewMac.m
+// DrawingIn3D-Mac
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import "MBEMetalViewMac.h"
+
+@interface MBEMetalViewMac()
+@property (nonatomic) CVDisplayLinkRef displayLink;
+@property (nonatomic, strong) CAMetalLayer *metalLayer;
+@end
+
+static NSTimeInterval C3DTimeIntervalFromTimeStamp(const CVTimeStamp *timeStamp) {
+ return 1.0 / (timeStamp->rateScalar * (double)timeStamp->videoTimeScale / (double)timeStamp->videoRefreshPeriod);
+}
+
+static CVReturn C3DViewDisplayLink(CVDisplayLinkRef displayLink,
+ const CVTimeStamp *inNow,
+ const CVTimeStamp *inOutputTime,
+ CVOptionFlags flagsIn,
+ CVOptionFlags *flagsOut,
+ void *view) {
+ @autoreleasepool {
+ [(__bridge MBEMetalView *)view renderWithDuration:C3DTimeIntervalFromTimeStamp(inOutputTime)];
+ }
+
+ return kCVReturnSuccess;
+}
+
+@implementation MBEMetalViewMac
+
+@synthesize metalLayer=_metalLayer;
+
+- (CALayer *)makeBackingLayer
+{
+ CAMetalLayer *layer = [[CAMetalLayer alloc] init];
+ _metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ _metalLayer = layer;
+ return layer;
+}
+
+- (CGSize)drawableSize {
+ return self.bounds.size;
+}
+
+- (void)viewDidMoveToSuperview
+{
+ [super viewDidMoveToSuperview];
+
+ if (self.metalLayer.device == nil) {
+ self.metalLayer.device = MTLCreateSystemDefaultDevice();
+ }
+ if (self.depthTexture == nil) {
+ [self makeDepthTexture];
+ }
+
+ if (self.superview) {
+ CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ CVDisplayLinkSetOutputCallback(_displayLink, C3DViewDisplayLink, (__bridge void *)(self));
+ CVDisplayLinkStart(_displayLink);
+ }
+ else {
+ CVDisplayLinkStop(_displayLink);
+ CVDisplayLinkRelease(_displayLink);
+ _displayLink = NULL;
+ }
+}
+
+@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D-Mac/main.m b/objc/04-DrawingIn3D/DrawingIn3D-Mac/main.m
new file mode 100644
index 0000000..0957be7
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D-Mac/main.m
@@ -0,0 +1,13 @@
+//
+// main.m
+// DrawingIn3D-Mac
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import
+
+int main(int argc, const char * argv[]) {
+ return NSApplicationMain(argc, argv);
+}
diff --git a/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.pbxproj b/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.pbxproj
index 6c4628b..930d5e0 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.pbxproj
+++ b/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.pbxproj
@@ -17,6 +17,17 @@
83E2D7B51BD598810006DDD8 /* MBERenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7AC1BD598810006DDD8 /* MBERenderer.m */; };
83E2D7B61BD598810006DDD8 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7AD1BD598810006DDD8 /* Shaders.metal */; };
83E2D7B81BD598810006DDD8 /* MBEMathUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7B11BD598810006DDD8 /* MBEMathUtilities.m */; };
+ 845182E520D8214900BF473E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 845182E420D8214900BF473E /* AppDelegate.m */; };
+ 845182EA20D8214A00BF473E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 845182E920D8214A00BF473E /* Assets.xcassets */; };
+ 845182ED20D8214A00BF473E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 845182EB20D8214A00BF473E /* Main.storyboard */; };
+ 845182F020D8214A00BF473E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 845182EF20D8214A00BF473E /* main.m */; };
+ 845182F720D821B300BF473E /* MBEMetalViewMac.m in Sources */ = {isa = PBXBuildFile; fileRef = 845182F620D821B300BF473E /* MBEMetalViewMac.m */; };
+ 845182F820D821DD00BF473E /* MBEMetalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7A71BD598810006DDD8 /* MBEMetalView.m */; };
+ 845182FB20D8222100BF473E /* MBEMetalViewIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 845182FA20D8222100BF473E /* MBEMetalViewIOS.m */; };
+ 8451830020D8278F00BF473E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7961BD597A30006DDD8 /* ViewController.m */; };
+ 8451830120D827C800BF473E /* MBEMathUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7B11BD598810006DDD8 /* MBEMathUtilities.m */; };
+ 8451830220D827C800BF473E /* MBERenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7AC1BD598810006DDD8 /* MBERenderer.m */; };
+ 8451830320D827DC00BF473E /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 83E2D7AD1BD598810006DDD8 /* Shaders.metal */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -37,6 +48,18 @@
83E2D7AD1BD598810006DDD8 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; };
83E2D7B01BD598810006DDD8 /* MBEMathUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBEMathUtilities.h; sourceTree = ""; };
83E2D7B11BD598810006DDD8 /* MBEMathUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBEMathUtilities.m; sourceTree = ""; };
+ 845182E120D8214900BF473E /* Drawing in 3D.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Drawing in 3D.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 845182E320D8214900BF473E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 845182E420D8214900BF473E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 845182E920D8214A00BF473E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 845182EC20D8214A00BF473E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 845182EE20D8214A00BF473E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 845182EF20D8214A00BF473E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 845182F120D8214A00BF473E /* DrawingIn3D_Mac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DrawingIn3D_Mac.entitlements; sourceTree = ""; };
+ 845182F520D821B300BF473E /* MBEMetalViewMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBEMetalViewMac.h; sourceTree = ""; };
+ 845182F620D821B300BF473E /* MBEMetalViewMac.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBEMetalViewMac.m; sourceTree = ""; };
+ 845182F920D8222100BF473E /* MBEMetalViewIOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBEMetalViewIOS.h; sourceTree = ""; };
+ 845182FA20D8222100BF473E /* MBEMetalViewIOS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBEMetalViewIOS.m; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -47,6 +70,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 845182DE20D8214900BF473E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -54,6 +84,7 @@
isa = PBXGroup;
children = (
83E2D78E1BD597A30006DDD8 /* DrawingIn3D */,
+ 845182E220D8214900BF473E /* DrawingIn3D-Mac */,
83E2D78D1BD597A30006DDD8 /* Products */,
);
sourceTree = "";
@@ -62,6 +93,7 @@
isa = PBXGroup;
children = (
83E2D78C1BD597A30006DDD8 /* DrawingIn3D.app */,
+ 845182E120D8214900BF473E /* Drawing in 3D.app */,
);
name = Products;
sourceTree = "";
@@ -71,20 +103,22 @@
children = (
83E2D7921BD597A30006DDD8 /* AppDelegate.h */,
83E2D7931BD597A30006DDD8 /* AppDelegate.m */,
- 83E2D7951BD597A30006DDD8 /* ViewController.h */,
- 83E2D7961BD597A30006DDD8 /* ViewController.m */,
+ 83E2D79B1BD597A30006DDD8 /* Assets.xcassets */,
+ 83E2D7A01BD597A30006DDD8 /* Info.plist */,
+ 83E2D79D1BD597A30006DDD8 /* LaunchScreen.storyboard */,
+ 83E2D7981BD597A30006DDD8 /* Main.storyboard */,
83E2D7B01BD598810006DDD8 /* MBEMathUtilities.h */,
83E2D7B11BD598810006DDD8 /* MBEMathUtilities.m */,
83E2D7A61BD598810006DDD8 /* MBEMetalView.h */,
83E2D7A71BD598810006DDD8 /* MBEMetalView.m */,
+ 845182F920D8222100BF473E /* MBEMetalViewIOS.h */,
+ 845182FA20D8222100BF473E /* MBEMetalViewIOS.m */,
83E2D7AB1BD598810006DDD8 /* MBERenderer.h */,
83E2D7AC1BD598810006DDD8 /* MBERenderer.m */,
83E2D7AD1BD598810006DDD8 /* Shaders.metal */,
- 83E2D7981BD597A30006DDD8 /* Main.storyboard */,
- 83E2D79B1BD597A30006DDD8 /* Assets.xcassets */,
- 83E2D79D1BD597A30006DDD8 /* LaunchScreen.storyboard */,
- 83E2D7A01BD597A30006DDD8 /* Info.plist */,
83E2D78F1BD597A30006DDD8 /* Supporting Files */,
+ 83E2D7951BD597A30006DDD8 /* ViewController.h */,
+ 83E2D7961BD597A30006DDD8 /* ViewController.m */,
);
path = DrawingIn3D;
sourceTree = "";
@@ -97,6 +131,22 @@
name = "Supporting Files";
sourceTree = "";
};
+ 845182E220D8214900BF473E /* DrawingIn3D-Mac */ = {
+ isa = PBXGroup;
+ children = (
+ 845182E320D8214900BF473E /* AppDelegate.h */,
+ 845182E420D8214900BF473E /* AppDelegate.m */,
+ 845182E920D8214A00BF473E /* Assets.xcassets */,
+ 845182F120D8214A00BF473E /* DrawingIn3D_Mac.entitlements */,
+ 845182EE20D8214A00BF473E /* Info.plist */,
+ 845182EF20D8214A00BF473E /* main.m */,
+ 845182EB20D8214A00BF473E /* Main.storyboard */,
+ 845182F520D821B300BF473E /* MBEMetalViewMac.h */,
+ 845182F620D821B300BF473E /* MBEMetalViewMac.m */,
+ );
+ path = "DrawingIn3D-Mac";
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -117,18 +167,39 @@
productReference = 83E2D78C1BD597A30006DDD8 /* DrawingIn3D.app */;
productType = "com.apple.product-type.application";
};
+ 845182E020D8214900BF473E /* DrawingIn3D-Mac */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 845182F220D8214A00BF473E /* Build configuration list for PBXNativeTarget "DrawingIn3D-Mac" */;
+ buildPhases = (
+ 845182DD20D8214900BF473E /* Sources */,
+ 845182DE20D8214900BF473E /* Frameworks */,
+ 845182DF20D8214900BF473E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "DrawingIn3D-Mac";
+ productName = "DrawingIn3D-Mac";
+ productReference = 845182E120D8214900BF473E /* Drawing in 3D.app */;
+ productType = "com.apple.product-type.application";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83E2D7841BD597A30006DDD8 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0900;
+ LastUpgradeCheck = 0940;
ORGANIZATIONNAME = "Metal by Example";
TargetAttributes = {
83E2D78B1BD597A30006DDD8 = {
CreatedOnToolsVersion = 7.0;
};
+ 845182E020D8214900BF473E = {
+ CreatedOnToolsVersion = 9.4;
+ ProvisioningStyle = Automatic;
+ };
};
};
buildConfigurationList = 83E2D7871BD597A30006DDD8 /* Build configuration list for PBXProject "DrawingIn3D" */;
@@ -145,6 +216,7 @@
projectRoot = "";
targets = (
83E2D78B1BD597A30006DDD8 /* DrawingIn3D */,
+ 845182E020D8214900BF473E /* DrawingIn3D-Mac */,
);
};
/* End PBXProject section */
@@ -160,6 +232,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 845182DF20D8214900BF473E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 845182EA20D8214A00BF473E /* Assets.xcassets in Resources */,
+ 845182ED20D8214A00BF473E /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -168,6 +249,7 @@
buildActionMask = 2147483647;
files = (
83E2D7971BD597A30006DDD8 /* ViewController.m in Sources */,
+ 845182FB20D8222100BF473E /* MBEMetalViewIOS.m in Sources */,
83E2D7B61BD598810006DDD8 /* Shaders.metal in Sources */,
83E2D7941BD597A30006DDD8 /* AppDelegate.m in Sources */,
83E2D7B51BD598810006DDD8 /* MBERenderer.m in Sources */,
@@ -177,6 +259,21 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 845182DD20D8214900BF473E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8451830320D827DC00BF473E /* Shaders.metal in Sources */,
+ 8451830020D8278F00BF473E /* ViewController.m in Sources */,
+ 8451830120D827C800BF473E /* MBEMathUtilities.m in Sources */,
+ 845182F020D8214A00BF473E /* main.m in Sources */,
+ 845182E520D8214900BF473E /* AppDelegate.m in Sources */,
+ 8451830220D827C800BF473E /* MBERenderer.m in Sources */,
+ 845182F820D821DD00BF473E /* MBEMetalView.m in Sources */,
+ 845182F720D821B300BF473E /* MBEMetalViewMac.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
@@ -196,6 +293,14 @@
name = LaunchScreen.storyboard;
sourceTree = "";
};
+ 845182EB20D8214A00BF473E /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 845182EC20D8214A00BF473E /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -211,12 +316,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -263,12 +370,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -321,6 +430,54 @@
};
name = Release;
};
+ 845182F320D8214A00BF473E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_ENTITLEMENTS = "DrawingIn3D-Mac/DrawingIn3D_Mac.entitlements";
+ CODE_SIGN_IDENTITY = "-";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = "DrawingIn3D-Mac/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.Metal-by-Example.DrawingIn3D-Mac";
+ PRODUCT_NAME = "Drawing in 3D";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 845182F420D8214A00BF473E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_ENTITLEMENTS = "DrawingIn3D-Mac/DrawingIn3D_Mac.entitlements";
+ CODE_SIGN_IDENTITY = "-";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ INFOPLIST_FILE = "DrawingIn3D-Mac/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.Metal-by-Example.DrawingIn3D-Mac";
+ PRODUCT_NAME = "Drawing in 3D";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -342,6 +499,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 845182F220D8214A00BF473E /* Build configuration list for PBXNativeTarget "DrawingIn3D-Mac" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 845182F320D8214A00BF473E /* Debug */,
+ 845182F420D8214A00BF473E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 83E2D7841BD597A30006DDD8 /* Project object */;
diff --git a/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/Base.lproj/Main.storyboard b/objc/04-DrawingIn3D/DrawingIn3D/Base.lproj/Main.storyboard
index 53b3c66..9033fb1 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D/Base.lproj/Main.storyboard
+++ b/objc/04-DrawingIn3D/DrawingIn3D/Base.lproj/Main.storyboard
@@ -1,7 +1,12 @@
-
-
+
+
+
+
+
-
+
+
+
@@ -12,11 +17,10 @@
-
-
+
+
-
-
+
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.h b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.h
index 3d4d533..c6c30f4 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.h
+++ b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.h
@@ -1,10 +1,18 @@
+#import
+
+#if TARGET_OS_IPHONE
@import UIKit;
+#define NSUIView UIView;
+#else
+@import AppKit;
+#define NSUIView NSView;
+#endif
@import Metal;
@import QuartzCore.CAMetalLayer;
@protocol MBEMetalViewDelegate;
-@interface MBEMetalView : UIView
+@interface MBEMetalView : NSUIView
/// The delegate of this view, responsible for drawing
@property (nonatomic, weak) id delegate;
@@ -36,6 +44,19 @@
/// size as its depth attachment's texture
@property (nonatomic, readonly) MTLRenderPassDescriptor *currentRenderPassDescriptor;
+// Subclass override points
+@property (nonatomic, readonly) CGSize drawableSize;
+
+- (void)makeDepthTexture;
+- (void)renderWithDuration:(NSTimeInterval)duration;
+
+@end
+
+// For subclasses
+@interface MBEMetalView ()
+@property (assign) NSTimeInterval frameDuration;
+@property (strong) id currentDrawable;
+@property (strong) id depthTexture;
@end
@protocol MBEMetalViewDelegate
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.m b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.m
index 9726fb2..a300e97 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.m
+++ b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalView.m
@@ -1,14 +1,10 @@
#import "MBEMetalView.h"
-@interface MBEMetalView ()
-@property (strong) id currentDrawable;
-@property (assign) NSTimeInterval frameDuration;
-@property (strong) id depthTexture;
-@property (strong) CADisplayLink *displayLink;
-@end
-
@implementation MBEMetalView
+@dynamic metalLayer;
+@dynamic drawableSize;
+
+ (Class)layerClass
{
return [CAMetalLayer class];
@@ -52,24 +48,7 @@ - (void)commonInit
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
-
- // During the first layout pass, we will not be in a view hierarchy, so we guess our scale
- CGFloat scale = [UIScreen mainScreen].scale;
-
- // If we've moved to a window by the time our frame is being set, we can take its scale as our own
- if (self.window)
- {
- scale = self.window.screen.scale;
- }
-
- CGSize drawableSize = self.bounds.size;
-
- // Since drawable size is in pixels, we need to multiply by the scale to move from points to pixels
- drawableSize.width *= scale;
- drawableSize.height *= scale;
-
- self.metalLayer.drawableSize = drawableSize;
-
+ self.metalLayer.drawableSize = self.drawableSize;
[self makeDepthTexture];
}
@@ -83,37 +62,6 @@ - (MTLPixelFormat)colorPixelFormat
return self.metalLayer.pixelFormat;
}
-- (void)didMoveToWindow
-{
- const NSTimeInterval idealFrameDuration = (1.0 / 60);
- const NSTimeInterval targetFrameDuration = (1.0 / self.preferredFramesPerSecond);
- const NSInteger frameInterval = round(targetFrameDuration / idealFrameDuration);
-
- if (self.window)
- {
- [self.displayLink invalidate];
- self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)];
- self.displayLink.frameInterval = frameInterval;
- [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
- }
- else
- {
- [self.displayLink invalidate];
- self.displayLink = nil;
- }
-}
-
-- (void)displayLinkDidFire:(CADisplayLink *)displayLink
-{
- self.currentDrawable = [self.metalLayer nextDrawable];
- self.frameDuration = displayLink.duration;
-
- if ([self.delegate respondsToSelector:@selector(drawInView:)])
- {
- [self.delegate drawInView:self];
- }
-}
-
- (void)makeDepthTexture
{
CGSize drawableSize = self.metalLayer.drawableSize;
@@ -126,6 +74,7 @@ - (void)makeDepthTexture
height:drawableSize.height
mipmapped:NO];
desc.usage = MTLTextureUsageRenderTarget;
+ desc.storageMode = MTLStorageModePrivate;
self.depthTexture = [self.metalLayer.device newTextureWithDescriptor:desc];
}
@@ -148,4 +97,14 @@ - (MTLRenderPassDescriptor *)currentRenderPassDescriptor
return passDescriptor;
}
+- (void)renderWithDuration:(NSTimeInterval)duration {
+ self.currentDrawable = [self.metalLayer nextDrawable];
+ self.frameDuration = duration;
+
+ if ([self.delegate respondsToSelector:@selector(drawInView:)])
+ {
+ [self.delegate drawInView:self];
+ }
+}
+
@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.h b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.h
new file mode 100644
index 0000000..0547944
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.h
@@ -0,0 +1,13 @@
+//
+// MBEMetalViewIOS.h
+// DrawingIn3D
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import "MBEMetalView.h"
+
+@interface MBEMetalViewIOS : MBEMetalView
+
+@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.m b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.m
new file mode 100644
index 0000000..93710eb
--- /dev/null
+++ b/objc/04-DrawingIn3D/DrawingIn3D/MBEMetalViewIOS.m
@@ -0,0 +1,56 @@
+//
+// MBEMetalViewIOS.m
+// DrawingIn3D
+//
+// Created by Brent Gulanowski on 2018-06-18.
+// Copyright © 2018 Metal by Example. All rights reserved.
+//
+
+#import "MBEMetalViewIOS.h"
+
+@interface MBEMetalViewIOS()
+@property (strong) CADisplayLink *displayLink;
+@end
+
+@implementation MBEMetalViewIOS
+
+- (CGSize)drawableSize {
+
+ // During the first layout pass, we will not be in a view hierarchy, so we guess our scale
+ // If we've moved to a window by the time our frame is being set, we can take its scale as our own
+ CGFloat scale = self.window ? self.window.screen.scale : [UIScreen mainScreen].scale;
+ CGSize drawableSize = self.bounds.size;
+
+ // Since drawable size is in pixels, we need to multiply by the scale to move from points to pixels
+ drawableSize.width *= scale;
+ drawableSize.height *= scale;
+
+ return drawableSize;
+}
+
+- (void)didMoveToWindow
+{
+ const NSTimeInterval idealFrameDuration = (1.0 / 60);
+ const NSTimeInterval targetFrameDuration = (1.0 / self.preferredFramesPerSecond);
+ const NSInteger frameInterval = round(targetFrameDuration / idealFrameDuration);
+
+ if (self.window)
+ {
+ [self.displayLink invalidate];
+ self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)];
+ self.displayLink.frameInterval = frameInterval;
+ [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+ }
+ else
+ {
+ [self.displayLink invalidate];
+ self.displayLink = nil;
+ }
+}
+
+- (void)displayLinkDidFire:(CADisplayLink *)displayLink
+{
+ [self renderWithDuration:displayLink.duration];
+}
+
+@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/MBERenderer.m b/objc/04-DrawingIn3D/DrawingIn3D/MBERenderer.m
index da35207..e4ad951 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D/MBERenderer.m
+++ b/objc/04-DrawingIn3D/DrawingIn3D/MBERenderer.m
@@ -112,7 +112,7 @@ - (void)makeBuffers
options:MTLResourceOptionCPUCacheModeDefault];
[_indexBuffer setLabel:@"Indices"];
- _uniformBuffer = [self.device newBufferWithLength:sizeof(MBEUniforms) * MBEInFlightBufferCount
+ _uniformBuffer = [self.device newBufferWithLength:self.uniformSize * MBEInFlightBufferCount
options:MTLResourceOptionCPUCacheModeDefault];
[_uniformBuffer setLabel:@"Uniforms"];
}
@@ -143,7 +143,7 @@ - (void)updateUniformsForView:(MBEMetalView *)view duration:(NSTimeInterval)dura
MBEUniforms uniforms;
uniforms.modelViewProjectionMatrix = matrix_multiply(projectionMatrix, matrix_multiply(viewMatrix, modelMatrix));
- const NSUInteger uniformBufferOffset = sizeof(MBEUniforms) * self.bufferIndex;
+ const NSUInteger uniformBufferOffset = self.uniformSize * self.bufferIndex;
memcpy([self.uniformBuffer contents] + uniformBufferOffset, &uniforms, sizeof(uniforms));
}
@@ -165,10 +165,8 @@ - (void)drawInView:(MBEMetalView *)view
[renderPass setFrontFacingWinding:MTLWindingCounterClockwise];
[renderPass setCullMode:MTLCullModeBack];
- const NSUInteger uniformBufferOffset = sizeof(MBEUniforms) * self.bufferIndex;
-
[renderPass setVertexBuffer:self.vertexBuffer offset:0 atIndex:0];
- [renderPass setVertexBuffer:self.uniformBuffer offset:uniformBufferOffset atIndex:1];
+ [renderPass setVertexBuffer:self.uniformBuffer offset:self.uniformSize * self.bufferIndex atIndex:1];
[renderPass drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:[self.indexBuffer length] / sizeof(MBEIndex)
@@ -188,4 +186,15 @@ - (void)drawInView:(MBEMetalView *)view
[commandBuffer commit];
}
+- (NSUInteger)uniformSize
+{
+ NSUInteger size = sizeof(MBEUniforms);
+#if TARGET_OS_MAC
+ if (size < 256) {
+ size = 256;
+ }
+#endif
+ return size;
+}
+
@end
diff --git a/objc/04-DrawingIn3D/DrawingIn3D/ViewController.h b/objc/04-DrawingIn3D/DrawingIn3D/ViewController.h
index 50a1e30..944d9df 100644
--- a/objc/04-DrawingIn3D/DrawingIn3D/ViewController.h
+++ b/objc/04-DrawingIn3D/DrawingIn3D/ViewController.h
@@ -1,7 +1,16 @@
+#import
+
+#if TARGET_OS_IPHONE
@import UIKit;
+#define NSUIViewController UIViewController
+#else
+@import AppKit;
+#define NSUIViewController NSViewController
+#endif
+
#import "MBERenderer.h"
-@interface ViewController : UIViewController
+@interface ViewController : NSUIViewController
@end