Skip to content

Commit 19a3081

Browse files
Added tvOS native app implementation
1 parent c693122 commit 19a3081

15 files changed

Lines changed: 567 additions & 2 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="17701" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
3+
<device id="appleTV" appearance="light"/>
4+
<dependencies>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
6+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7+
</dependencies>
8+
<scenes>
9+
<!--Metal View Controller-->
10+
<scene sceneID="tne-QT-ifu">
11+
<objects>
12+
<viewController id="BYZ-38-t0r" customClass="MetalViewController" sceneMemberID="viewController">
13+
<layoutGuides>
14+
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
15+
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
16+
</layoutGuides>
17+
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="MainUIView">
18+
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
19+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
20+
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
21+
</view>
22+
</viewController>
23+
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
24+
</objects>
25+
<point key="canvasLocation" x="69" y="69"/>
26+
</scene>
27+
</scenes>
28+
</document>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>com.diligentengine.sampleapp</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>APPL</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleSignature</key>
20+
<string>????</string>
21+
<key>CFBundleVersion</key>
22+
<string>1</string>
23+
<key>LSRequiresIPhoneOS</key>
24+
<true/>
25+
<key>UIMainStoryboardFile</key>
26+
<string>Main</string>
27+
<key>UIRequiredDeviceCapabilities</key>
28+
<array>
29+
<string>metal</string>
30+
<string>armv7</string>
31+
</array>
32+
<key>UIUserInterfaceStyle</key>
33+
<string>Automatic</string>
34+
</dict>
35+
</plist>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
4+
Abstract:
5+
Application delegate for Metal Sample Code
6+
*/
7+
8+
#import <UIKit/UIKit.h>
9+
10+
@interface AppDelegate : UIResponder <UIApplicationDelegate>
11+
12+
@property (strong, nonatomic) UIWindow *window;
13+
14+
@end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
4+
Abstract:
5+
Application delegate for Metal Sample Code
6+
*/
7+
8+
#import "AppDelegate.h"
9+
10+
@implementation AppDelegate
11+
12+
@end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
*/
4+
5+
#import <Metal/Metal.h>
6+
#import <UIKit/UIKit.h>
7+
#import "MetalView.h"
8+
9+
@interface MainUIView : MetalView
10+
11+
@end
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
*/
4+
5+
#import "MainUIView.h"
6+
7+
@implementation MainUIView
8+
{
9+
CADisplayLink *_displayLink;
10+
}
11+
12+
+ (Class) layerClass
13+
{
14+
return [CAMetalLayer class];
15+
}
16+
17+
- (void)didMoveToWindow
18+
{
19+
[super didMoveToWindow];
20+
21+
if(self.window == nil)
22+
{
23+
// If moving off of a window destroy the display link.
24+
[_displayLink invalidate];
25+
_displayLink = nil;
26+
return;
27+
}
28+
29+
[self setupCADisplayLinkForScreen:self.window.screen];
30+
31+
// CADisplayLink callbacks are associated with an 'NSRunLoop'. The currentRunLoop is the
32+
// the main run loop (since 'didMoveToWindow' is always executed from the main thread.
33+
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
34+
35+
// Perform any actions which need to know the size and scale of the drawable. When UIKit calls
36+
// didMoveToWindow after the view initialization, this is the first opportunity to notify
37+
// components of the drawable's size
38+
[self resizeDrawable:self.window.screen.nativeScale];
39+
40+
self.layer.opaque = YES;
41+
self.opaque = YES;
42+
self.window.opaque = YES;
43+
}
44+
45+
46+
47+
- (void)setPaused:(BOOL)paused
48+
{
49+
super.paused = paused;
50+
51+
_displayLink.paused = paused;
52+
}
53+
54+
- (void)setupCADisplayLinkForScreen:(UIScreen*)screen
55+
{
56+
[self stopRenderLoop];
57+
58+
_displayLink = [screen displayLinkWithTarget:self selector:@selector(render)];
59+
60+
_displayLink.paused = self.paused;
61+
62+
_displayLink.preferredFramesPerSecond = 60;
63+
}
64+
65+
- (void)didEnterBackground:(NSNotification*)notification
66+
{
67+
self.paused = YES;
68+
}
69+
70+
- (void)willEnterForeground:(NSNotification*)notification
71+
{
72+
self.paused = NO;
73+
}
74+
75+
- (void)stopRenderLoop
76+
{
77+
[_displayLink invalidate];
78+
}
79+
80+
81+
82+
// Override all methods which indicate the view's size has changed
83+
84+
- (void)setContentScaleFactor:(CGFloat)contentScaleFactor
85+
{
86+
[super setContentScaleFactor:contentScaleFactor];
87+
[self resizeDrawable:self.window.screen.nativeScale];
88+
}
89+
90+
- (void)layoutSubviews
91+
{
92+
[super layoutSubviews];
93+
[self resizeDrawable:self.window.screen.nativeScale];
94+
}
95+
96+
- (void)setFrame:(CGRect)frame
97+
{
98+
[super setFrame:frame];
99+
[self resizeDrawable:self.window.screen.nativeScale];
100+
}
101+
102+
- (void)setBounds:(CGRect)bounds
103+
{
104+
[super setBounds:bounds];
105+
[self resizeDrawable:self.window.screen.nativeScale];
106+
}
107+
108+
@end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
*/
4+
5+
#import <QuartzCore/CAMetalLayer.h>
6+
#import <Metal/Metal.h>
7+
#import <UIKit/UIKit.h>
8+
9+
// Protocol to provide resize and redraw callbacks to a delegate
10+
@protocol MetalViewDelegate <NSObject>
11+
12+
- (void)drawableResize:(CGSize)size;
13+
14+
- (void)renderToMetalLayer:(nonnull CAMetalLayer *)metalLayer;
15+
16+
@end
17+
18+
// Metal view base class
19+
@interface MetalView : UIView <CALayerDelegate>
20+
21+
@property (nonatomic, nonnull, readonly) CAMetalLayer *metalLayer;
22+
23+
@property (nonatomic, getter=isPaused) BOOL paused;
24+
25+
@property (nonatomic, nullable, retain) id<MetalViewDelegate> delegate;
26+
27+
- (void)initCommon;
28+
29+
- (void)resizeDrawable:(CGFloat)scaleFactor;
30+
- (void)stopRenderLoop;
31+
- (void)render;
32+
33+
@end
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
*/
4+
5+
#import "MetalView.h"
6+
7+
@implementation MetalView
8+
9+
- (instancetype) initWithFrame:(CGRect)frame
10+
{
11+
self = [super initWithFrame:frame];
12+
if(self)
13+
{
14+
[self initCommon];
15+
}
16+
return self;
17+
}
18+
19+
- (instancetype) initWithCoder:(NSCoder *)aDecoder
20+
{
21+
self = [super initWithCoder:aDecoder];
22+
if(self)
23+
{
24+
[self initCommon];
25+
}
26+
return self;
27+
}
28+
29+
- (void)initCommon
30+
{
31+
_metalLayer = (CAMetalLayer*) self.layer;
32+
33+
self.layer.delegate = self;
34+
}
35+
36+
37+
- (void)stopRenderLoop
38+
{
39+
// Stubbed out method. Subclasses need to implement this method.
40+
}
41+
42+
- (void)dealloc
43+
{
44+
[self stopRenderLoop];
45+
[super dealloc];
46+
}
47+
48+
49+
- (void)resizeDrawable:(CGFloat)scaleFactor
50+
{
51+
CGSize newSize = self.bounds.size;
52+
newSize.width *= scaleFactor;
53+
newSize.height *= scaleFactor;
54+
55+
if(newSize.width <= 0 || newSize.width <= 0)
56+
{
57+
return;
58+
}
59+
60+
if(newSize.width == _metalLayer.drawableSize.width &&
61+
newSize.height == _metalLayer.drawableSize.height)
62+
{
63+
return;
64+
}
65+
66+
_metalLayer.drawableSize = newSize;
67+
68+
[_delegate drawableResize:newSize];
69+
}
70+
71+
72+
- (void)render
73+
{
74+
[_delegate renderToMetalLayer:_metalLayer];
75+
}
76+
77+
@end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
See LICENSE folder for this sample’s licensing information.
3+
*/
4+
5+
#import <UIKit/UIKit.h>
6+
#import "MetalView.h"
7+
8+
@interface MetalViewController : UIViewController <MetalViewDelegate>
9+
10+
@end

0 commit comments

Comments
 (0)