Backends for Mac OS X, iOS and tvOS

This is a bunch of experimental render backends for Mac OS X, iOS and
tvOS.
This commit is contained in:
richi 2016-01-17 16:09:59 +01:00
parent 9f067e37c2
commit 5d1fdcdbe2
17 changed files with 2466 additions and 0 deletions

53
demo/apple/.gitignore vendored Executable file
View File

@ -0,0 +1,53 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
*.ipa
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
fastlane/report.xml
fastlane/screenshots

View File

@ -0,0 +1,289 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
500B20241C4B41870002B53F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B20231C4B41870002B53F /* main.m */; };
500B20401C4B43930002B53F /* ZahnradBackend.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B203F1C4B43930002B53F /* ZahnradBackend.m */; };
500B20421C4B43A30002B53F /* zahnrad.c in Sources */ = {isa = PBXBuildFile; fileRef = 500B20411C4B43A30002B53F /* zahnrad.c */; };
500B20481C4B43BC0002B53F /* DroidSans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20441C4B43BC0002B53F /* DroidSans.ttf */; };
500B20491C4B43BC0002B53F /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20451C4B43BC0002B53F /* Roboto-Bold.ttf */; };
500B204A1C4B43BC0002B53F /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20461C4B43BC0002B53F /* Roboto-Light.ttf */; };
500B204B1C4B43BC0002B53F /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20471C4B43BC0002B53F /* Roboto-Regular.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
500B201C1C4B41870002B53F /* Mac_GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Mac_GL.app; sourceTree = BUILT_PRODUCTS_DIR; };
500B20231C4B41870002B53F /* main.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; tabWidth = 4; };
500B202A1C4B41880002B53F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
500B203E1C4B43930002B53F /* ZahnradBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ZahnradBackend.h; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B203F1C4B43930002B53F /* ZahnradBackend.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = ZahnradBackend.m; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B20411C4B43A30002B53F /* zahnrad.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = zahnrad.c; path = ../../../zahnrad.c; sourceTree = "<group>"; tabWidth = 5; };
500B20441C4B43BC0002B53F /* DroidSans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = DroidSans.ttf; sourceTree = "<group>"; };
500B20451C4B43BC0002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
500B20461C4B43BC0002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
500B20471C4B43BC0002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
500B20191C4B41870002B53F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
500B20131C4B41870002B53F = {
isa = PBXGroup;
children = (
500B201E1C4B41870002B53F /* Mac_GL */,
500B20431C4B43BC0002B53F /* font */,
500B201D1C4B41870002B53F /* Products */,
);
sourceTree = "<group>";
};
500B201D1C4B41870002B53F /* Products */ = {
isa = PBXGroup;
children = (
500B201C1C4B41870002B53F /* Mac_GL.app */,
);
name = Products;
sourceTree = "<group>";
};
500B201E1C4B41870002B53F /* Mac_GL */ = {
isa = PBXGroup;
children = (
500B203E1C4B43930002B53F /* ZahnradBackend.h */,
500B203F1C4B43930002B53F /* ZahnradBackend.m */,
500B20231C4B41870002B53F /* main.m */,
500B20411C4B43A30002B53F /* zahnrad.c */,
500B202A1C4B41880002B53F /* Info.plist */,
);
path = Mac_GL;
sourceTree = "<group>";
};
500B20431C4B43BC0002B53F /* font */ = {
isa = PBXGroup;
children = (
500B20441C4B43BC0002B53F /* DroidSans.ttf */,
500B20451C4B43BC0002B53F /* Roboto-Bold.ttf */,
500B20461C4B43BC0002B53F /* Roboto-Light.ttf */,
500B20471C4B43BC0002B53F /* Roboto-Regular.ttf */,
);
name = font;
path = ../../font;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
500B201B1C4B41870002B53F /* Mac_GL */ = {
isa = PBXNativeTarget;
buildConfigurationList = 500B202D1C4B41880002B53F /* Build configuration list for PBXNativeTarget "Mac_GL" */;
buildPhases = (
500B20181C4B41870002B53F /* Sources */,
500B20191C4B41870002B53F /* Frameworks */,
500B201A1C4B41870002B53F /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Mac_GL;
productName = Mac_GL;
productReference = 500B201C1C4B41870002B53F /* Mac_GL.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
500B20141C4B41870002B53F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = richi;
TargetAttributes = {
500B201B1C4B41870002B53F = {
CreatedOnToolsVersion = 7.2;
};
};
};
buildConfigurationList = 500B20171C4B41870002B53F /* Build configuration list for PBXProject "Mac_GL" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 500B20131C4B41870002B53F;
productRefGroup = 500B201D1C4B41870002B53F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
500B201B1C4B41870002B53F /* Mac_GL */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
500B201A1C4B41870002B53F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B20491C4B43BC0002B53F /* Roboto-Bold.ttf in Resources */,
500B20481C4B43BC0002B53F /* DroidSans.ttf in Resources */,
500B204B1C4B43BC0002B53F /* Roboto-Regular.ttf in Resources */,
500B204A1C4B43BC0002B53F /* Roboto-Light.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
500B20181C4B41870002B53F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B20241C4B41870002B53F /* main.m in Sources */,
500B20421C4B43A30002B53F /* zahnrad.c in Sources */,
500B20401C4B43930002B53F /* ZahnradBackend.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
500B202B1C4B41880002B53F /* 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.8;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
500B202C1C4B41880002B53F /* 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.8;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
500B202E1C4B41880002B53F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Mac_GL/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.Mac-GL";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
500B202F1C4B41880002B53F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Mac_GL/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.Mac-GL";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
500B20171C4B41870002B53F /* Build configuration list for PBXProject "Mac_GL" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B202B1C4B41880002B53F /* Debug */,
500B202C1C4B41880002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
500B202D1C4B41880002B53F /* Build configuration list for PBXNativeTarget "Mac_GL" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B202E1C4B41880002B53F /* Debug */,
500B202F1C4B41880002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 500B20141C4B41870002B53F /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Mac_GL.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 richi. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

400
demo/apple/Mac_GL/main.m Normal file
View File

@ -0,0 +1,400 @@
/*
Copyright (c) 2016 richi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#import "ZahnradBackend.h"
@interface ZahnradView : NSOpenGLView
@end
@implementation ZahnradView
{
ZahnradBackend* zr;
NSTrackingArea* currentTrackingArea;
CVDisplayLinkRef displayLink;
}
#pragma mark - Setup -
- (instancetype) initWithFrame: (NSRect) frameRect
{
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery,
0
};
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: pixelFormatAttributes];
assert(self = [super initWithFrame: frameRect pixelFormat: pixelFormat]);
[self updateTrackingArea];
[[self openGLContext] makeCurrentContext];
zr = [[ZahnradBackend alloc] initWithView: self];
return self;
}
#if !SIMULATE_TOUCH
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
return [(__bridge ZahnradView*) displayLinkContext drawFrameForTime: outputTime];
}
- (void) prepareOpenGL
{
// Synchronize buffer swaps with vertical refresh rate
GLint swapInt = 1;
[[self openGLContext] setValues: &swapInt forParameter: NSOpenGLCPSwapInterval];
// Create a display link capable of being used with all active displays
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
// Set the renderer output callback function
CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void* _Nullable)(self));
// Set the display link for the current renderer
CGLContextObj cglContext = [[self openGLContext] CGLContextObj];
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
// Activate the display link
CVDisplayLinkStart(displayLink);
}
#endif
- (void) glLocked: (dispatch_block_t) block
{
CGLLockContext(self.openGLContext.CGLContextObj);
@try
{
block();
}
@catch (NSException *exception)
{
NSLog(@"%@", exception);
}
@finally
{
CGLUnlockContext(self.openGLContext.CGLContextObj);
}
}
#pragma mark - Drawing -
- (void) drawFrame
{
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
[zr updateFrame];
[zr drawFrameWithScale: 1.0 width: self.bounds.size.width height: self.bounds.size.height];
[[self openGLContext] flushBuffer];
}
- (CVReturn) drawFrameForTime: (const CVTimeStamp*) outputTime
{
@autoreleasepool
{
[self glLocked: ^{
[[self openGLContext] makeCurrentContext];
[self drawFrame];
}];
}
return kCVReturnSuccess;
}
- (void) drawRect: (NSRect) dirtyRect
{
[self glLocked: ^{
[[self openGLContext] makeCurrentContext];
[super drawRect: dirtyRect];
[self drawFrame];
}];
}
#pragma mark - User Input -
- (void) addEvent: (NSDictionary*) event
{
[self glLocked: ^{
[zr addEvent: event];
}];
#if SIMULATE_TOUCH
[self setNeedsDisplay: YES];
#endif
}
- (void) mouseMoved: (NSEvent*) theEvent
{
#if !SIMULATE_TOUCH
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @1, @"pos" : NSStringFromPoint(location)}];
#endif
}
- (void) mouseDragged: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @2, @"pos" : NSStringFromPoint(location)}];
}
- (void) rightMouseDragged: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @3, @"pos" : NSStringFromPoint(location)}];
}
- (void) otherMouseDragged: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @4, @"pos" : NSStringFromPoint(location)}];
}
- (void) mouseDown: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @5, @"pos" : NSStringFromPoint(location)}];
}
- (void) mouseUp: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @6, @"pos" : NSStringFromPoint(location)}];
}
- (void) rightMouseDown: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @7, @"pos" : NSStringFromPoint(location)}];
}
- (void) rightMouseUp: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @8, @"pos" : NSStringFromPoint(location)}];
}
- (void) otherMouseDown: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @9, @"pos" : NSStringFromPoint(location)}];
}
- (void) otherMouseUp: (NSEvent*) theEvent
{
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
[self addEvent: @{@"type" : @10, @"pos" : NSStringFromPoint(location)}];
}
- (void) scrollWheel: (NSEvent*) theEvent
{
[self addEvent: @{@"type" : @11, @"deltaX" : @(theEvent.deltaX), @"deltaY" : @(theEvent.deltaY)}];
}
- (void) keyDown: (NSEvent*) theEvent
{
NSString* str = theEvent.characters;
if (str.length)
[self addEvent: @{@"type" : @12, @"txt" : str, @"mod" : @(theEvent.modifierFlags)}];
}
- (void) keyUp: (NSEvent*) theEvent
{
NSString* str = theEvent.characters;
if (str.length)
[self addEvent: @{@"type" : @13, @"txt" : str, @"mod" : @(theEvent.modifierFlags)}];
}
- (BOOL) acceptsFirstResponder
{
return YES;
}
- (void) removeCurrentTrackingArea
{
if (currentTrackingArea)
{
[self removeTrackingArea: currentTrackingArea];
currentTrackingArea = nil;
}
}
- (void) updateTrackingArea
{
[self removeCurrentTrackingArea];
#if !SIMULATE_TOUCH
currentTrackingArea = [[NSTrackingArea alloc]
initWithRect: self.bounds
options: NSTrackingMouseMoved | NSTrackingActiveInActiveApp
owner: self
userInfo: nil];
[self addTrackingArea: currentTrackingArea];
#endif
}
- (void) reshape
{
[self updateTrackingArea];
NSRect bounds = [self bounds];
[self glLocked: ^{
[[self openGLContext] makeCurrentContext];
glViewport((GLint)NSMinX(bounds), (GLint)NSMinY(bounds), (GLint)NSWidth(bounds), (GLint)NSHeight(bounds));
}];
}
- (void) update
{
[self glLocked: ^{
[super update];
}];
}
@end
#pragma mark - App Delegate -
@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>
@property (strong) IBOutlet NSWindow* window;
@end
@implementation AppDelegate
- (void) applicationDidFinishLaunching: (NSNotification*) aNotification
{
NSString* appName = [[NSProcessInfo processInfo] processName];
NSLog(@"Starting %@", appName);
NSMenu* appMenu = [NSMenu new];
[appMenu addItem: [[NSMenuItem alloc] initWithTitle: [@"Quit " stringByAppendingString: appName]
action: @selector(terminate:)
keyEquivalent: @"q"]];
NSMenuItem* appMenuItem = [NSMenuItem new];
[appMenuItem setSubmenu: appMenu];
NSMenu* menubar = [NSMenu new];
[menubar addItem: appMenuItem];
[NSApp setMainMenu: menubar];
NSRect frame = NSMakeRect(0, 0, 800, 600);
_window = [[NSWindow alloc] initWithContentRect: frame
styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
backing: NSBackingStoreBuffered
defer: NO];
[_window setContentView: [[ZahnradView alloc] initWithFrame: frame]];
[_window setDelegate: self];
[_window setTitle: appName];
[_window cascadeTopLeftFromPoint: NSMakePoint(20, 20)];
[_window makeKeyAndOrderFront: nil];
}
- (void) windowWillClose: (NSNotification*) notification
{
[NSApp terminate: self];
}
@end
int main()
{
@autoreleasepool
{
[NSApplication sharedApplication];
[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
AppDelegate* appDelegate = [AppDelegate new];
[NSApp setDelegate: appDelegate];
[NSApp run];
}
return EXIT_SUCCESS;
}

19
demo/apple/README.md Executable file
View File

@ -0,0 +1,19 @@
Zahnrad for Mac OS X, iOS and tvOS
==================================
This is a bunch of experimental render backends for [Zahnrad](https://github.com/vurtun/zahnrad) a gorgeous immediate mode GUI toolkit.
Include are native versions for Mac OS X, iOS and tvOS. The Mac version is using OpenGL 3.2. iOS and tvOS are running on OpenGL ES 3.2.
Versions utilising Metal are in the making.
How to use?
-----------
Open `ZahnradBackend.xcworkspace` with XCode and start your engines.
License
-------
[WTFPL](http://www.wtfpl.net)

View File

@ -0,0 +1,58 @@
/*
Copyright (c) 2016 Micha Mettke
Macintosh / Objective-C adaptation (c) 2016 richi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#import <Foundation/Foundation.h>
#define SIMULATE_TOUCH 0
#if (TARGET_OS_IPHONE && (!TARGET_OS_TV)) || SIMULATE_TOUCH
#define ZR_REFRESH_ON_EVENT_ONLY 1
#define ZR_TOUCH_SCREEN 1
#endif
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
#define GLVIEW GLKView
#else
#import <Cocoa/Cocoa.h>
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#import <OpenGL/gl3.h>
#define GLVIEW NSOpenGLView
#endif
@interface ZahnradBackend : NSObject
@property (readonly) GLVIEW* view;
- (instancetype) initWithView: (GLVIEW*) view;
- (void) addEvent: (NSDictionary*) event;
- (void) updateFrame;
- (void) drawFrameWithScale: (CGFloat) scale width: (CGFloat) width height: (CGFloat) height;
@end

607
demo/apple/ZahnradBackend.m Normal file
View File

@ -0,0 +1,607 @@
/*
Copyright (c) 2016 Micha Mettke
Macintosh / Objective-C adaptation (c) 2016 richi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "../../zahnrad.h"
#include "../demo.c"
#undef MAX
#undef MIN
#import "ZahnradBackend.h"
#define MAX_VERTEX_MEMORY (512 * 1024)
#define MAX_ELEMENT_MEMORY (128 * 1024)
static void* mem_alloc(zr_handle unused, size_t size)
{
return calloc(1, size);
}
static void mem_free(zr_handle unused, void* ptr)
{
free(ptr);
}
struct device
{
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
GLuint frag_shdr;
GLint attrib_pos;
GLint attrib_uv;
GLint attrib_col;
GLint uniform_tex;
GLint uniform_proj;
GLuint font_tex;
struct zr_draw_null_texture null;
struct zr_buffer cmds;
};
@implementation ZahnradBackend
{
struct demo gui;
struct device device;
struct zr_font font;
struct zr_user_font usrfnt;
struct zr_allocator alloc;
NSMutableArray* events;
NSMutableArray* drawCommands;
}
#pragma mark - Setup -
- (instancetype) initWithView: (GLVIEW*) view;
{
if (!(self = [super init])) return self;
_view = view;
events = [NSMutableArray new];
drawCommands = [NSMutableArray new];
[self setupGL];
NSURL* fontURL = [[NSBundle mainBundle] URLForResource: @"DroidSans" withExtension: @"ttf"];
assert(fontURL != nil);
alloc.userdata.ptr = NULL;
alloc.alloc = mem_alloc;
alloc.free = mem_free;
zr_buffer_init(&device.cmds, &alloc, 4096);
usrfnt = [self fontFromUrl: fontURL height: 14 range: zr_font_default_glyph_ranges()];
zr_init(&gui.ctx, &alloc, &usrfnt);
[self fillFrame];
return self;
}
- (void) setupGL
{
GLint status;
static const GLchar* vss =
#if TARGET_OS_IPHONE
"#version 300 es\n"
#else
"#version 150\n"
#endif
"uniform mat4 ProjMtx;\n"
"in vec2 Position;\n"
"in vec2 TexCoord;\n"
"in vec4 Color;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main() {\n"
" Frag_UV = TexCoord;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
"}\n";
static const GLchar* fss =
#if TARGET_OS_IPHONE
"#version 300 es\n"
#else
"#version 150\n"
#endif
"precision mediump float;\n"
"uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"out vec4 Out_Color;\n"
"void main(){\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
device.prog = glCreateProgram();
device.vert_shdr = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(device.vert_shdr, 1, &vss, 0);
glCompileShader(device.vert_shdr);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(device.vert_shdr, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar* log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(device.vert_shdr, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(device.vert_shdr, GL_COMPILE_STATUS, &status);
assert(status == GL_TRUE);
device.frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(device.frag_shdr, 1, &fss, 0);
glCompileShader(device.frag_shdr);
#if defined(DEBUG)
glGetShaderiv(device.frag_shdr, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar* log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(device.frag_shdr, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(device.frag_shdr, GL_COMPILE_STATUS, &status);
assert(status == GL_TRUE);
glAttachShader(device.prog, device.vert_shdr);
glAttachShader(device.prog, device.frag_shdr);
glLinkProgram(device.prog);
#if defined(DEBUG)
glGetProgramiv(device.prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar* log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(device.prog, logLength, &logLength, log);
NSLog(@"Program link log:\n%s", log);
free(log);
}
#endif
glGetProgramiv(device.prog, GL_LINK_STATUS, &status);
assert(status == GL_TRUE);
device.uniform_tex = glGetUniformLocation(device.prog, "Texture");
device.uniform_proj = glGetUniformLocation(device.prog, "ProjMtx");
device.attrib_pos = glGetAttribLocation(device.prog, "Position");
device.attrib_uv = glGetAttribLocation(device.prog, "TexCoord");
device.attrib_col = glGetAttribLocation(device.prog, "Color");
// buffer setup
GLsizei vs = sizeof(struct zr_draw_vertex);
size_t vp = offsetof(struct zr_draw_vertex, position);
size_t vt = offsetof(struct zr_draw_vertex, uv);
size_t vc = offsetof(struct zr_draw_vertex, col);
// allocate vertex and element buffer
glGenBuffers(1, &device.vbo);
glGenBuffers(1, &device.ebo);
glGenVertexArrays(1, &device.vao);
glBindVertexArray(device.vao);
glBindBuffer(GL_ARRAY_BUFFER, device.vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, device.ebo);
glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
glEnableVertexAttribArray((GLuint)device.attrib_pos);
glEnableVertexAttribArray((GLuint)device.attrib_uv);
glEnableVertexAttribArray((GLuint)device.attrib_col);
glVertexAttribPointer((GLuint)device.attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
glVertexAttribPointer((GLuint)device.attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
glVertexAttribPointer((GLuint)device.attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
- (struct zr_user_font) fontFromUrl: (NSURL*) url height: (unsigned) fontHeight range: (const zr_rune*) range
{
struct zr_baked_font baked_font;
struct zr_user_font user_font;
struct zr_recti custom;
memset(&baked_font, 0, sizeof(baked_font));
memset(&user_font, 0, sizeof(user_font));
memset(&custom, 0, sizeof(custom));
// bake and upload font texture
NSData* ttfData = [NSData dataWithContentsOfURL: url];
assert(ttfData != nil);
// setup font configuration
struct zr_font_config config;
memset(&config, 0, sizeof(config));
config.ttf_blob = (void*)ttfData.bytes;
config.font = &baked_font;
config.coord_type = ZR_COORD_UV;
config.range = range;
config.pixel_snap = zr_false;
config.size = (float)fontHeight;
config.spacing = zr_vec2(0, 0);
config.oversample_h = 1;
config.oversample_v = 1;
// query needed amount of memory for the font baking process
int glyph_count;
size_t tmp_size;
zr_font_bake_memory(&tmp_size, &glyph_count, &config, 1);
struct zr_font_glyph* glyphes = (struct zr_font_glyph*)calloc(sizeof(struct zr_font_glyph), (size_t)glyph_count);
void* tmp = calloc(1, tmp_size);
// pack all glyphes and return needed image width, height and memory size
int img_width, img_height;
size_t img_size;
custom.w = 2; custom.h = 2;
assert(zr_font_bake_pack(&img_size, &img_width, &img_height, &custom, tmp, tmp_size, &config, 1));
// bake all glyphes and custom white pixel into image
const char* custom_data = "....";
void* img = calloc(1, img_size);
zr_font_bake(img, img_width, img_height, tmp, tmp_size, glyphes, glyph_count, &config, 1);
zr_font_bake_custom_data(img, img_width, img_height, custom, custom_data, 2, 2, '.', 'X');
// convert alpha8 image into rgba8 image
void* img_rgba = calloc(4, (size_t)(img_height * img_width));
zr_font_bake_convert(img_rgba, img_width, img_height, img);
free(img);
img = img_rgba;
// upload baked font image
glGenTextures(1, &device.font_tex);
glBindTexture(GL_TEXTURE_2D, device.font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)img_width, (GLsizei)img_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
free(tmp);
free(img);
// default white pixel in a texture which is needed to draw primitives
device.null.texture.id = (int)device.font_tex;
device.null.uv = zr_vec2((custom.x + 0.5f) / (float)img_width,
(custom.y + 0.5f) / (float)img_height);
/* setup font with glyphes. IMPORTANT: the font only references the glyphes
this was done to have the possibility to have multible fonts with one
total glyph array. Not quite sure if it is a good thing since the
glyphes have to be freed as well.
*/
zr_font_init(&font, (float)fontHeight, '?', glyphes, &baked_font, device.null.texture);
return zr_font_ref(&font);
}
#pragma mark - Drawing -
- (void) drawFrameWithScale: (CGFloat) scale width: (CGFloat) width height: (CGFloat) height
{
// save opengl state
GLint last_prog, last_tex;
GLint last_ebo, last_vbo, last_vao;
glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
// setup global state
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0);
// setup program
GLfloat ortho[4][4] = {
{2.0f, 0.0f, 0.0f, 0.0f},
{0.0f, -2.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 0.0f},
{-1.0f, 1.0f, 0.0f, 1.0f},
};
ortho[0][0] /= width;
ortho[1][1] /= height;
glUseProgram(device.prog);
glUniform1i(device.uniform_tex, 0);
glUniformMatrix4fv(device.uniform_proj, 1, GL_FALSE, &ortho[0][0]);
// activate vertex and element buffer
glBindVertexArray(device.vao);
glBindBuffer(GL_ARRAY_BUFFER, device.vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, device.ebo);
// if draw commands have been buffered we will draw only those
if (drawCommands.count)
{
const struct zr_draw_command* cmd;
const zr_draw_index* offset = NULL;
// iterate over and execute each draw command
for (NSData* data in drawCommands)
{
cmd = data.bytes;
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor((GLint)(cmd->clip_rect.x * scale),
(GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale),
(GLint)(cmd->clip_rect.w * scale),
(GLint)(cmd->clip_rect.h * scale));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
}
else
{
// load draw vertexes & elements into vertex + element buffer
void* vertexes = glMapBufferRange(GL_ARRAY_BUFFER, 0, MAX_VERTEX_MEMORY, GL_MAP_WRITE_BIT);
void* elements = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, MAX_ELEMENT_MEMORY, GL_MAP_WRITE_BIT);
// fill converting configuration
struct zr_convert_config config;
memset(&config, 0, sizeof(config));
config.shape_AA = ZR_ANTI_ALIASING_ON;
config.line_AA = ZR_ANTI_ALIASING_ON;
config.circle_segment_count = 22;
config.line_thickness = 1.0f;
config.null = device.null;
// setup buffers to load vertexes and elements
struct zr_buffer vbuf, ebuf;
zr_buffer_init_fixed(&vbuf, vertexes, MAX_VERTEX_MEMORY);
zr_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
zr_convert(&gui.ctx, &device.cmds, &vbuf, &ebuf, &config);
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
// convert from command queue into draw list and draw to screen
const struct zr_draw_command* cmd;
const zr_draw_index* offset = NULL;
[drawCommands removeAllObjects];
// iterate over and execute each draw command
zr_draw_foreach(cmd, &gui.ctx, &device.cmds)
{
if (cmd->elem_count > 0)
{
#if ZR_REFRESH_ON_EVENT_ONLY
[drawCommands addObject: [NSData dataWithBytes: cmd length: sizeof(struct zr_draw_command)]];
#endif
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor((GLint)(cmd->clip_rect.x * scale),
(GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale),
(GLint)(cmd->clip_rect.w * scale),
(GLint)(cmd->clip_rect.h * scale));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
}
zr_clear(&gui.ctx);
}
// restore old state
glUseProgram((GLuint)last_prog);
glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
glBindVertexArray((GLuint)last_vao);
glDisable(GL_SCISSOR_TEST);
}
- (void) fillFrame
{
run_demo(&gui);
}
#pragma mark - Events -
- (void) updateFrame
{
#if ZR_REFRESH_ON_EVENT_ONLY
if (events.count)
#endif
{
[self handleEvents];
[self fillFrame];
}
}
- (void) handleEvents
{
NSArray* currentEvents = events.copy;
[events removeAllObjects];
zr_input_begin(&gui.ctx);
for (NSDictionary* event in currentEvents)
{
#if TARGET_OS_IPHONE
CGPoint location = CGPointFromString(event[@"pos"]);
#else
NSPoint location = NSPointFromString(event[@"pos"]);
location.y = (int)(self.view.bounds.size.height - location.y);
#endif
int x = (int)location.x;
int y = (int)location.y;
int type = [event[@"type"] intValue];
switch (type)
{
#if ZR_REFRESH_ON_EVENT_ONLY || ZR_TOUCH_SCREEN
case 2: case 3: case 4:
zr_input_motion(&gui.ctx, x, y);
break;
case 5:
zr_input_motion(&gui.ctx, x, y);
zr_input_end(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_true);
break;
case 6:
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_false);
zr_input_end(&gui.ctx);
[self fillFrame];
zr_clear(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_motion(&gui.ctx, INT_MAX, INT_MAX);
break;
#else
case 1: case 2: case 3: case 4:
zr_input_motion(&gui.ctx, x, y);
break;
case 5:
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_true);
break;
case 6:
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_false);
break;
case 7:
zr_input_button(&gui.ctx, ZR_BUTTON_RIGHT, x, y, zr_true);
break;
case 8:
zr_input_button(&gui.ctx, ZR_BUTTON_RIGHT, x, y, zr_false);
break;
case 9:
zr_input_button(&gui.ctx, ZR_BUTTON_MIDDLE, x, y, zr_true);
break;
case 10:
zr_input_button(&gui.ctx, ZR_BUTTON_MIDDLE, x, y, zr_false);
break;
case 11:
zr_input_scroll(&gui.ctx, -[event[@"deltaY"] floatValue]);
break;
#if !TARGET_OS_IPHONE
case 12:
case 13:
{
int down = type == 12 ? zr_true : zr_false;
NSString* str = event[@"txt"];
NSData* data = [str dataUsingEncoding: NSUTF32LittleEndianStringEncoding];
const uint32_t* c = data.bytes;
NSInteger n = data.length / sizeof(uint32_t);
for (NSInteger i = 0; i < n; i += 1, c += 1)
{
if (*c == 127 || *c < ' ' || *c >= NSUpArrowFunctionKey)
{
switch (*c)
{
case NSLeftArrowFunctionKey:
zr_input_key(&gui.ctx, ZR_KEY_LEFT, down);
break;
case NSRightArrowFunctionKey:
zr_input_key(&gui.ctx, ZR_KEY_RIGHT, down);
break;
case 3:
zr_input_key(&gui.ctx, ZR_KEY_COPY, down);
break;
case 22:
zr_input_key(&gui.ctx, ZR_KEY_PASTE, down);
break;
case 24:
zr_input_key(&gui.ctx, ZR_KEY_CUT, down);
break;
case 9:
zr_input_key(&gui.ctx, ZR_KEY_TAB, down);
break;
case 13:
zr_input_key(&gui.ctx, ZR_KEY_ENTER, down);
break;
case 127:
zr_input_key(&gui.ctx, ZR_KEY_BACKSPACE, down);
break;
default:
break;
}
}
else if (down)
{
zr_input_unicode(&gui.ctx, *c);
}
}
}
break;
#endif
#endif
default:
break;
}
}
zr_input_end(&gui.ctx);
}
- (void) addEvent: (NSDictionary*) event
{
[drawCommands removeAllObjects];
[events addObject: event];
}
@end

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Mac_GL.xcodeproj">
</FileRef>
<FileRef
location = "group:iOS_GL_ES.xcodeproj">
</FileRef>
<FileRef
location = "group:tvOS_GL_ES.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,292 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
500B1FFA1C4B410F0002B53F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B1FF91C4B410F0002B53F /* main.m */; };
500B20321C4B42B60002B53F /* ZahnradBackend.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B20311C4B42B60002B53F /* ZahnradBackend.m */; };
500B20341C4B43010002B53F /* zahnrad.c in Sources */ = {isa = PBXBuildFile; fileRef = 500B20331C4B43010002B53F /* zahnrad.c */; };
500B203A1C4B43380002B53F /* DroidSans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20361C4B43380002B53F /* DroidSans.ttf */; };
500B203B1C4B43380002B53F /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20371C4B43380002B53F /* Roboto-Bold.ttf */; };
500B203C1C4B43380002B53F /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20381C4B43380002B53F /* Roboto-Light.ttf */; };
500B203D1C4B43380002B53F /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20391C4B43380002B53F /* Roboto-Regular.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
500B1FF51C4B410F0002B53F /* iOS_GL_ES.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOS_GL_ES.app; sourceTree = BUILT_PRODUCTS_DIR; };
500B1FF91C4B410F0002B53F /* main.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; tabWidth = 4; };
500B200D1C4B410F0002B53F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
500B20301C4B42B60002B53F /* ZahnradBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ZahnradBackend.h; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B20311C4B42B60002B53F /* ZahnradBackend.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = ZahnradBackend.m; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B20331C4B43010002B53F /* zahnrad.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = zahnrad.c; path = ../../../zahnrad.c; sourceTree = "<group>"; tabWidth = 4; };
500B20361C4B43380002B53F /* DroidSans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = DroidSans.ttf; sourceTree = "<group>"; };
500B20371C4B43380002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
500B20381C4B43380002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
500B20391C4B43380002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
500B1FF21C4B410F0002B53F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
500B1FEC1C4B410F0002B53F = {
isa = PBXGroup;
children = (
500B1FF71C4B410F0002B53F /* iOS_GL_ES */,
500B20351C4B43380002B53F /* font */,
500B1FF61C4B410F0002B53F /* Products */,
);
sourceTree = "<group>";
};
500B1FF61C4B410F0002B53F /* Products */ = {
isa = PBXGroup;
children = (
500B1FF51C4B410F0002B53F /* iOS_GL_ES.app */,
);
name = Products;
sourceTree = "<group>";
};
500B1FF71C4B410F0002B53F /* iOS_GL_ES */ = {
isa = PBXGroup;
children = (
500B20301C4B42B60002B53F /* ZahnradBackend.h */,
500B20311C4B42B60002B53F /* ZahnradBackend.m */,
500B1FF91C4B410F0002B53F /* main.m */,
500B20331C4B43010002B53F /* zahnrad.c */,
500B200D1C4B410F0002B53F /* Info.plist */,
);
path = iOS_GL_ES;
sourceTree = "<group>";
};
500B20351C4B43380002B53F /* font */ = {
isa = PBXGroup;
children = (
500B20361C4B43380002B53F /* DroidSans.ttf */,
500B20371C4B43380002B53F /* Roboto-Bold.ttf */,
500B20381C4B43380002B53F /* Roboto-Light.ttf */,
500B20391C4B43380002B53F /* Roboto-Regular.ttf */,
);
name = font;
path = ../../font;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
500B1FF41C4B410F0002B53F /* iOS_GL_ES */ = {
isa = PBXNativeTarget;
buildConfigurationList = 500B20101C4B410F0002B53F /* Build configuration list for PBXNativeTarget "iOS_GL_ES" */;
buildPhases = (
500B1FF11C4B410F0002B53F /* Sources */,
500B1FF21C4B410F0002B53F /* Frameworks */,
500B1FF31C4B410F0002B53F /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = iOS_GL_ES;
productName = iOS_GL_ES;
productReference = 500B1FF51C4B410F0002B53F /* iOS_GL_ES.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
500B1FED1C4B410F0002B53F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = richi;
TargetAttributes = {
500B1FF41C4B410F0002B53F = {
CreatedOnToolsVersion = 7.2;
};
};
};
buildConfigurationList = 500B1FF01C4B410F0002B53F /* Build configuration list for PBXProject "iOS_GL_ES" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 500B1FEC1C4B410F0002B53F;
productRefGroup = 500B1FF61C4B410F0002B53F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
500B1FF41C4B410F0002B53F /* iOS_GL_ES */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
500B1FF31C4B410F0002B53F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B203B1C4B43380002B53F /* Roboto-Bold.ttf in Resources */,
500B203A1C4B43380002B53F /* DroidSans.ttf in Resources */,
500B203D1C4B43380002B53F /* Roboto-Regular.ttf in Resources */,
500B203C1C4B43380002B53F /* Roboto-Light.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
500B1FF11C4B410F0002B53F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B1FFA1C4B410F0002B53F /* main.m in Sources */,
500B20341C4B43010002B53F /* zahnrad.c in Sources */,
500B20321C4B42B60002B53F /* ZahnradBackend.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
500B200E1C4B410F0002B53F /* 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[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
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;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
500B200F1C4B410F0002B53F /* 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[sdk=iphoneos*]" = "iPhone Developer";
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;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
500B20111C4B410F0002B53F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = iOS_GL_ES/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.iOS-GL-ES";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
500B20121C4B410F0002B53F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = iOS_GL_ES/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.iOS-GL-ES";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
500B1FF01C4B410F0002B53F /* Build configuration list for PBXProject "iOS_GL_ES" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B200E1C4B410F0002B53F /* Debug */,
500B200F1C4B410F0002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
500B20101C4B410F0002B53F /* Build configuration list for PBXNativeTarget "iOS_GL_ES" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B20111C4B410F0002B53F /* Debug */,
500B20121C4B410F0002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 500B1FED1C4B410F0002B53F /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:iOS_GL_ES.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

150
demo/apple/iOS_GL_ES/main.m Normal file
View File

@ -0,0 +1,150 @@
/*
Copyright (c) 2016 richi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import "ZahnradBackend.h"
@interface GameViewController : GLKViewController
@end
@implementation GameViewController
{
EAGLContext* context;
ZahnradBackend* zr;
}
- (void) viewDidLoad
{
[super viewDidLoad];
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3];
assert(context != nil);
((GLKView*)self.view).context = context;
((GLKView*)self.view).drawableDepthFormat = GLKViewDrawableDepthFormatNone;
[EAGLContext setCurrentContext: context];
zr = [[ZahnradBackend alloc] initWithView: ((GLKView*)self.view)];
}
- (BOOL) prefersStatusBarHidden
{
return YES;
}
- (void) update
{
[zr updateFrame];
}
- (void) glkView: (GLKView*) view drawInRect: (CGRect) rect
{
CGRect bounds = view.bounds;
CGFloat scale = view.window.screen.scale;
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
[zr drawFrameWithScale: scale width: bounds.size.width height: bounds.size.height];
}
#pragma mark - User Input -
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event
{
UITouch* touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView: self.view];
[zr addEvent: @{@"type" : @2, @"pos" : NSStringFromCGPoint(location)}];
}
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event
{
UITouch* touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView: self.view];
[zr addEvent: @{@"type" : @5, @"pos" : NSStringFromCGPoint(location)}];
}
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event
{
UITouch* touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView: self.view];
[zr addEvent: @{@"type" : @6, @"pos" : NSStringFromCGPoint(location)}];
}
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event
{
[self touchesEnded: touches withEvent: event];
}
@end
#pragma mark - App Delegate -
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow* window;
@end
@implementation AppDelegate
- (BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
{
_window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
_window.rootViewController = [GameViewController new];
[_window makeKeyAndVisible];
return YES;
}
@end
int main(int argc, char* argv[])
{
@autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,288 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
500B20661C4B4AB00002B53F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B20651C4B4AB00002B53F /* main.m */; };
500B208A1C4B4D460002B53F /* ZahnradBackend.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B20891C4B4D460002B53F /* ZahnradBackend.m */; };
500B208C1C4B4D580002B53F /* zahnrad.c in Sources */ = {isa = PBXBuildFile; fileRef = 500B208B1C4B4D580002B53F /* zahnrad.c */; };
500B20921C4B4D700002B53F /* DroidSans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B208E1C4B4D700002B53F /* DroidSans.ttf */; };
500B20931C4B4D700002B53F /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B208F1C4B4D700002B53F /* Roboto-Bold.ttf */; };
500B20941C4B4D700002B53F /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20901C4B4D700002B53F /* Roboto-Light.ttf */; };
500B20951C4B4D700002B53F /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20911C4B4D700002B53F /* Roboto-Regular.ttf */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
500B20611C4B4AB00002B53F /* tvOS_GL_ES.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tvOS_GL_ES.app; sourceTree = BUILT_PRODUCTS_DIR; };
500B20651C4B4AB00002B53F /* main.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; tabWidth = 4; };
500B20741C4B4AB00002B53F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
500B20881C4B4D460002B53F /* ZahnradBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ZahnradBackend.h; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B20891C4B4D460002B53F /* ZahnradBackend.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = ZahnradBackend.m; sourceTree = SOURCE_ROOT; tabWidth = 4; };
500B208B1C4B4D580002B53F /* zahnrad.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = zahnrad.c; path = ../../../zahnrad.c; sourceTree = "<group>"; tabWidth = 5; };
500B208E1C4B4D700002B53F /* DroidSans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = DroidSans.ttf; sourceTree = "<group>"; };
500B208F1C4B4D700002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
500B20901C4B4D700002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
500B20911C4B4D700002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
500B205E1C4B4AB00002B53F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
500B20581C4B4AB00002B53F = {
isa = PBXGroup;
children = (
500B20631C4B4AB00002B53F /* tvOS_GL_ES */,
500B208D1C4B4D700002B53F /* font */,
500B20621C4B4AB00002B53F /* Products */,
);
sourceTree = "<group>";
};
500B20621C4B4AB00002B53F /* Products */ = {
isa = PBXGroup;
children = (
500B20611C4B4AB00002B53F /* tvOS_GL_ES.app */,
);
name = Products;
sourceTree = "<group>";
};
500B20631C4B4AB00002B53F /* tvOS_GL_ES */ = {
isa = PBXGroup;
children = (
500B20881C4B4D460002B53F /* ZahnradBackend.h */,
500B20891C4B4D460002B53F /* ZahnradBackend.m */,
500B20651C4B4AB00002B53F /* main.m */,
500B208B1C4B4D580002B53F /* zahnrad.c */,
500B20741C4B4AB00002B53F /* Info.plist */,
);
path = tvOS_GL_ES;
sourceTree = "<group>";
};
500B208D1C4B4D700002B53F /* font */ = {
isa = PBXGroup;
children = (
500B208E1C4B4D700002B53F /* DroidSans.ttf */,
500B208F1C4B4D700002B53F /* Roboto-Bold.ttf */,
500B20901C4B4D700002B53F /* Roboto-Light.ttf */,
500B20911C4B4D700002B53F /* Roboto-Regular.ttf */,
);
name = font;
path = ../../font;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
500B20601C4B4AB00002B53F /* tvOS_GL_ES */ = {
isa = PBXNativeTarget;
buildConfigurationList = 500B20771C4B4AB00002B53F /* Build configuration list for PBXNativeTarget "tvOS_GL_ES" */;
buildPhases = (
500B205D1C4B4AB00002B53F /* Sources */,
500B205E1C4B4AB00002B53F /* Frameworks */,
500B205F1C4B4AB00002B53F /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = tvOS_GL_ES;
productName = tvOS_GL_ES;
productReference = 500B20611C4B4AB00002B53F /* tvOS_GL_ES.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
500B20591C4B4AB00002B53F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = richi;
TargetAttributes = {
500B20601C4B4AB00002B53F = {
CreatedOnToolsVersion = 7.2;
};
};
};
buildConfigurationList = 500B205C1C4B4AB00002B53F /* Build configuration list for PBXProject "tvOS_GL_ES" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 500B20581C4B4AB00002B53F;
productRefGroup = 500B20621C4B4AB00002B53F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
500B20601C4B4AB00002B53F /* tvOS_GL_ES */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
500B205F1C4B4AB00002B53F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B20931C4B4D700002B53F /* Roboto-Bold.ttf in Resources */,
500B20921C4B4D700002B53F /* DroidSans.ttf in Resources */,
500B20951C4B4D700002B53F /* Roboto-Regular.ttf in Resources */,
500B20941C4B4D700002B53F /* Roboto-Light.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
500B205D1C4B4AB00002B53F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
500B20661C4B4AB00002B53F /* main.m in Sources */,
500B208C1C4B4D580002B53F /* zahnrad.c in Sources */,
500B208A1C4B4D460002B53F /* ZahnradBackend.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
500B20751C4B4AB00002B53F /* 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;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
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;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = appletvos;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.1;
};
name = Debug;
};
500B20761C4B4AB00002B53F /* 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;
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;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = appletvos;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.1;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
500B20781C4B4AB00002B53F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = tvOS_GL_ES/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.tvOS-GL-ES";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
500B20791C4B4AB00002B53F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = tvOS_GL_ES/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.richi.tvOS-GL-ES";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
500B205C1C4B4AB00002B53F /* Build configuration list for PBXProject "tvOS_GL_ES" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B20751C4B4AB00002B53F /* Debug */,
500B20761C4B4AB00002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
500B20771C4B4AB00002B53F /* Build configuration list for PBXNativeTarget "tvOS_GL_ES" */ = {
isa = XCConfigurationList;
buildConfigurations = (
500B20781C4B4AB00002B53F /* Debug */,
500B20791C4B4AB00002B53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 500B20591C4B4AB00002B53F /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:tvOS_GL_ES.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,164 @@
/*
Copyright (c) 2016 richi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import "ZahnradBackend.h"
@interface GameViewController : GLKViewController
@end
@implementation GameViewController
{
EAGLContext* context;
ZahnradBackend* zr;
CGPoint cursor;
UIView* cursorView;
}
- (void) viewDidLoad
{
[super viewDidLoad];
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3];
assert(context != nil);
((GLKView*)self.view).context = context;
((GLKView*)self.view).drawableDepthFormat = GLKViewDrawableDepthFormatNone;
[EAGLContext setCurrentContext: context];
zr = [[ZahnradBackend alloc] initWithView: ((GLKView*)self.view)];
UIPanGestureRecognizer* panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector(pan:)];
[self.view addGestureRecognizer:panRecognizer];
cursorView = [[UIView alloc] initWithFrame: CGRectMake(100, 100, 10, 10)];
cursorView.backgroundColor = UIColor.redColor;
[self.view addSubview: cursorView];
}
- (void) update
{
[zr updateFrame];
}
- (void) glkView: (GLKView*) view drawInRect: (CGRect) rect
{
CGRect bounds = view.bounds;
CGFloat scale = view.window.screen.scale;
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
[zr drawFrameWithScale: scale width: bounds.size.width height: bounds.size.height];
}
#pragma mark - User Input -
- (void) pan: (UIPanGestureRecognizer*) panRecognizer
{
CGPoint delta = [panRecognizer translationInView: self.view];
cursor.x += delta.x / 33.0;
cursor.y += delta.y / 33.0;
CGRect bounds = self.view.bounds;
if (cursor.x < CGRectGetMinX(bounds)) cursor.x = CGRectGetMinX(bounds);
if (cursor.x > CGRectGetMaxX(bounds)) cursor.x = CGRectGetMaxX(bounds);
if (cursor.y < CGRectGetMinY(bounds)) cursor.y = CGRectGetMinY(bounds);
if (cursor.y > CGRectGetMaxY(bounds)) cursor.y = CGRectGetMaxY(bounds);
cursorView.center = cursor;
[zr addEvent: @{@"type" : @2, @"pos" : NSStringFromCGPoint(cursor)}];
}
- (void) pressesBegan: (NSSet*) presses withEvent: (UIPressesEvent*) event
{
UIPress* press = [[event allPresses] anyObject];
if (press.type != UIPressTypeSelect) return;
[zr addEvent: @{@"type" : @5, @"pos" : NSStringFromCGPoint(cursor)}];
}
- (void) pressesEnded: (NSSet*) presses withEvent: (UIPressesEvent*) event
{
UIPress* press = [[event allPresses] anyObject];
if (press.type != UIPressTypeSelect) return;
[zr addEvent: @{@"type" : @6, @"pos" : NSStringFromCGPoint(cursor)}];
}
- (void) pressesCancelled: (NSSet*) presses withEvent: (UIPressesEvent*) event
{
[self pressesEnded: presses withEvent: event];
}
@end
#pragma mark - App Delegate -
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow* window;
@end
@implementation AppDelegate
- (BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
{
_window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
_window.rootViewController = [GameViewController new];
[_window makeKeyAndVisible];
return YES;
}
@end
int main(int argc, char* argv[])
{
@autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}