├── handmadeAssets ├── .gitkeep └── .gitignore ├── handmadeSrc └── .gitkeep ├── Handmade Hero Dylib ├── handmadeSrc └── Handmade Hero Dylib.xcodeproj │ └── project.pbxproj ├── Handmade Hero OSX ├── Handmade Hero OSX │ ├── handmadeSrc │ ├── handmadeAssets │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── hmhero512x512.jpeg │ │ │ └── Contents.json │ ├── Handmade Hero OSX-Bridging-Header.h │ ├── Helpers.swift │ ├── AppDelegate.swift │ ├── Info.plist │ ├── GameCodeLoader.swift │ ├── PlatformLayer.swift │ ├── ObjCShim.h │ ├── SoundManager.swift │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── ObjCShim.m │ ├── InputManager.swift │ └── GameView.swift ├── Handmade Hero OSX.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── Handmade Hero OSXTests │ ├── Info.plist │ └── Handmade_Hero_OSXTests.swift ├── .gitignore └── README.md /handmadeAssets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /handmadeSrc/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /handmadeAssets/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /Handmade Hero Dylib/handmadeSrc: -------------------------------------------------------------------------------- 1 | ../handmadeSrc/ -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/handmadeSrc: -------------------------------------------------------------------------------- 1 | ../../handmadeSrc/ -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/handmadeAssets: -------------------------------------------------------------------------------- 1 | ../../handmadeAssets/ -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Images.xcassets/AppIcon.appiconset/hmhero512x512.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joekarl/swift_handmade_hero/HEAD/Handmade Hero OSX/Handmade Hero OSX/Images.xcassets/AppIcon.appiconset/hmhero512x512.jpeg -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # Handmade source 21 | 22 | handmadeSrc/*.cpp 23 | handmadeSrc/*.h 24 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Handmade Hero OSX-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Include all c headers that should be exposed to swift 3 | // 4 | 5 | // include opengl C calls 6 | #import 7 | #import 8 | #import 9 | #import 10 | 11 | // include IOKit/HID 12 | #import 13 | 14 | // include platform layer header 15 | #import "handmadeSrc/handmade_platform.h" 16 | 17 | // include the obj shims 18 | #import "ObjCShim.h" 19 | 20 | // include dylib handling code 21 | #import -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Helpers.swift 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/25/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | class Helpers { 10 | 11 | class func kilobytes(m: uint64) -> uint64 { 12 | return m * 1024 13 | } 14 | 15 | class func megabytes(m: uint64) -> uint64 { 16 | return kilobytes(m) * 1024 17 | } 18 | 19 | class func gigabytes(m: uint64) -> uint64 { 20 | return megabytes(m) * 1024 21 | } 22 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSXTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.handmadehero.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSXTests/Handmade_Hero_OSXTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Handmade_Hero_OSXTests.swift 3 | // Handmade Hero OSXTests 4 | // 5 | // Created by Karl Kirch on 12/28/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import XCTest 11 | 12 | class Handmade_Hero_OSXTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Handmade Hero OSX 4 | // 5 | // Created by Karl Kirch on 12/28/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | @IBOutlet weak var window: NSWindow! 15 | @IBOutlet weak var gameView: GameView! 16 | 17 | 18 | func applicationDidFinishLaunching(aNotification: NSNotification) { 19 | // Insert code here to initialize your application 20 | window.aspectRatio = window.frame.size; 21 | } 22 | 23 | func applicationWillTerminate(aNotification: NSNotification) { 24 | // Insert code here to tear down your application 25 | } 26 | 27 | func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool { 28 | return true 29 | } 30 | 31 | 32 | func applicationDidBecomeActive(notification: NSNotification) { 33 | gameView.setAppIsActive(true) 34 | } 35 | 36 | func applicationDidResignActive(notification: NSNotification) { 37 | gameView.setAppIsActive(false) 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "512x512", 45 | "idiom" : "mac", 46 | "filename" : "hmhero512x512.jpeg", 47 | "scale" : "1x" 48 | }, 49 | { 50 | "idiom" : "mac", 51 | "size" : "512x512", 52 | "scale" : "2x" 53 | } 54 | ], 55 | "info" : { 56 | "version" : 1, 57 | "author" : "xcode" 58 | } 59 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.handmadehero.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2014 Handmade Hero. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Handmade Hero Swift Cocoa Platform Layer 2 | 3 | This is an ongoing OSX version of a platform layer for Casey Muratori's Handmade Hero. 4 | 5 | The goal is to be able to drop in Casey's platform independent game source code and compile and run it unchanged. 6 | 7 | ###Xcode 8 | I'm using xcode 6.1.1 on OSX 10.9.5. This targets 10.9 using the OSX 10.10 SDK. 9 | 10 | ###dylib support 11 | The platform independent layer is wrapped up in a dylib and is loaded dynamically by the platform layer. This allows the code to be reloaded at runtime by simply building the dylib. Due to the way xcode projects work, this is as simple as building the main project (⌘-b or ⌘-⏎-b). 12 | 13 | Ultimately how this works is the main project has the dylib as a compile dependency. A copy files build phase is setup to copy the dylib (once built) into the frameworks folder of our resulting app. The platform layer looks for this the dylib at runtime and checks to see whether the dylib has been updated. If it has been updated, it reloads the dylib. 14 | 15 | ###Game input 16 | Right now this just supports keyboard input but has the beginnings of controller support (turns out this is just super messy on OSX). 17 | 18 | As of right now, the controls are wasd for movement and you can also press the up arrow to speed up movement. 19 | 20 | To connect to the game initially, press the space bar. 21 | 22 | ###Swift ObjC shim 23 | So Swift is nice and all, but any API that takes a function pointer or needs to invoke the function behind a function pointer cannot be implemented in Swift. This is just a limitation of the language. So what you will find in this code is an ObjcShim file which is where anything that can't be done in Swift will reside. Some of these things just forward calls from the objc shim back in to the Swift layer, others will be invoked by the Swift layer to forward calls from the Swift layer into the platform independent layer. 24 | 25 | ####IMPORTANT 26 | 27 | I removed Casey's platform-independent game code from this repository. At the moment that is just handmade*.cpp and handmade*.h files. 28 | 29 | Once you clone or update from this repository, copy over the handmade .cpp/.h files from Casey's source code into the handmadeSrc folder (don't copy the platform layer files, just the platform independent files). 30 | You also need to copy over the assets into the handmadeAssets folder. For this copy the entire contents of the assets zip into the assets folder (should end up with a handmadeAssets/test/*.bmp folder structure) 31 | 32 | This repository works with Casey's handmade*.cpp/handmade*.h files from handmade_hero_050_source. 33 | 34 | ####Author 35 | 36 | Karl Kirch 37 | 38 | Handmade Hero is being created by Casey Muratori. 39 | 40 | You can find more information about Handmade Hero at: http://handmadehero.org 41 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/GameCodeLoader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameCode.swift 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/26/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class GameCodeLoader { 12 | var gameUpdateAndRenderFn = CFunctionPointer.null() 13 | var gameGetSoundSamplesFn = CFunctionPointer.null() 14 | var isInitialized = false 15 | let dylibPath: String 16 | var lastLoadTime = NSDate() 17 | var dylibRef = UnsafeMutablePointer.null() 18 | 19 | init() { 20 | let frameworksPath = NSBundle.mainBundle().privateFrameworksPath 21 | let dylibName = "libHandmade Hero Dylib.dylib" 22 | dylibPath = frameworksPath! + "/" + dylibName 23 | } 24 | 25 | func reloadGameCodeIfNeeded() -> Bool { 26 | if (!isInitialized) { 27 | NSLog("ERROR: Must call loadGameCode before calling reloadGameCodeIfNeeded") 28 | abort() 29 | } 30 | 31 | var err = NSErrorPointer() 32 | var attributes = NSFileManager.defaultManager().attributesOfItemAtPath(dylibPath, error: err) 33 | if (attributes == nil) { 34 | return false 35 | } 36 | var currentLoadTime = attributes![NSFileModificationDate]! as NSDate 37 | if (currentLoadTime.compare(lastLoadTime) == NSComparisonResult.OrderedDescending) { 38 | // ie currentLoadTime > lastLoadTime 39 | lastLoadTime = currentLoadTime 40 | unloadGameCode() 41 | return loadGameCode() 42 | } else { 43 | return false 44 | } 45 | } 46 | 47 | func loadGameCode() -> Bool { 48 | var didLoadCorrectly = false 49 | 50 | dylibRef = dlopen(dylibPath, RTLD_LAZY | RTLD_LOCAL) 51 | if (dylibRef != UnsafeMutablePointer.null()) { 52 | gameUpdateAndRenderFn = unsafeBitCast(dlsym(dylibRef, "GameUpdateAndRender"), CFunctionPointer.self) 53 | gameGetSoundSamplesFn = unsafeBitCast(dlsym(dylibRef, "GameGetSoundSamples"), CFunctionPointer.self) 54 | 55 | if (gameUpdateAndRenderFn != CFunctionPointer.null() 56 | && gameGetSoundSamplesFn != CFunctionPointer.null()) { 57 | didLoadCorrectly = true 58 | } 59 | } 60 | 61 | if (didLoadCorrectly) { 62 | NSLog("Successfully loaded game code") 63 | isInitialized = true 64 | } else { 65 | unloadGameCode() 66 | NSLog("WARNING: Failed to load game code") 67 | } 68 | return isInitialized 69 | } 70 | 71 | func unloadGameCode() { 72 | isInitialized = false 73 | 74 | if (dylibRef != UnsafeMutablePointer.null()) { 75 | dlclose(dylibRef) 76 | dylibRef = UnsafeMutablePointer.null() 77 | } 78 | 79 | // null out our pointers for good measure... 80 | gameUpdateAndRenderFn = CFunctionPointer.null() 81 | gameGetSoundSamplesFn = CFunctionPointer.null() 82 | } 83 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/PlatformLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlatformLayer.swift 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/26/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class PlatformLayer { 12 | 13 | // uninitialized pointers to our platform layer memory 14 | var gameMemory = UnsafeMutablePointer.alloc(1) 15 | var gameInput = UnsafeMutablePointer.alloc(1) 16 | var gameOffscreenBuffer = UnsafeMutablePointer.alloc(1) 17 | var gameThreadContext = UnsafeMutablePointer.null() 18 | 19 | // game code loader 20 | private var gameCodeLoader = GameCodeLoader() 21 | 22 | // input manager 23 | private let inputManager: InputManager 24 | private let soundManager = SoundManager() 25 | 26 | init(anInputManager: InputManager) { 27 | inputManager = anInputManager 28 | 29 | // initialize all of our memory 30 | let permanantStorageSize = Helpers.megabytes(64) 31 | let TransientStorageSize = Helpers.gigabytes(1) 32 | gameMemory.memory.PermanentStorageSize = permanantStorageSize 33 | gameMemory.memory.TransientStorageSize = TransientStorageSize 34 | gameMemory.memory.PermanentStorage = UnsafeMutablePointer.alloc(Int(permanantStorageSize)) 35 | gameMemory.memory.TransientStorage = UnsafeMutablePointer.alloc(Int(TransientStorageSize)) 36 | gameMemory.memory.DEBUGPlatformFreeFileMemory = getFreeFileFn() 37 | gameMemory.memory.DEBUGPlatformReadEntireFile = getReadFileFn() 38 | gameMemory.memory.DEBUGPlatformWriteEntireFile = getWriteFileFn() 39 | 40 | gameOffscreenBuffer.memory.Width = 960 /*magic value*/ 41 | gameOffscreenBuffer.memory.Height = 540 /*magic value*/ 42 | gameOffscreenBuffer.memory.BytesPerPixel = 4 /*magic value*/ 43 | gameOffscreenBuffer.memory.Pitch = gameOffscreenBuffer.memory.Width * gameOffscreenBuffer.memory.BytesPerPixel 44 | 45 | var totalBufferSize = gameOffscreenBuffer.memory.Pitch * gameOffscreenBuffer.memory.Height 46 | gameOffscreenBuffer.memory.Memory = UnsafeMutablePointer.alloc(Int(totalBufferSize)) 47 | 48 | // load our dylib game code 49 | gameCodeLoader.loadGameCode() 50 | } 51 | 52 | func platformGameUpdateAndRender(targetFrameTime: real32) { 53 | // reload our dylib if it's changed 54 | gameCodeLoader.reloadGameCodeIfNeeded() 55 | 56 | // update input state 57 | inputManager.updateInputState(gameInput) 58 | 59 | // have to do this every frame because of me copying over all of the input state :/ 60 | // TODO: get this value from display link 61 | gameInput.memory.dtForFrame = targetFrameTime 62 | 63 | // sanity check 64 | if (gameCodeLoader.isInitialized) { 65 | // run function pointer in objc b/c swift can't call function pointers o_0 66 | shimCallGameUpdateAndRenderFn(gameCodeLoader.gameUpdateAndRenderFn, gameThreadContext, gameMemory, gameInput, gameOffscreenBuffer) 67 | 68 | // delegate sound handling to sound manager 69 | soundManager.updateAudioBuffer(gameCodeLoader.gameGetSoundSamplesFn, threadContext: gameThreadContext, gameMemory: gameMemory) 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/ObjCShim.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjcShim.h 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/23/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | #ifndef Handmade_Hero_Swift_Platform_DisplayLinkShim_h 10 | #define Handmade_Hero_Swift_Platform_DisplayLinkShim_h 11 | 12 | #import 13 | #import 14 | #import 15 | #include "handmade_platform.h" 16 | 17 | // Display link shims 18 | CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, 19 | const CVTimeStamp *outputTime, CVOptionFlags flagsIn, 20 | CVOptionFlags *flagsOut, void *displayLinkContext); 21 | CVDisplayLinkOutputCallback getDisplayLinkCallback(); 22 | 23 | // Core Audio shims 24 | OSStatus coreAudioCallback(void* inRefCon, 25 | AudioUnitRenderActionFlags* ioActionFlags, 26 | const AudioTimeStamp* inTimeStamp, 27 | UInt32 inBusNumber, 28 | UInt32 inNumberFrames, 29 | AudioBufferList* ioData); 30 | AURenderCallback getCoreAudioCallback(); 31 | 32 | // Platform indepent layer shims 33 | void shimCallGameUpdateAndRenderFn(game_update_and_render fn, 34 | thread_context* threadContext, 35 | game_memory* memory, 36 | game_input* input, 37 | game_offscreen_buffer* buffer); 38 | 39 | void shimCallGameGetSoundSamplesFn(game_get_sound_samples fn, 40 | thread_context* threadContext, 41 | game_memory* memory, 42 | game_sound_output_buffer* buffer); 43 | 44 | // HID lib shims 45 | void hidDeviceAdded(void* context, IOReturn result, void* sender, IOHIDDeviceRef device); 46 | void hidDeviceRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device); 47 | void hidDeviceAction(void* context, IOReturn result, void* sender, IOHIDValueRef value); 48 | IOHIDDeviceCallback getHidDeviceAddedCallback(); 49 | IOHIDDeviceCallback getHidDeviceRemovedCallback(); 50 | IOHIDValueCallback getHidDeviceActionCallback(); 51 | 52 | // game_controller_input shim due to lack of union support in swift :/ 53 | typedef struct game_controller_input_shim { 54 | bool32 IsConnected; 55 | bool32 IsAnalog; 56 | real32 StickAverageX; 57 | real32 StickAverageY; 58 | game_button_state MoveUp; 59 | game_button_state MoveDown; 60 | game_button_state MoveLeft; 61 | game_button_state MoveRight; 62 | 63 | game_button_state ActionUp; 64 | game_button_state ActionDown; 65 | game_button_state ActionLeft; 66 | game_button_state ActionRight; 67 | 68 | game_button_state LeftShoulder; 69 | game_button_state RightShoulder; 70 | 71 | game_button_state Back; 72 | game_button_state Start; 73 | 74 | // NOTE(casey): All buttons must be added above this line 75 | 76 | game_button_state Terminator; 77 | } game_controller_input_shim; 78 | 79 | game_controller_input_shim * unsafeControllerInputCast(game_input * input, int controller); 80 | 81 | // Get debug file read callbacks 82 | debug_platform_read_entire_file* getReadFileFn(); 83 | debug_platform_write_entire_file* getWriteFileFn(); 84 | debug_platform_free_file_memory* getFreeFileFn(); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/SoundManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SoundManager.swift 3 | // Handmade Hero OSX 4 | // 5 | // Created by Karl Kirch on 12/31/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AudioUnit 11 | 12 | @objc class SoundManager { 13 | 14 | // sound buffer that the game will use 15 | private let soundBuffer = UnsafeMutablePointer.alloc(1) 16 | 17 | // Lock for synchronizing between core audio thread and other threads 18 | private let audioLock = NSLock() 19 | 20 | init() { 21 | let samplesPerSec = 4800 22 | let bytesPerSample = sizeof(int16) * 2 23 | let numberOfSamples = bytesPerSample * samplesPerSec 24 | soundBuffer.memory.SamplesPerSecond = int32(samplesPerSec) 25 | soundBuffer.memory.SampleCount = 0 26 | soundBuffer.memory.Samples = UnsafeMutablePointer.alloc(numberOfSamples) 27 | 28 | // init core audio 29 | let audioComponentDescription = UnsafeMutablePointer.alloc(1) 30 | audioComponentDescription.memory.componentType = OSType(kAudioUnitType_Output) 31 | audioComponentDescription.memory.componentSubType = OSType(kAudioUnitSubType_DefaultOutput) 32 | audioComponentDescription.memory.componentManufacturer = OSType(kAudioUnitManufacturer_Apple) 33 | 34 | let outputComponent = AudioComponentFindNext(nil, audioComponentDescription) 35 | let audioUnit = UnsafeMutablePointer.alloc(1) 36 | 37 | AudioComponentInstanceNew(outputComponent, audioUnit) 38 | AudioUnitInitialize(audioUnit.memory) 39 | 40 | let audioStreamBasicDescription = UnsafeMutablePointer.alloc(1) 41 | audioStreamBasicDescription.memory.mSampleRate = Float64(soundBuffer.memory.SamplesPerSecond) 42 | audioStreamBasicDescription.memory.mFormatID = AudioFormatID(kAudioFormatLinearPCM) 43 | audioStreamBasicDescription.memory.mFormatFlags = AudioFormatFlags(kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked) 44 | audioStreamBasicDescription.memory.mChannelsPerFrame = 2 45 | audioStreamBasicDescription.memory.mBitsPerChannel = 16 46 | audioStreamBasicDescription.memory.mBytesPerPacket = 4 47 | audioStreamBasicDescription.memory.mBytesPerFrame = 4 48 | 49 | AudioUnitSetProperty(audioUnit.memory, AudioUnitPropertyID(kAudioUnitProperty_StreamFormat), AudioUnitScope(kAudioUnitScope_Input), 0, audioStreamBasicDescription, UInt32(sizeof(AudioStreamBasicDescription))) 50 | 51 | let caContext = unsafeBitCast(self, UnsafeMutablePointer.self) 52 | let audioUnitCallbacks = UnsafeMutablePointer.alloc(1) 53 | audioUnitCallbacks.memory.inputProc = getCoreAudioCallback() 54 | audioUnitCallbacks.memory.inputProcRefCon = caContext 55 | 56 | AudioUnitSetProperty(audioUnit.memory, AudioUnitPropertyID(kAudioUnitProperty_SetRenderCallback), AudioUnitScope(kAudioUnitScope_Global), 0, audioUnitCallbacks, UInt32(sizeof(AURenderCallbackStruct))) 57 | 58 | //AudioOutputUnitStart(audioUnit.memory); 59 | } 60 | 61 | func updateAudioBuffer(sampleGameAudioFn: CFunctionPointer, threadContext: UnsafeMutablePointer, gameMemory: UnsafeMutablePointer) { 62 | audioLock.lock() 63 | shimCallGameGetSoundSamplesFn(sampleGameAudioFn, threadContext, gameMemory, soundBuffer) 64 | audioLock.unlock() 65 | } 66 | 67 | func coreAudioCallback(inRefCon: UnsafeMutablePointer, ioActionFlags: UnsafeMutablePointer, inTimeStamp: UnsafePointer, inBusNumber: UInt32, inNumberFrames: UInt32, ioData: UnsafeMutablePointer) -> OSStatus{ 68 | 69 | audioLock.lock() 70 | 71 | audioLock.unlock() 72 | return noErr 73 | } 74 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/ObjCShim.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCShim.m 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/23/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | #import "ObjCShim.h" 10 | 11 | // Imports the generated bridge from objc to swift 12 | // This is available after setting Defines Module to YES in the Build Settings for the project 13 | #import "Handmade_Hero_OSX-Swift.h" 14 | 15 | CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, 16 | const CVTimeStamp *outputTime, CVOptionFlags flagsIn, 17 | CVOptionFlags *flagsOut, void *displayLinkContext) 18 | { 19 | // wrap our call to swift in an autorelease pool because the cvdisplaylink thread doesn't 20 | // have an autorelease pool by default 21 | @autoreleasepool { 22 | [(__bridge GameView*)displayLinkContext getFrame:outputTime]; 23 | } 24 | 25 | return kCVReturnSuccess; 26 | } 27 | 28 | CVDisplayLinkOutputCallback getDisplayLinkCallback() 29 | { 30 | return displayLinkCallback; 31 | } 32 | 33 | OSStatus coreAudioCallback(void* inRefCon, 34 | AudioUnitRenderActionFlags* ioActionFlags, 35 | const AudioTimeStamp* inTimeStamp, 36 | UInt32 inBusNumber, 37 | UInt32 inNumberFrames, 38 | AudioBufferList* ioData) 39 | { 40 | return [(__bridge SoundManager*)inRefCon coreAudioCallback:inRefCon ioActionFlags:ioActionFlags inTimeStamp:inTimeStamp inBusNumber:inBusNumber inNumberFrames:inNumberFrames ioData:ioData]; 41 | } 42 | 43 | AURenderCallback getCoreAudioCallback() 44 | { 45 | return coreAudioCallback; 46 | } 47 | 48 | void shimCallGameUpdateAndRenderFn(game_update_and_render fn, 49 | thread_context* threadContext, 50 | game_memory* memory, 51 | game_input* input, 52 | game_offscreen_buffer* buffer) 53 | { 54 | fn(threadContext, memory, input, buffer); 55 | } 56 | 57 | void shimCallGameGetSoundSamplesFn(game_get_sound_samples fn, 58 | thread_context* threadContext, 59 | game_memory* memory, 60 | game_sound_output_buffer* buffer) 61 | { 62 | fn(threadContext, memory, buffer); 63 | } 64 | 65 | void hidDeviceAdded(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) 66 | { 67 | [(__bridge InputManager*)context hidDeviceAdded:context result:result sender:sender device:device]; 68 | } 69 | 70 | void hidDeviceRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) 71 | { 72 | [(__bridge InputManager*)context hidDeviceRemoved:context result:result sender:sender device:device]; 73 | } 74 | 75 | void hidDeviceAction(void* context, IOReturn result, void* sender, IOHIDValueRef value) 76 | { 77 | [(__bridge InputManager*)context hidDeviceAction:context result:result sender:sender value:value]; 78 | } 79 | 80 | IOHIDDeviceCallback getHidDeviceAddedCallback() 81 | { 82 | return hidDeviceAdded; 83 | } 84 | 85 | IOHIDDeviceCallback getHidDeviceRemovedCallback() 86 | { 87 | return hidDeviceRemoved; 88 | } 89 | 90 | IOHIDValueCallback getHidDeviceActionCallback() 91 | { 92 | return hidDeviceAction; 93 | } 94 | 95 | game_controller_input_shim * unsafeControllerInputCast(game_input * input, int controller) 96 | { 97 | return (game_controller_input_shim *) &input->Controllers[controller]; 98 | } 99 | 100 | // TODO write all this in swift and shim it 101 | DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUGPlatformFreeFileMemory) 102 | { 103 | if (Memory) 104 | { 105 | free(Memory); 106 | } 107 | } 108 | 109 | // TODO write all this in swift and shim it 110 | DEBUG_PLATFORM_READ_ENTIRE_FILE(DEBUGPlatformReadEntireFile) 111 | { 112 | debug_read_file_result Result = {}; 113 | 114 | NSString *frameworksPath = [[NSBundle mainBundle] resourcePath]; 115 | NSString *filePath = [NSString stringWithFormat:@"%@/%s", frameworksPath, Filename]; 116 | 117 | int fd = open([filePath cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY); 118 | if (fd != -1) 119 | { 120 | struct stat fileStat; 121 | if (fstat(fd, &fileStat) == 0) 122 | { 123 | uint32 FileSize32 = fileStat.st_size; 124 | 125 | kern_return_t result = vm_allocate((vm_map_t)mach_task_self(), 126 | (vm_address_t*)&Result.Contents, 127 | FileSize32, 128 | VM_FLAGS_ANYWHERE); 129 | if ((result == KERN_SUCCESS) && Result.Contents) 130 | { 131 | ssize_t BytesRead; 132 | BytesRead = read(fd, Result.Contents, FileSize32); 133 | if (BytesRead == FileSize32) // should have read until EOF 134 | { 135 | Result.ContentsSize = FileSize32; 136 | } 137 | else 138 | { 139 | DEBUGPlatformFreeFileMemory(Thread, Result.Contents); 140 | Result.Contents = 0; 141 | } 142 | } 143 | else 144 | { 145 | printf("DEBUGPlatformReadEntireFile %s: vm_allocate error: %d: %s\n", 146 | Filename, errno, strerror(errno)); 147 | } 148 | } 149 | else 150 | { 151 | printf("DEBUGPlatformReadEntireFile %s: fstat error: %d: %s\n", 152 | Filename, errno, strerror(errno)); 153 | } 154 | 155 | close(fd); 156 | } 157 | else 158 | { 159 | printf("DEBUGPlatformReadEntireFile %s: open error: %d: %s\n", 160 | Filename, errno, strerror(errno)); 161 | } 162 | 163 | return Result; 164 | } 165 | 166 | // TODO write all this in swift and shim it 167 | DEBUG_PLATFORM_WRITE_ENTIRE_FILE(DEBUGPlatformWriteEntireFile) 168 | { 169 | bool32 Result = false; 170 | 171 | NSString *frameworksPath = [[NSBundle mainBundle] resourcePath]; 172 | NSString *filePath = [NSString stringWithFormat:@"%@/%s", frameworksPath, Filename]; 173 | 174 | int fd = open([filePath cStringUsingEncoding:NSUTF8StringEncoding], O_WRONLY | O_CREAT, 0644); 175 | if (fd != -1) 176 | { 177 | ssize_t BytesWritten = write(fd, Memory, MemorySize); 178 | Result = (BytesWritten == MemorySize); 179 | 180 | if (!Result) 181 | { 182 | 183 | } 184 | 185 | close(fd); 186 | } 187 | else 188 | { 189 | } 190 | 191 | return Result; 192 | } 193 | 194 | debug_platform_read_entire_file* getReadFileFn() 195 | { 196 | return DEBUGPlatformReadEntireFile; 197 | } 198 | 199 | debug_platform_write_entire_file* getWriteFileFn() 200 | { 201 | return DEBUGPlatformWriteEntireFile; 202 | } 203 | 204 | debug_platform_free_file_memory* getFreeFileFn() 205 | { 206 | return DEBUGPlatformFreeFileMemory; 207 | } 208 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/InputManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputManager.swift 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/27/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | @objc class InputManager { 12 | 13 | // lock for thread safety 14 | private let inputLock = NSLock() 15 | 16 | // local copy of input 17 | private var input = UnsafeMutablePointer.alloc(1) 18 | 19 | private var hidManager: Unmanaged 20 | 21 | var shouldProcessInput = true 22 | 23 | init() { 24 | //assume keyboard always connected 25 | input.memory.Controllers.0.IsConnected = 1 26 | 27 | hidManager = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone)); 28 | 29 | let hidContext = unsafeBitCast(self, UnsafeMutablePointer.self) 30 | let hidManagerVal = hidManager.takeUnretainedValue(); 31 | // device types we want to monitor 32 | let deviceCriteria = [ 33 | [ 34 | kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop, 35 | kIOHIDDeviceUsageKey: kHIDUsage_GD_Joystick 36 | ], 37 | [ 38 | kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop, 39 | kIOHIDDeviceUsageKey: kHIDUsage_GD_GamePad 40 | ], 41 | [ 42 | kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop, 43 | kIOHIDDeviceUsageKey: kHIDUsage_GD_MultiAxisController 44 | ], 45 | [ 46 | kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop, 47 | kIOHIDDeviceUsageKey: kHIDUsage_GD_Keyboard 48 | ] 49 | ] 50 | IOHIDManagerSetDeviceMatchingMultiple(hidManagerVal, deviceCriteria) 51 | IOHIDManagerRegisterDeviceMatchingCallback(hidManagerVal, getHidDeviceAddedCallback(), hidContext); 52 | IOHIDManagerRegisterDeviceRemovalCallback(hidManagerVal, getHidDeviceRemovedCallback(), hidContext); 53 | IOHIDManagerScheduleWithRunLoop(hidManagerVal, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode) 54 | IOHIDManagerOpen(hidManagerVal, IOOptionBits(kIOHIDOptionsTypeNone)) 55 | IOHIDManagerRegisterInputValueCallback(hidManagerVal, getHidDeviceActionCallback(), hidContext); 56 | } 57 | 58 | func updateInputState(inputPtr: UnsafeMutablePointer) { 59 | inputLock.lock() 60 | memcpy(inputPtr, input, UInt(sizeof(game_input))) 61 | inputLock.unlock() 62 | } 63 | 64 | func hidDeviceAdded(context: UnsafeMutablePointer, result: IOReturn, sender: UnsafeMutablePointer, device: IOHIDDevice) { 65 | var manufacturer = "Unknown" 66 | // let mfnTypeRef: AnyObject = IOHIDDeviceGetProperty(device, kIOHIDManufacturerKey).takeUnretainedValue() 67 | // if (unsafeBitCast(mfnTypeRef, CFStringRef.self) != nil) { 68 | // manufacturer = unsafeBitCast(mfnTypeRef, CFStringRef.self) as String 69 | // } 70 | 71 | var product = "Unknown" 72 | let prodTypeRef: AnyObject = IOHIDDeviceGetProperty(device, kIOHIDProductKey).takeUnretainedValue() 73 | if (unsafeBitCast(prodTypeRef, CFStringRef.self) != nil) { 74 | product = unsafeBitCast(prodTypeRef, CFStringRef.self) as String 75 | } 76 | 77 | NSLog("Device added %@ %@", manufacturer, product) 78 | } 79 | 80 | func hidDeviceRemoved(context: UnsafeMutablePointer, result: IOReturn, sender: UnsafeMutablePointer, device: IOHIDDevice) { 81 | var manufacturer = "Unknown" 82 | // let mfnTypeRef: AnyObject = IOHIDDeviceGetProperty(device, kIOHIDManufacturerKey).takeUnretainedValue() 83 | // if (unsafeBitCast(mfnTypeRef, CFStringRef.self) != nil) { 84 | // manufacturer = unsafeBitCast(mfnTypeRef, CFStringRef.self) as String 85 | // } 86 | 87 | var product = "Unknown" 88 | let prodTypeRef: AnyObject = IOHIDDeviceGetProperty(device, kIOHIDProductKey).takeUnretainedValue() 89 | if (unsafeBitCast(prodTypeRef, CFStringRef.self) != nil) { 90 | product = unsafeBitCast(prodTypeRef, CFStringRef.self) as String 91 | } 92 | 93 | NSLog("Device removed %@ %@", manufacturer, product) 94 | } 95 | 96 | func hidDeviceAction(context: UnsafeMutablePointer, result: IOReturn, sender: UnsafeMutablePointer, value: IOHIDValueRef) { 97 | // make sure we should actually record our input 98 | // TODO: this should probably be more than a boolean 99 | // so that we can reset all input on window inactive 100 | if (!shouldProcessInput) { 101 | return 102 | } 103 | 104 | // PS3 controllers report bogus values 105 | // just throw them away 106 | // via itfrombit 107 | // https://github.com/itfrombit/osx_handmade/blob/master/Handmade%20Hero/HandmadeView.mm#L336-L337 108 | if (IOHIDValueGetLength(value) > 2) 109 | { 110 | //NSLog("OSXHIDAction: value length > 2: %ld", IOHIDValueGetLength(value)); 111 | return 112 | } 113 | 114 | inputLock.lock() 115 | 116 | let element = IOHIDValueGetElement(value) 117 | let elementValue = IOHIDValueGetIntegerValue(value); 118 | let usagePage = Int(IOHIDElementGetUsagePage(element.takeUnretainedValue())) 119 | let usage = Int(IOHIDElementGetUsage(element.takeUnretainedValue())) 120 | 121 | switch(usagePage) { 122 | case kHIDPage_KeyboardOrKeypad: 123 | handleKeyboardInput(usage, isDown: elementValue == 1); 124 | break 125 | default: 126 | if (usage == 0x01 || (usage >= 0x30 && usage <= 0x35)) { 127 | break 128 | } 129 | NSLog("Unhandled usagePage %02x usage %02x val %02x", usagePage, usage, elementValue) 130 | break 131 | } 132 | 133 | inputLock.unlock() 134 | } 135 | 136 | private func handleKeyboardInput(usage: Int, isDown: Bool) { 137 | // get a non-unioned version of our controller input 138 | // (this is because Swift doesn't handle c structs with unions :/ 139 | var controllerInput = unsafeControllerInputCast(input, 0) 140 | 141 | let endedDownVal = bool32(isDown ? 1 : 0) 142 | 143 | switch(usage) { 144 | case kHIDUsage_KeyboardA: 145 | controllerInput.memory.MoveLeft.EndedDown = endedDownVal 146 | break 147 | case kHIDUsage_KeyboardW: 148 | controllerInput.memory.MoveUp.EndedDown = endedDownVal 149 | break 150 | case kHIDUsage_KeyboardS: 151 | controllerInput.memory.MoveDown.EndedDown = endedDownVal 152 | break 153 | case kHIDUsage_KeyboardD: 154 | controllerInput.memory.MoveRight.EndedDown = endedDownVal 155 | break 156 | case kHIDUsage_KeyboardLeftArrow: 157 | controllerInput.memory.ActionLeft.EndedDown = endedDownVal 158 | break 159 | case kHIDUsage_KeyboardRightArrow: 160 | controllerInput.memory.ActionRight.EndedDown = endedDownVal 161 | break 162 | case kHIDUsage_KeyboardUpArrow: 163 | controllerInput.memory.ActionUp.EndedDown = endedDownVal 164 | break 165 | case kHIDUsage_KeyboardDownArrow: 166 | controllerInput.memory.ActionDown.EndedDown = endedDownVal 167 | break 168 | case kHIDUsage_KeyboardQ: 169 | controllerInput.memory.LeftShoulder.EndedDown = endedDownVal 170 | break 171 | case kHIDUsage_KeyboardE: 172 | controllerInput.memory.RightShoulder.EndedDown = endedDownVal 173 | break 174 | case kHIDUsage_KeyboardEscape: 175 | controllerInput.memory.Back.EndedDown = endedDownVal 176 | break 177 | case kHIDUsage_KeyboardSpacebar: 178 | controllerInput.memory.Start.EndedDown = endedDownVal 179 | break 180 | 181 | default: 182 | return 183 | } 184 | } 185 | } -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX/GameView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameView.swift 3 | // Handmade Hero Swift Platform 4 | // 5 | // Created by Karl Kirch on 12/23/14. 6 | // Copyright (c) 2014 Handmade Hero. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import CoreVideo 11 | 12 | @objc class GameView: NSOpenGLView { 13 | 14 | // opengl defines 15 | // textureId that we'll use to store reference to our opengl texture 16 | var textureId: GLuint = GLuint() 17 | // pixel format attributes 18 | let pixelFormatAttrsBestCase: [NSOpenGLPixelFormatAttribute] = [ 19 | UInt32(NSOpenGLPFADoubleBuffer), 20 | UInt32(NSOpenGLPFAAccelerated), 21 | UInt32(NSOpenGLPFADepthSize), UInt32(24), 22 | UInt32(0) 23 | ] 24 | let pixelFormatAttrsFallbackCase: [NSOpenGLPixelFormatAttribute] = [ 25 | UInt32(NSOpenGLPFADepthSize), UInt32(24), 26 | UInt32(0) 27 | ] 28 | // list of vertices we'll use for defining our triangles 29 | let vertices: [GLfloat] = [ 30 | -1, -1, 0, 31 | -1, 1, 0, 32 | 1, 1, 0, 33 | 1, -1, 0, 34 | ] 35 | // list of coordinates that we'll bind our texture to 36 | let texCoords: [GLfloat] = [ 37 | 0, 1, 38 | 0, 0, 39 | 1, 0, 40 | 1, 1, 41 | ] 42 | // list of vertices to be used to draw triangles 43 | let triangleIndices: [GLushort] = [ 0, 1, 2, 0, 2, 3 ] 44 | 45 | 46 | // pointer to an uninitialized CVDisplayLinkRef 47 | var displayLink = UnsafeMutablePointer?>.alloc(1) 48 | 49 | let inputManager = InputManager() 50 | 51 | var platformLayer: PlatformLayer 52 | 53 | var targetFrameTime: real32 = 0 54 | 55 | required init?(coder: NSCoder) { 56 | platformLayer = PlatformLayer(anInputManager: inputManager) 57 | super.init(coder: coder) 58 | } 59 | 60 | override func awakeFromNib() { 61 | var pf = NSOpenGLPixelFormat(attributes: pixelFormatAttrsBestCase) 62 | if (pf == nil) { 63 | NSLog("Couldn't init opengl the way we wanted, using fallback") 64 | pf = NSOpenGLPixelFormat(attributes: pixelFormatAttrsFallbackCase) 65 | } 66 | if (pf == nil) { 67 | NSLog("Couldn't init opengl at all, sorry :(") 68 | abort() 69 | } 70 | let glContext = NSOpenGLContext(format: pf, shareContext: nil) 71 | self.pixelFormat = pf 72 | self.openGLContext = glContext 73 | } 74 | 75 | override func prepareOpenGL() { 76 | super.prepareOpenGL() 77 | 78 | // make current context for use 79 | openGLContext.makeCurrentContext() 80 | 81 | // lock context just in case something else is using it (shouldn't be though) 82 | CGLLockContext(openGLContext.CGLContextObj) 83 | 84 | // setup opengl defaults 85 | glDisable(GLenum(GL_DEPTH_TEST)) 86 | glLoadIdentity() 87 | 88 | // setup viewport for opengl 89 | glViewport(0, 0, platformLayer.gameOffscreenBuffer.memory.Width, platformLayer.gameOffscreenBuffer.memory.Height); 90 | 91 | // set to use vsync (will default to 60hz in theory) 92 | var vsync = GLint(1) 93 | openGLContext.setValues(&vsync, forParameter:NSOpenGLContextParameter.GLCPSwapInterval) 94 | 95 | // I don't know what this does o_0 96 | glPixelStorei(GLenum(GL_UNPACK_ALIGNMENT), 1) 97 | 98 | // create texture for later so we can draw into it 99 | glGenTextures(1, &textureId) 100 | glBindTexture(GLenum(GL_TEXTURE_2D), textureId) 101 | 102 | // clear texture initially to get rid of junk from previous memory 103 | glTexImage2D( 104 | GLenum(GL_TEXTURE_2D), 105 | GLint(0), 106 | GLint(GL_RGBA), 107 | GLsizei(platformLayer.gameOffscreenBuffer.memory.Width), GLsizei(platformLayer.gameOffscreenBuffer.memory.Height), 108 | GLint(0), 109 | GLenum(GL_BGRA), 110 | GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), UnsafePointer.null()) 111 | 112 | // setup texture modes 113 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_NEAREST) 114 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_NEAREST) 115 | glTexEnvi(GLenum(GL_TEXTURE_ENV), GLenum(GL_TEXTURE_ENV_MODE), GL_REPLACE) 116 | 117 | // release lock on the opengl context 118 | CGLUnlockContext(openGLContext.CGLContextObj) 119 | 120 | // create displaylink and store in displayLink pointer 121 | CVDisplayLinkCreateWithActiveCGDisplays(displayLink) 122 | 123 | // get reference to displayLink memory now it's been created 124 | var displayLinkRef: CVDisplayLinkRef? = displayLink.memory?.takeUnretainedValue() 125 | 126 | // setup displaylink callback 127 | // need to create an UnsafeMutablePointer by using an unsafeBitCast 128 | let dlContext = unsafeBitCast(self, UnsafeMutablePointer.self) 129 | // call shim to get the displaylink callback (the shim calls getFrame when fired) 130 | CVDisplayLinkSetOutputCallback(displayLinkRef, getDisplayLinkCallback(), dlContext) 131 | 132 | // setup opengl for displaylink 133 | CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLinkRef, openGLContext.CGLContextObj, pixelFormat!.CGLPixelFormatObj) 134 | 135 | let cvtime = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(displayLinkRef) 136 | targetFrameTime = real32(cvtime.timeValue) / real32(cvtime.timeScale) 137 | 138 | // start the display link 139 | CVDisplayLinkStart(displayLinkRef) 140 | 141 | } 142 | 143 | // callback that our shim will call on cvdisplaylink fire 144 | func getFrame(time: UnsafePointer) { 145 | 146 | // lock the opengl context because the main thread might be drawing 147 | CGLLockContext(openGLContext.CGLContextObj) 148 | 149 | // make current for subsequent opengl calls 150 | openGLContext.makeCurrentContext() 151 | 152 | glClearColor(0x00, 0x00, 0x00, 0xFF) 153 | glClear(GLenum(GL_COLOR_BUFFER_BIT)) 154 | 155 | glVertexPointer(GLint(3), GLenum(GL_FLOAT), GLsizei(0), vertices) 156 | glTexCoordPointer(GLint(2), GLenum(GL_FLOAT), GLsizei(0), texCoords) 157 | 158 | glEnableClientState(GLenum(GL_VERTEX_ARRAY)) 159 | glEnableClientState(GLenum(GL_TEXTURE_COORD_ARRAY)) 160 | 161 | glBindTexture(GLenum(GL_TEXTURE_2D), textureId) 162 | 163 | glEnable(GLenum(GL_TEXTURE_2D)) 164 | 165 | // TODO: update input 166 | 167 | // TODO: call into platform layer to update the game 168 | platformLayer.platformGameUpdateAndRender(targetFrameTime) 169 | 170 | // TODO: update texture and draw to screen 171 | glTexSubImage2D( 172 | GLenum(GL_TEXTURE_2D), 173 | GLint(0), 174 | GLint(0), 175 | GLint(0), 176 | GLsizei(platformLayer.gameOffscreenBuffer.memory.Width), GLsizei(platformLayer.gameOffscreenBuffer.memory.Height), 177 | GLenum(GL_BGRA), 178 | GLenum(GL_UNSIGNED_INT_8_8_8_8_REV), platformLayer.gameOffscreenBuffer.memory.Memory) 179 | 180 | glColor4f(1, 1, 1, 1) 181 | glDrawElements(GLenum(GL_TRIANGLES), GLsizei(6), GLenum(GL_UNSIGNED_SHORT), triangleIndices) 182 | glDisable(GLenum(GL_TEXTURE_2D)) 183 | 184 | glDisableClientState(GLenum(GL_VERTEX_ARRAY)) 185 | glDisableClientState(GLenum(GL_TEXTURE_COORD_ARRAY)) 186 | 187 | glFlush() 188 | 189 | // we're double buffered so need to flush to screen 190 | openGLContext.flushBuffer() 191 | 192 | CGLUnlockContext(openGLContext.CGLContextObj) 193 | } 194 | 195 | // resize the viewport when window size changes 196 | override func reshape() { 197 | // lock the opengl context because the displaylink might be drawing 198 | CGLLockContext(openGLContext.CGLContextObj) 199 | 200 | openGLContext.makeCurrentContext() 201 | 202 | // resize the viewport based on the view's size 203 | glDisable(GLenum(GL_DEPTH_TEST)) 204 | glLoadIdentity() 205 | glViewport(0, 0, GLsizei(bounds.width), GLsizei(bounds.height)) 206 | 207 | glClearColor(0x00, 0x00, 0x00, 0xFF) 208 | glClear(GLenum(GL_COLOR_BUFFER_BIT)) 209 | 210 | // just draw whatever we have cached in the texture here, don't worry about updating the game 211 | glVertexPointer(GLint(3), GLenum(GL_FLOAT), GLsizei(0), vertices) 212 | glTexCoordPointer(GLint(2), GLenum(GL_FLOAT), GLsizei(0), texCoords) 213 | 214 | glEnableClientState(GLenum(GL_VERTEX_ARRAY)) 215 | glEnableClientState(GLenum(GL_TEXTURE_COORD_ARRAY)) 216 | 217 | glBindTexture(GLenum(GL_TEXTURE_2D), textureId) 218 | 219 | glEnable(GLenum(GL_TEXTURE_2D)) 220 | 221 | glColor4f(1, 1, 1, 1) 222 | glDrawElements(GLenum(GL_TRIANGLES), GLsizei(6), GLenum(GL_UNSIGNED_SHORT), triangleIndices) 223 | glDisable(GLenum(GL_TEXTURE_2D)) 224 | 225 | glDisableClientState(GLenum(GL_VERTEX_ARRAY)) 226 | glDisableClientState(GLenum(GL_TEXTURE_COORD_ARRAY)) 227 | 228 | // we're double buffered so need to flush to screen 229 | openGLContext.flushBuffer() 230 | 231 | CGLUnlockContext(openGLContext.CGLContextObj); 232 | } 233 | 234 | 235 | func setAppIsActive(active: Bool) { 236 | inputManager.shouldProcessInput = active 237 | } 238 | 239 | // accept first responder and ignore keyboard events because we handle them in the input manager 240 | func acceptsFirstResponder() -> Bool { 241 | return true; 242 | } 243 | 244 | override func keyDown(theEvent: NSEvent) { 245 | // noop 246 | } 247 | 248 | override func keyUp(theEvent: NSEvent) { 249 | // noop 250 | } 251 | } 252 | 253 | -------------------------------------------------------------------------------- /Handmade Hero Dylib/Handmade Hero Dylib.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CB0192781A6B05C1004638FA /* handmade_math.h in Headers */ = {isa = PBXBuildFile; fileRef = CB0192771A6B05C1004638FA /* handmade_math.h */; }; 11 | CB1FBF661A5F361900B06069 /* handmade_random.h in Headers */ = {isa = PBXBuildFile; fileRef = CB1FBF631A5F361900B06069 /* handmade_random.h */; }; 12 | CB1FBF681A5F361900B06069 /* handmade_tile.h in Headers */ = {isa = PBXBuildFile; fileRef = CB1FBF651A5F361900B06069 /* handmade_tile.h */; }; 13 | CB469B691A50D9450000A950 /* handmade_platform.h in Headers */ = {isa = PBXBuildFile; fileRef = CB469B661A50D9450000A950 /* handmade_platform.h */; }; 14 | CB469B6A1A50D9450000A950 /* handmade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB469B671A50D9450000A950 /* handmade.cpp */; }; 15 | CB469B6B1A50D9450000A950 /* handmade.h in Headers */ = {isa = PBXBuildFile; fileRef = CB469B681A50D9450000A950 /* handmade.h */; }; 16 | CBD97E151A54F237006CCBFB /* handmade_intrinsics.h in Headers */ = {isa = PBXBuildFile; fileRef = CBD97E141A54F237006CCBFB /* handmade_intrinsics.h */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | CB0192771A6B05C1004638FA /* handmade_math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_math.h; path = ../handmadeSrc/handmade_math.h; sourceTree = ""; }; 21 | CB1FBF631A5F361900B06069 /* handmade_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_random.h; path = ../handmadeSrc/handmade_random.h; sourceTree = ""; }; 22 | CB1FBF641A5F361900B06069 /* handmade_tile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = handmade_tile.cpp; path = ../handmadeSrc/handmade_tile.cpp; sourceTree = ""; }; 23 | CB1FBF651A5F361900B06069 /* handmade_tile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_tile.h; path = ../handmadeSrc/handmade_tile.h; sourceTree = ""; }; 24 | CB469B661A50D9450000A950 /* handmade_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_platform.h; path = ../handmadeSrc/handmade_platform.h; sourceTree = ""; }; 25 | CB469B671A50D9450000A950 /* handmade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = handmade.cpp; path = ../handmadeSrc/handmade.cpp; sourceTree = ""; }; 26 | CB469B681A50D9450000A950 /* handmade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade.h; path = ../handmadeSrc/handmade.h; sourceTree = ""; }; 27 | CB60F04C1A4D38C400492AB5 /* libHandmade Hero Dylib.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libHandmade Hero Dylib.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | CBD97E141A54F237006CCBFB /* handmade_intrinsics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_intrinsics.h; path = ../handmadeSrc/handmade_intrinsics.h; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | CB60F0491A4D38C400492AB5 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | CB60F0431A4D38C400492AB5 = { 43 | isa = PBXGroup; 44 | children = ( 45 | CB0192771A6B05C1004638FA /* handmade_math.h */, 46 | CB1FBF631A5F361900B06069 /* handmade_random.h */, 47 | CB1FBF641A5F361900B06069 /* handmade_tile.cpp */, 48 | CB1FBF651A5F361900B06069 /* handmade_tile.h */, 49 | CBD97E141A54F237006CCBFB /* handmade_intrinsics.h */, 50 | CB469B661A50D9450000A950 /* handmade_platform.h */, 51 | CB469B671A50D9450000A950 /* handmade.cpp */, 52 | CB469B681A50D9450000A950 /* handmade.h */, 53 | CB60F04D1A4D38C400492AB5 /* Products */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | CB60F04D1A4D38C400492AB5 /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | CB60F04C1A4D38C400492AB5 /* libHandmade Hero Dylib.dylib */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXHeadersBuildPhase section */ 68 | CB60F04A1A4D38C400492AB5 /* Headers */ = { 69 | isa = PBXHeadersBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | CB0192781A6B05C1004638FA /* handmade_math.h in Headers */, 73 | CB1FBF681A5F361900B06069 /* handmade_tile.h in Headers */, 74 | CBD97E151A54F237006CCBFB /* handmade_intrinsics.h in Headers */, 75 | CB1FBF661A5F361900B06069 /* handmade_random.h in Headers */, 76 | CB469B6B1A50D9450000A950 /* handmade.h in Headers */, 77 | CB469B691A50D9450000A950 /* handmade_platform.h in Headers */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | /* End PBXHeadersBuildPhase section */ 82 | 83 | /* Begin PBXNativeTarget section */ 84 | CB60F04B1A4D38C400492AB5 /* Handmade Hero Dylib */ = { 85 | isa = PBXNativeTarget; 86 | buildConfigurationList = CB60F0501A4D38C400492AB5 /* Build configuration list for PBXNativeTarget "Handmade Hero Dylib" */; 87 | buildPhases = ( 88 | CB60F0481A4D38C400492AB5 /* Sources */, 89 | CB60F0491A4D38C400492AB5 /* Frameworks */, 90 | CB60F04A1A4D38C400492AB5 /* Headers */, 91 | ); 92 | buildRules = ( 93 | ); 94 | dependencies = ( 95 | ); 96 | name = "Handmade Hero Dylib"; 97 | productName = "Handmade Hero Dylib"; 98 | productReference = CB60F04C1A4D38C400492AB5 /* libHandmade Hero Dylib.dylib */; 99 | productType = "com.apple.product-type.library.dynamic"; 100 | }; 101 | /* End PBXNativeTarget section */ 102 | 103 | /* Begin PBXProject section */ 104 | CB60F0441A4D38C400492AB5 /* Project object */ = { 105 | isa = PBXProject; 106 | attributes = { 107 | LastUpgradeCheck = 0610; 108 | ORGANIZATIONNAME = "Handmade Hero"; 109 | TargetAttributes = { 110 | CB60F04B1A4D38C400492AB5 = { 111 | CreatedOnToolsVersion = 6.1.1; 112 | }; 113 | }; 114 | }; 115 | buildConfigurationList = CB60F0471A4D38C400492AB5 /* Build configuration list for PBXProject "Handmade Hero Dylib" */; 116 | compatibilityVersion = "Xcode 3.2"; 117 | developmentRegion = English; 118 | hasScannedForEncodings = 0; 119 | knownRegions = ( 120 | en, 121 | ); 122 | mainGroup = CB60F0431A4D38C400492AB5; 123 | productRefGroup = CB60F04D1A4D38C400492AB5 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | CB60F04B1A4D38C400492AB5 /* Handmade Hero Dylib */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXSourcesBuildPhase section */ 133 | CB60F0481A4D38C400492AB5 /* Sources */ = { 134 | isa = PBXSourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | CB469B6A1A50D9450000A950 /* handmade.cpp in Sources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXSourcesBuildPhase section */ 142 | 143 | /* Begin XCBuildConfiguration section */ 144 | CB60F04E1A4D38C400492AB5 /* Debug */ = { 145 | isa = XCBuildConfiguration; 146 | buildSettings = { 147 | ALWAYS_SEARCH_USER_PATHS = NO; 148 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 149 | CLANG_CXX_LIBRARY = "libc++"; 150 | CLANG_ENABLE_MODULES = YES; 151 | CLANG_ENABLE_OBJC_ARC = YES; 152 | CLANG_WARN_BOOL_CONVERSION = YES; 153 | CLANG_WARN_CONSTANT_CONVERSION = YES; 154 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 155 | CLANG_WARN_EMPTY_BODY = YES; 156 | CLANG_WARN_ENUM_CONVERSION = YES; 157 | CLANG_WARN_INT_CONVERSION = YES; 158 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | ENABLE_STRICT_OBJC_MSGSEND = YES; 163 | GCC_C_LANGUAGE_STANDARD = gnu99; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_OPTIMIZATION_LEVEL = 0; 166 | GCC_PREPROCESSOR_DEFINITIONS = ( 167 | "DEBUG=1", 168 | "$(inherited)", 169 | ); 170 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.9; 178 | MTL_ENABLE_DEBUG_INFO = YES; 179 | ONLY_ACTIVE_ARCH = YES; 180 | OTHER_CFLAGS = "-Dsize_t=__darwin_size_t"; 181 | SDKROOT = macosx; 182 | }; 183 | name = Debug; 184 | }; 185 | CB60F04F1A4D38C400492AB5 /* Release */ = { 186 | isa = XCBuildConfiguration; 187 | buildSettings = { 188 | ALWAYS_SEARCH_USER_PATHS = NO; 189 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 190 | CLANG_CXX_LIBRARY = "libc++"; 191 | CLANG_ENABLE_MODULES = YES; 192 | CLANG_ENABLE_OBJC_ARC = YES; 193 | CLANG_WARN_BOOL_CONVERSION = YES; 194 | CLANG_WARN_CONSTANT_CONVERSION = YES; 195 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 196 | CLANG_WARN_EMPTY_BODY = YES; 197 | CLANG_WARN_ENUM_CONVERSION = YES; 198 | CLANG_WARN_INT_CONVERSION = YES; 199 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 200 | CLANG_WARN_UNREACHABLE_CODE = YES; 201 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 202 | COPY_PHASE_STRIP = YES; 203 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 204 | ENABLE_NS_ASSERTIONS = NO; 205 | ENABLE_STRICT_OBJC_MSGSEND = YES; 206 | GCC_C_LANGUAGE_STANDARD = gnu99; 207 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 208 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 209 | GCC_WARN_UNDECLARED_SELECTOR = YES; 210 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 211 | GCC_WARN_UNUSED_FUNCTION = YES; 212 | GCC_WARN_UNUSED_VARIABLE = YES; 213 | MACOSX_DEPLOYMENT_TARGET = 10.9; 214 | MTL_ENABLE_DEBUG_INFO = NO; 215 | OTHER_CFLAGS = "-Dsize_t=__darwin_size_t"; 216 | SDKROOT = macosx; 217 | }; 218 | name = Release; 219 | }; 220 | CB60F0511A4D38C400492AB5 /* Debug */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | DYLIB_COMPATIBILITY_VERSION = 1; 224 | DYLIB_CURRENT_VERSION = 1; 225 | EXECUTABLE_PREFIX = lib; 226 | "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( 227 | "HANDMADE_INTERNAL=1", 228 | "HANDMADE_SLOW=1", 229 | "$(inherited)", 230 | ); 231 | PRODUCT_NAME = "$(TARGET_NAME)"; 232 | }; 233 | name = Debug; 234 | }; 235 | CB60F0521A4D38C400492AB5 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | DYLIB_COMPATIBILITY_VERSION = 1; 239 | DYLIB_CURRENT_VERSION = 1; 240 | EXECUTABLE_PREFIX = lib; 241 | GCC_OPTIMIZATION_LEVEL = s; 242 | "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "HANDMADE_INTERNAL=1"; 243 | PRODUCT_NAME = "$(TARGET_NAME)"; 244 | }; 245 | name = Release; 246 | }; 247 | /* End XCBuildConfiguration section */ 248 | 249 | /* Begin XCConfigurationList section */ 250 | CB60F0471A4D38C400492AB5 /* Build configuration list for PBXProject "Handmade Hero Dylib" */ = { 251 | isa = XCConfigurationList; 252 | buildConfigurations = ( 253 | CB60F04E1A4D38C400492AB5 /* Debug */, 254 | CB60F04F1A4D38C400492AB5 /* Release */, 255 | ); 256 | defaultConfigurationIsVisible = 0; 257 | defaultConfigurationName = Release; 258 | }; 259 | CB60F0501A4D38C400492AB5 /* Build configuration list for PBXNativeTarget "Handmade Hero Dylib" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | CB60F0511A4D38C400492AB5 /* Debug */, 263 | CB60F0521A4D38C400492AB5 /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | /* End XCConfigurationList section */ 269 | }; 270 | rootObject = CB60F0441A4D38C400492AB5 /* Project object */; 271 | } 272 | -------------------------------------------------------------------------------- /Handmade Hero OSX/Handmade Hero OSX.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CB1FBFA61A5F395D00B06069 /* test_background.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF6D1A5F391E00B06069 /* test_background.bmp */; }; 11 | CB1FBFA71A5F395D00B06069 /* test_hero_back_cape.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF6E1A5F391E00B06069 /* test_hero_back_cape.bmp */; }; 12 | CB1FBFA81A5F395D00B06069 /* test_hero_back_head.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF6F1A5F391E00B06069 /* test_hero_back_head.bmp */; }; 13 | CB1FBFA91A5F395D00B06069 /* test_hero_back_torso.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF701A5F391E00B06069 /* test_hero_back_torso.bmp */; }; 14 | CB1FBFAA1A5F395D00B06069 /* test_hero_front_cape.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF711A5F391E00B06069 /* test_hero_front_cape.bmp */; }; 15 | CB1FBFAB1A5F395D00B06069 /* test_hero_front_head.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF721A5F391E00B06069 /* test_hero_front_head.bmp */; }; 16 | CB1FBFAC1A5F395D00B06069 /* test_hero_front_torso.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF731A5F391E00B06069 /* test_hero_front_torso.bmp */; }; 17 | CB1FBFAD1A5F395D00B06069 /* test_hero_left_cape.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF741A5F391E00B06069 /* test_hero_left_cape.bmp */; }; 18 | CB1FBFAE1A5F395D00B06069 /* test_hero_left_head.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF751A5F391E00B06069 /* test_hero_left_head.bmp */; }; 19 | CB1FBFAF1A5F395D00B06069 /* test_hero_left_torso.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF761A5F391E00B06069 /* test_hero_left_torso.bmp */; }; 20 | CB1FBFB01A5F395D00B06069 /* test_hero_right_cape.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF771A5F391E00B06069 /* test_hero_right_cape.bmp */; }; 21 | CB1FBFB11A5F395D00B06069 /* test_hero_right_head.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF781A5F391E00B06069 /* test_hero_right_head.bmp */; }; 22 | CB1FBFB21A5F395D00B06069 /* test_hero_right_torso.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF791A5F391E00B06069 /* test_hero_right_torso.bmp */; }; 23 | CB1FBFB31A5F395D00B06069 /* test_hero_shadow.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7A1A5F391E00B06069 /* test_hero_shadow.bmp */; }; 24 | CB1FBFB41A5F395D00B06069 /* test_scene_layer_00.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7B1A5F391E00B06069 /* test_scene_layer_00.bmp */; }; 25 | CB1FBFB51A5F395D00B06069 /* test_scene_layer_01.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7C1A5F391E00B06069 /* test_scene_layer_01.bmp */; }; 26 | CB1FBFB61A5F395D00B06069 /* test_scene_layer_02.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7D1A5F391E00B06069 /* test_scene_layer_02.bmp */; }; 27 | CB1FBFB71A5F395D00B06069 /* test_scene_layer_03.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7E1A5F391E00B06069 /* test_scene_layer_03.bmp */; }; 28 | CB1FBFB81A5F395D00B06069 /* test_scene_layer_04.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB1FBF7F1A5F391E00B06069 /* test_scene_layer_04.bmp */; }; 29 | CB1FBFBA1A5F39A000B06069 /* libHandmade Hero Dylib.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = CB469B651A50D8D90000A950 /* libHandmade Hero Dylib.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 30 | CB469B461A50D8A40000A950 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B451A50D8A40000A950 /* AppDelegate.swift */; }; 31 | CB469B481A50D8A40000A950 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB469B471A50D8A40000A950 /* Images.xcassets */; }; 32 | CB469B4B1A50D8A40000A950 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB469B491A50D8A40000A950 /* MainMenu.xib */; }; 33 | CB469B571A50D8A40000A950 /* Handmade_Hero_OSXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B561A50D8A40000A950 /* Handmade_Hero_OSXTests.swift */; }; 34 | CB469B741A50D9DE0000A950 /* GameCodeLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B6C1A50D9DE0000A950 /* GameCodeLoader.swift */; }; 35 | CB469B751A50D9DE0000A950 /* GameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B6D1A50D9DE0000A950 /* GameView.swift */; }; 36 | CB469B761A50D9DE0000A950 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B6F1A50D9DE0000A950 /* Helpers.swift */; }; 37 | CB469B771A50D9DE0000A950 /* InputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B701A50D9DE0000A950 /* InputManager.swift */; }; 38 | CB469B781A50D9DE0000A950 /* ObjCShim.m in Sources */ = {isa = PBXBuildFile; fileRef = CB469B721A50D9DE0000A950 /* ObjCShim.m */; }; 39 | CB469B791A50D9DE0000A950 /* PlatformLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB469B731A50D9DE0000A950 /* PlatformLayer.swift */; }; 40 | CB469B7B1A50D9F90000A950 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB469B7A1A50D9F90000A950 /* OpenGL.framework */; }; 41 | CB469B7D1A50DA000000A950 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB469B7C1A50DA000000A950 /* CoreVideo.framework */; }; 42 | CB469B7F1A50DA090000A950 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB469B7E1A50DA090000A950 /* IOKit.framework */; }; 43 | CBD97E171A54F662006CCBFB /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD97E161A54F662006CCBFB /* SoundManager.swift */; }; 44 | CBD97E191A54FB92006CCBFB /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBD97E181A54FB92006CCBFB /* CoreAudio.framework */; }; 45 | /* End PBXBuildFile section */ 46 | 47 | /* Begin PBXContainerItemProxy section */ 48 | CB469B511A50D8A40000A950 /* PBXContainerItemProxy */ = { 49 | isa = PBXContainerItemProxy; 50 | containerPortal = CB469B381A50D8A40000A950 /* Project object */; 51 | proxyType = 1; 52 | remoteGlobalIDString = CB469B3F1A50D8A40000A950; 53 | remoteInfo = "Handmade Hero OSX"; 54 | }; 55 | CB469B641A50D8D90000A950 /* PBXContainerItemProxy */ = { 56 | isa = PBXContainerItemProxy; 57 | containerPortal = CB469B601A50D8D90000A950 /* Handmade Hero Dylib.xcodeproj */; 58 | proxyType = 2; 59 | remoteGlobalIDString = CB60F04C1A4D38C400492AB5; 60 | remoteInfo = "Handmade Hero Dylib"; 61 | }; 62 | /* End PBXContainerItemProxy section */ 63 | 64 | /* Begin PBXCopyFilesBuildPhase section */ 65 | CB1FBFB91A5F399A00B06069 /* CopyFiles */ = { 66 | isa = PBXCopyFilesBuildPhase; 67 | buildActionMask = 2147483647; 68 | dstPath = ""; 69 | dstSubfolderSpec = 10; 70 | files = ( 71 | CB1FBFBA1A5F39A000B06069 /* libHandmade Hero Dylib.dylib in CopyFiles */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | CB469B841A50DAFE0000A950 /* CopyFiles */ = { 76 | isa = PBXCopyFilesBuildPhase; 77 | buildActionMask = 2147483647; 78 | dstPath = test; 79 | dstSubfolderSpec = 7; 80 | files = ( 81 | CB1FBFA61A5F395D00B06069 /* test_background.bmp in CopyFiles */, 82 | CB1FBFA71A5F395D00B06069 /* test_hero_back_cape.bmp in CopyFiles */, 83 | CB1FBFA81A5F395D00B06069 /* test_hero_back_head.bmp in CopyFiles */, 84 | CB1FBFA91A5F395D00B06069 /* test_hero_back_torso.bmp in CopyFiles */, 85 | CB1FBFAA1A5F395D00B06069 /* test_hero_front_cape.bmp in CopyFiles */, 86 | CB1FBFAB1A5F395D00B06069 /* test_hero_front_head.bmp in CopyFiles */, 87 | CB1FBFAC1A5F395D00B06069 /* test_hero_front_torso.bmp in CopyFiles */, 88 | CB1FBFAD1A5F395D00B06069 /* test_hero_left_cape.bmp in CopyFiles */, 89 | CB1FBFAE1A5F395D00B06069 /* test_hero_left_head.bmp in CopyFiles */, 90 | CB1FBFAF1A5F395D00B06069 /* test_hero_left_torso.bmp in CopyFiles */, 91 | CB1FBFB01A5F395D00B06069 /* test_hero_right_cape.bmp in CopyFiles */, 92 | CB1FBFB11A5F395D00B06069 /* test_hero_right_head.bmp in CopyFiles */, 93 | CB1FBFB21A5F395D00B06069 /* test_hero_right_torso.bmp in CopyFiles */, 94 | CB1FBFB31A5F395D00B06069 /* test_hero_shadow.bmp in CopyFiles */, 95 | CB1FBFB41A5F395D00B06069 /* test_scene_layer_00.bmp in CopyFiles */, 96 | CB1FBFB51A5F395D00B06069 /* test_scene_layer_01.bmp in CopyFiles */, 97 | CB1FBFB61A5F395D00B06069 /* test_scene_layer_02.bmp in CopyFiles */, 98 | CB1FBFB71A5F395D00B06069 /* test_scene_layer_03.bmp in CopyFiles */, 99 | CB1FBFB81A5F395D00B06069 /* test_scene_layer_04.bmp in CopyFiles */, 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | /* End PBXCopyFilesBuildPhase section */ 104 | 105 | /* Begin PBXFileReference section */ 106 | CB1FBF6D1A5F391E00B06069 /* test_background.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_background.bmp; sourceTree = ""; }; 107 | CB1FBF6E1A5F391E00B06069 /* test_hero_back_cape.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_back_cape.bmp; sourceTree = ""; }; 108 | CB1FBF6F1A5F391E00B06069 /* test_hero_back_head.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_back_head.bmp; sourceTree = ""; }; 109 | CB1FBF701A5F391E00B06069 /* test_hero_back_torso.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_back_torso.bmp; sourceTree = ""; }; 110 | CB1FBF711A5F391E00B06069 /* test_hero_front_cape.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_front_cape.bmp; sourceTree = ""; }; 111 | CB1FBF721A5F391E00B06069 /* test_hero_front_head.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_front_head.bmp; sourceTree = ""; }; 112 | CB1FBF731A5F391E00B06069 /* test_hero_front_torso.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_front_torso.bmp; sourceTree = ""; }; 113 | CB1FBF741A5F391E00B06069 /* test_hero_left_cape.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_left_cape.bmp; sourceTree = ""; }; 114 | CB1FBF751A5F391E00B06069 /* test_hero_left_head.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_left_head.bmp; sourceTree = ""; }; 115 | CB1FBF761A5F391E00B06069 /* test_hero_left_torso.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_left_torso.bmp; sourceTree = ""; }; 116 | CB1FBF771A5F391E00B06069 /* test_hero_right_cape.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_right_cape.bmp; sourceTree = ""; }; 117 | CB1FBF781A5F391E00B06069 /* test_hero_right_head.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_right_head.bmp; sourceTree = ""; }; 118 | CB1FBF791A5F391E00B06069 /* test_hero_right_torso.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_right_torso.bmp; sourceTree = ""; }; 119 | CB1FBF7A1A5F391E00B06069 /* test_hero_shadow.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_hero_shadow.bmp; sourceTree = ""; }; 120 | CB1FBF7B1A5F391E00B06069 /* test_scene_layer_00.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_scene_layer_00.bmp; sourceTree = ""; }; 121 | CB1FBF7C1A5F391E00B06069 /* test_scene_layer_01.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_scene_layer_01.bmp; sourceTree = ""; }; 122 | CB1FBF7D1A5F391E00B06069 /* test_scene_layer_02.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_scene_layer_02.bmp; sourceTree = ""; }; 123 | CB1FBF7E1A5F391E00B06069 /* test_scene_layer_03.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_scene_layer_03.bmp; sourceTree = ""; }; 124 | CB1FBF7F1A5F391E00B06069 /* test_scene_layer_04.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = test_scene_layer_04.bmp; sourceTree = ""; }; 125 | CB469B401A50D8A40000A950 /* Handmade Hero OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Handmade Hero OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 126 | CB469B441A50D8A40000A950 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 127 | CB469B451A50D8A40000A950 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 128 | CB469B471A50D8A40000A950 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 129 | CB469B4A1A50D8A40000A950 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 130 | CB469B501A50D8A40000A950 /* Handmade Hero OSXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Handmade Hero OSXTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 131 | CB469B551A50D8A40000A950 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 132 | CB469B561A50D8A40000A950 /* Handmade_Hero_OSXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Handmade_Hero_OSXTests.swift; sourceTree = ""; }; 133 | CB469B601A50D8D90000A950 /* Handmade Hero Dylib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "Handmade Hero Dylib.xcodeproj"; path = "../Handmade Hero Dylib/Handmade Hero Dylib.xcodeproj"; sourceTree = ""; }; 134 | CB469B6C1A50D9DE0000A950 /* GameCodeLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameCodeLoader.swift; sourceTree = ""; }; 135 | CB469B6D1A50D9DE0000A950 /* GameView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameView.swift; sourceTree = ""; }; 136 | CB469B6E1A50D9DE0000A950 /* Handmade Hero OSX-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Handmade Hero OSX-Bridging-Header.h"; sourceTree = ""; }; 137 | CB469B6F1A50D9DE0000A950 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; 138 | CB469B701A50D9DE0000A950 /* InputManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputManager.swift; sourceTree = ""; }; 139 | CB469B711A50D9DE0000A950 /* ObjCShim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjCShim.h; sourceTree = ""; }; 140 | CB469B721A50D9DE0000A950 /* ObjCShim.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCShim.m; sourceTree = ""; }; 141 | CB469B731A50D9DE0000A950 /* PlatformLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlatformLayer.swift; sourceTree = ""; }; 142 | CB469B7A1A50D9F90000A950 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 143 | CB469B7C1A50DA000000A950 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; 144 | CB469B7E1A50DA090000A950 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 145 | CB469B821A50DA880000A950 /* handmade_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handmade_platform.h; path = ../../handmadeSrc/handmade_platform.h; sourceTree = ""; }; 146 | CBD97E161A54F662006CCBFB /* SoundManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; 147 | CBD97E181A54FB92006CCBFB /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; 148 | /* End PBXFileReference section */ 149 | 150 | /* Begin PBXFrameworksBuildPhase section */ 151 | CB469B3D1A50D8A40000A950 /* Frameworks */ = { 152 | isa = PBXFrameworksBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | CBD97E191A54FB92006CCBFB /* CoreAudio.framework in Frameworks */, 156 | CB469B7F1A50DA090000A950 /* IOKit.framework in Frameworks */, 157 | CB469B7D1A50DA000000A950 /* CoreVideo.framework in Frameworks */, 158 | CB469B7B1A50D9F90000A950 /* OpenGL.framework in Frameworks */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | CB469B4D1A50D8A40000A950 /* Frameworks */ = { 163 | isa = PBXFrameworksBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXFrameworksBuildPhase section */ 170 | 171 | /* Begin PBXGroup section */ 172 | CB1FBF6A1A5F390F00B06069 /* Handmade Hero Assets */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | CB1FBF6C1A5F391E00B06069 /* test */, 176 | ); 177 | name = "Handmade Hero Assets"; 178 | sourceTree = ""; 179 | }; 180 | CB1FBF6C1A5F391E00B06069 /* test */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | CB1FBF6D1A5F391E00B06069 /* test_background.bmp */, 184 | CB1FBF6E1A5F391E00B06069 /* test_hero_back_cape.bmp */, 185 | CB1FBF6F1A5F391E00B06069 /* test_hero_back_head.bmp */, 186 | CB1FBF701A5F391E00B06069 /* test_hero_back_torso.bmp */, 187 | CB1FBF711A5F391E00B06069 /* test_hero_front_cape.bmp */, 188 | CB1FBF721A5F391E00B06069 /* test_hero_front_head.bmp */, 189 | CB1FBF731A5F391E00B06069 /* test_hero_front_torso.bmp */, 190 | CB1FBF741A5F391E00B06069 /* test_hero_left_cape.bmp */, 191 | CB1FBF751A5F391E00B06069 /* test_hero_left_head.bmp */, 192 | CB1FBF761A5F391E00B06069 /* test_hero_left_torso.bmp */, 193 | CB1FBF771A5F391E00B06069 /* test_hero_right_cape.bmp */, 194 | CB1FBF781A5F391E00B06069 /* test_hero_right_head.bmp */, 195 | CB1FBF791A5F391E00B06069 /* test_hero_right_torso.bmp */, 196 | CB1FBF7A1A5F391E00B06069 /* test_hero_shadow.bmp */, 197 | CB1FBF7B1A5F391E00B06069 /* test_scene_layer_00.bmp */, 198 | CB1FBF7C1A5F391E00B06069 /* test_scene_layer_01.bmp */, 199 | CB1FBF7D1A5F391E00B06069 /* test_scene_layer_02.bmp */, 200 | CB1FBF7E1A5F391E00B06069 /* test_scene_layer_03.bmp */, 201 | CB1FBF7F1A5F391E00B06069 /* test_scene_layer_04.bmp */, 202 | ); 203 | name = test; 204 | path = ../../handmadeAssets/test; 205 | sourceTree = ""; 206 | }; 207 | CB469B371A50D8A40000A950 = { 208 | isa = PBXGroup; 209 | children = ( 210 | CB469B601A50D8D90000A950 /* Handmade Hero Dylib.xcodeproj */, 211 | CB469B421A50D8A40000A950 /* Handmade Hero OSX */, 212 | CB469B531A50D8A40000A950 /* Handmade Hero OSXTests */, 213 | CB469B411A50D8A40000A950 /* Products */, 214 | CBD97E181A54FB92006CCBFB /* CoreAudio.framework */, 215 | CB469B7E1A50DA090000A950 /* IOKit.framework */, 216 | CB469B7C1A50DA000000A950 /* CoreVideo.framework */, 217 | CB469B7A1A50D9F90000A950 /* OpenGL.framework */, 218 | ); 219 | sourceTree = ""; 220 | }; 221 | CB469B411A50D8A40000A950 /* Products */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | CB469B401A50D8A40000A950 /* Handmade Hero OSX.app */, 225 | CB469B501A50D8A40000A950 /* Handmade Hero OSXTests.xctest */, 226 | ); 227 | name = Products; 228 | sourceTree = ""; 229 | }; 230 | CB469B421A50D8A40000A950 /* Handmade Hero OSX */ = { 231 | isa = PBXGroup; 232 | children = ( 233 | CB1FBF6A1A5F390F00B06069 /* Handmade Hero Assets */, 234 | CB469B831A50DA8C0000A950 /* Handmade Hero Headers */, 235 | CB469B451A50D8A40000A950 /* AppDelegate.swift */, 236 | CB469B6C1A50D9DE0000A950 /* GameCodeLoader.swift */, 237 | CB469B6D1A50D9DE0000A950 /* GameView.swift */, 238 | CB469B6E1A50D9DE0000A950 /* Handmade Hero OSX-Bridging-Header.h */, 239 | CB469B6F1A50D9DE0000A950 /* Helpers.swift */, 240 | CB469B701A50D9DE0000A950 /* InputManager.swift */, 241 | CB469B711A50D9DE0000A950 /* ObjCShim.h */, 242 | CB469B721A50D9DE0000A950 /* ObjCShim.m */, 243 | CB469B731A50D9DE0000A950 /* PlatformLayer.swift */, 244 | CBD97E161A54F662006CCBFB /* SoundManager.swift */, 245 | CB469B471A50D8A40000A950 /* Images.xcassets */, 246 | CB469B491A50D8A40000A950 /* MainMenu.xib */, 247 | CB469B431A50D8A40000A950 /* Supporting Files */, 248 | ); 249 | path = "Handmade Hero OSX"; 250 | sourceTree = ""; 251 | }; 252 | CB469B431A50D8A40000A950 /* Supporting Files */ = { 253 | isa = PBXGroup; 254 | children = ( 255 | CB469B441A50D8A40000A950 /* Info.plist */, 256 | ); 257 | name = "Supporting Files"; 258 | sourceTree = ""; 259 | }; 260 | CB469B531A50D8A40000A950 /* Handmade Hero OSXTests */ = { 261 | isa = PBXGroup; 262 | children = ( 263 | CB469B561A50D8A40000A950 /* Handmade_Hero_OSXTests.swift */, 264 | CB469B541A50D8A40000A950 /* Supporting Files */, 265 | ); 266 | path = "Handmade Hero OSXTests"; 267 | sourceTree = ""; 268 | }; 269 | CB469B541A50D8A40000A950 /* Supporting Files */ = { 270 | isa = PBXGroup; 271 | children = ( 272 | CB469B551A50D8A40000A950 /* Info.plist */, 273 | ); 274 | name = "Supporting Files"; 275 | sourceTree = ""; 276 | }; 277 | CB469B611A50D8D90000A950 /* Products */ = { 278 | isa = PBXGroup; 279 | children = ( 280 | CB469B651A50D8D90000A950 /* libHandmade Hero Dylib.dylib */, 281 | ); 282 | name = Products; 283 | sourceTree = ""; 284 | }; 285 | CB469B831A50DA8C0000A950 /* Handmade Hero Headers */ = { 286 | isa = PBXGroup; 287 | children = ( 288 | CB469B821A50DA880000A950 /* handmade_platform.h */, 289 | ); 290 | name = "Handmade Hero Headers"; 291 | sourceTree = ""; 292 | }; 293 | /* End PBXGroup section */ 294 | 295 | /* Begin PBXNativeTarget section */ 296 | CB469B3F1A50D8A40000A950 /* Handmade Hero OSX */ = { 297 | isa = PBXNativeTarget; 298 | buildConfigurationList = CB469B5A1A50D8A40000A950 /* Build configuration list for PBXNativeTarget "Handmade Hero OSX" */; 299 | buildPhases = ( 300 | CB469B3C1A50D8A40000A950 /* Sources */, 301 | CB469B3D1A50D8A40000A950 /* Frameworks */, 302 | CB469B3E1A50D8A40000A950 /* Resources */, 303 | CB469B841A50DAFE0000A950 /* CopyFiles */, 304 | CB1FBFB91A5F399A00B06069 /* CopyFiles */, 305 | ); 306 | buildRules = ( 307 | ); 308 | dependencies = ( 309 | ); 310 | name = "Handmade Hero OSX"; 311 | productName = "Handmade Hero OSX"; 312 | productReference = CB469B401A50D8A40000A950 /* Handmade Hero OSX.app */; 313 | productType = "com.apple.product-type.application"; 314 | }; 315 | CB469B4F1A50D8A40000A950 /* Handmade Hero OSXTests */ = { 316 | isa = PBXNativeTarget; 317 | buildConfigurationList = CB469B5D1A50D8A40000A950 /* Build configuration list for PBXNativeTarget "Handmade Hero OSXTests" */; 318 | buildPhases = ( 319 | CB469B4C1A50D8A40000A950 /* Sources */, 320 | CB469B4D1A50D8A40000A950 /* Frameworks */, 321 | CB469B4E1A50D8A40000A950 /* Resources */, 322 | ); 323 | buildRules = ( 324 | ); 325 | dependencies = ( 326 | CB469B521A50D8A40000A950 /* PBXTargetDependency */, 327 | ); 328 | name = "Handmade Hero OSXTests"; 329 | productName = "Handmade Hero OSXTests"; 330 | productReference = CB469B501A50D8A40000A950 /* Handmade Hero OSXTests.xctest */; 331 | productType = "com.apple.product-type.bundle.unit-test"; 332 | }; 333 | /* End PBXNativeTarget section */ 334 | 335 | /* Begin PBXProject section */ 336 | CB469B381A50D8A40000A950 /* Project object */ = { 337 | isa = PBXProject; 338 | attributes = { 339 | LastUpgradeCheck = 0610; 340 | ORGANIZATIONNAME = "Handmade Hero"; 341 | TargetAttributes = { 342 | CB469B3F1A50D8A40000A950 = { 343 | CreatedOnToolsVersion = 6.1.1; 344 | }; 345 | CB469B4F1A50D8A40000A950 = { 346 | CreatedOnToolsVersion = 6.1.1; 347 | TestTargetID = CB469B3F1A50D8A40000A950; 348 | }; 349 | }; 350 | }; 351 | buildConfigurationList = CB469B3B1A50D8A40000A950 /* Build configuration list for PBXProject "Handmade Hero OSX" */; 352 | compatibilityVersion = "Xcode 3.2"; 353 | developmentRegion = English; 354 | hasScannedForEncodings = 0; 355 | knownRegions = ( 356 | en, 357 | Base, 358 | ); 359 | mainGroup = CB469B371A50D8A40000A950; 360 | productRefGroup = CB469B411A50D8A40000A950 /* Products */; 361 | projectDirPath = ""; 362 | projectReferences = ( 363 | { 364 | ProductGroup = CB469B611A50D8D90000A950 /* Products */; 365 | ProjectRef = CB469B601A50D8D90000A950 /* Handmade Hero Dylib.xcodeproj */; 366 | }, 367 | ); 368 | projectRoot = ""; 369 | targets = ( 370 | CB469B3F1A50D8A40000A950 /* Handmade Hero OSX */, 371 | CB469B4F1A50D8A40000A950 /* Handmade Hero OSXTests */, 372 | ); 373 | }; 374 | /* End PBXProject section */ 375 | 376 | /* Begin PBXReferenceProxy section */ 377 | CB469B651A50D8D90000A950 /* libHandmade Hero Dylib.dylib */ = { 378 | isa = PBXReferenceProxy; 379 | fileType = "compiled.mach-o.dylib"; 380 | path = "libHandmade Hero Dylib.dylib"; 381 | remoteRef = CB469B641A50D8D90000A950 /* PBXContainerItemProxy */; 382 | sourceTree = BUILT_PRODUCTS_DIR; 383 | }; 384 | /* End PBXReferenceProxy section */ 385 | 386 | /* Begin PBXResourcesBuildPhase section */ 387 | CB469B3E1A50D8A40000A950 /* Resources */ = { 388 | isa = PBXResourcesBuildPhase; 389 | buildActionMask = 2147483647; 390 | files = ( 391 | CB469B481A50D8A40000A950 /* Images.xcassets in Resources */, 392 | CB469B4B1A50D8A40000A950 /* MainMenu.xib in Resources */, 393 | ); 394 | runOnlyForDeploymentPostprocessing = 0; 395 | }; 396 | CB469B4E1A50D8A40000A950 /* Resources */ = { 397 | isa = PBXResourcesBuildPhase; 398 | buildActionMask = 2147483647; 399 | files = ( 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | }; 403 | /* End PBXResourcesBuildPhase section */ 404 | 405 | /* Begin PBXSourcesBuildPhase section */ 406 | CB469B3C1A50D8A40000A950 /* Sources */ = { 407 | isa = PBXSourcesBuildPhase; 408 | buildActionMask = 2147483647; 409 | files = ( 410 | CB469B771A50D9DE0000A950 /* InputManager.swift in Sources */, 411 | CBD97E171A54F662006CCBFB /* SoundManager.swift in Sources */, 412 | CB469B461A50D8A40000A950 /* AppDelegate.swift in Sources */, 413 | CB469B781A50D9DE0000A950 /* ObjCShim.m in Sources */, 414 | CB469B751A50D9DE0000A950 /* GameView.swift in Sources */, 415 | CB469B741A50D9DE0000A950 /* GameCodeLoader.swift in Sources */, 416 | CB469B761A50D9DE0000A950 /* Helpers.swift in Sources */, 417 | CB469B791A50D9DE0000A950 /* PlatformLayer.swift in Sources */, 418 | ); 419 | runOnlyForDeploymentPostprocessing = 0; 420 | }; 421 | CB469B4C1A50D8A40000A950 /* Sources */ = { 422 | isa = PBXSourcesBuildPhase; 423 | buildActionMask = 2147483647; 424 | files = ( 425 | CB469B571A50D8A40000A950 /* Handmade_Hero_OSXTests.swift in Sources */, 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | /* End PBXSourcesBuildPhase section */ 430 | 431 | /* Begin PBXTargetDependency section */ 432 | CB469B521A50D8A40000A950 /* PBXTargetDependency */ = { 433 | isa = PBXTargetDependency; 434 | target = CB469B3F1A50D8A40000A950 /* Handmade Hero OSX */; 435 | targetProxy = CB469B511A50D8A40000A950 /* PBXContainerItemProxy */; 436 | }; 437 | /* End PBXTargetDependency section */ 438 | 439 | /* Begin PBXVariantGroup section */ 440 | CB469B491A50D8A40000A950 /* MainMenu.xib */ = { 441 | isa = PBXVariantGroup; 442 | children = ( 443 | CB469B4A1A50D8A40000A950 /* Base */, 444 | ); 445 | name = MainMenu.xib; 446 | sourceTree = ""; 447 | }; 448 | /* End PBXVariantGroup section */ 449 | 450 | /* Begin XCBuildConfiguration section */ 451 | CB469B581A50D8A40000A950 /* Debug */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | ALWAYS_SEARCH_USER_PATHS = NO; 455 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 456 | CLANG_CXX_LIBRARY = "libc++"; 457 | CLANG_ENABLE_MODULES = YES; 458 | CLANG_ENABLE_OBJC_ARC = YES; 459 | CLANG_WARN_BOOL_CONVERSION = YES; 460 | CLANG_WARN_CONSTANT_CONVERSION = YES; 461 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 462 | CLANG_WARN_EMPTY_BODY = YES; 463 | CLANG_WARN_ENUM_CONVERSION = YES; 464 | CLANG_WARN_INT_CONVERSION = YES; 465 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 466 | CLANG_WARN_UNREACHABLE_CODE = YES; 467 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 468 | CODE_SIGN_IDENTITY = "-"; 469 | COPY_PHASE_STRIP = NO; 470 | ENABLE_STRICT_OBJC_MSGSEND = YES; 471 | GCC_C_LANGUAGE_STANDARD = gnu99; 472 | GCC_DYNAMIC_NO_PIC = NO; 473 | GCC_OPTIMIZATION_LEVEL = 0; 474 | GCC_PREPROCESSOR_DEFINITIONS = ( 475 | "DEBUG=1", 476 | "$(inherited)", 477 | ); 478 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 479 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 480 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 481 | GCC_WARN_UNDECLARED_SELECTOR = YES; 482 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 483 | GCC_WARN_UNUSED_FUNCTION = YES; 484 | GCC_WARN_UNUSED_VARIABLE = YES; 485 | MACOSX_DEPLOYMENT_TARGET = 10.9; 486 | MTL_ENABLE_DEBUG_INFO = YES; 487 | ONLY_ACTIVE_ARCH = YES; 488 | SDKROOT = macosx; 489 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 490 | }; 491 | name = Debug; 492 | }; 493 | CB469B591A50D8A40000A950 /* Release */ = { 494 | isa = XCBuildConfiguration; 495 | buildSettings = { 496 | ALWAYS_SEARCH_USER_PATHS = NO; 497 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 498 | CLANG_CXX_LIBRARY = "libc++"; 499 | CLANG_ENABLE_MODULES = YES; 500 | CLANG_ENABLE_OBJC_ARC = YES; 501 | CLANG_WARN_BOOL_CONVERSION = YES; 502 | CLANG_WARN_CONSTANT_CONVERSION = YES; 503 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 504 | CLANG_WARN_EMPTY_BODY = YES; 505 | CLANG_WARN_ENUM_CONVERSION = YES; 506 | CLANG_WARN_INT_CONVERSION = YES; 507 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 508 | CLANG_WARN_UNREACHABLE_CODE = YES; 509 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 510 | CODE_SIGN_IDENTITY = "-"; 511 | COPY_PHASE_STRIP = YES; 512 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 513 | ENABLE_NS_ASSERTIONS = NO; 514 | ENABLE_STRICT_OBJC_MSGSEND = YES; 515 | GCC_C_LANGUAGE_STANDARD = gnu99; 516 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 517 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 518 | GCC_WARN_UNDECLARED_SELECTOR = YES; 519 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 520 | GCC_WARN_UNUSED_FUNCTION = YES; 521 | GCC_WARN_UNUSED_VARIABLE = YES; 522 | MACOSX_DEPLOYMENT_TARGET = 10.9; 523 | MTL_ENABLE_DEBUG_INFO = NO; 524 | SDKROOT = macosx; 525 | }; 526 | name = Release; 527 | }; 528 | CB469B5B1A50D8A40000A950 /* Debug */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 532 | COMBINE_HIDPI_IMAGES = YES; 533 | GCC_PREPROCESSOR_DEFINITIONS = ( 534 | "DEBUG=1", 535 | "HANDMADE_INTERNAL=1", 536 | "HANDMADE_SLOW=1", 537 | ); 538 | INFOPLIST_FILE = "Handmade Hero OSX/Info.plist"; 539 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 540 | PRODUCT_NAME = "$(TARGET_NAME)"; 541 | SWIFT_OBJC_BRIDGING_HEADER = "Handmade Hero OSX/Handmade Hero OSX-Bridging-Header.h"; 542 | }; 543 | name = Debug; 544 | }; 545 | CB469B5C1A50D8A40000A950 /* Release */ = { 546 | isa = XCBuildConfiguration; 547 | buildSettings = { 548 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 549 | COMBINE_HIDPI_IMAGES = YES; 550 | GCC_PREPROCESSOR_DEFINITIONS = "HANDMADE_INTERNAL=1"; 551 | INFOPLIST_FILE = "Handmade Hero OSX/Info.plist"; 552 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | SWIFT_OBJC_BRIDGING_HEADER = "Handmade Hero OSX/Handmade Hero OSX-Bridging-Header.h"; 555 | }; 556 | name = Release; 557 | }; 558 | CB469B5E1A50D8A40000A950 /* Debug */ = { 559 | isa = XCBuildConfiguration; 560 | buildSettings = { 561 | BUNDLE_LOADER = "$(TEST_HOST)"; 562 | COMBINE_HIDPI_IMAGES = YES; 563 | FRAMEWORK_SEARCH_PATHS = ( 564 | "$(DEVELOPER_FRAMEWORKS_DIR)", 565 | "$(inherited)", 566 | ); 567 | GCC_PREPROCESSOR_DEFINITIONS = ( 568 | "DEBUG=1", 569 | "$(inherited)", 570 | ); 571 | INFOPLIST_FILE = "Handmade Hero OSXTests/Info.plist"; 572 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 573 | PRODUCT_NAME = "$(TARGET_NAME)"; 574 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Handmade Hero OSX.app/Contents/MacOS/Handmade Hero OSX"; 575 | }; 576 | name = Debug; 577 | }; 578 | CB469B5F1A50D8A40000A950 /* Release */ = { 579 | isa = XCBuildConfiguration; 580 | buildSettings = { 581 | BUNDLE_LOADER = "$(TEST_HOST)"; 582 | COMBINE_HIDPI_IMAGES = YES; 583 | FRAMEWORK_SEARCH_PATHS = ( 584 | "$(DEVELOPER_FRAMEWORKS_DIR)", 585 | "$(inherited)", 586 | ); 587 | INFOPLIST_FILE = "Handmade Hero OSXTests/Info.plist"; 588 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 589 | PRODUCT_NAME = "$(TARGET_NAME)"; 590 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Handmade Hero OSX.app/Contents/MacOS/Handmade Hero OSX"; 591 | }; 592 | name = Release; 593 | }; 594 | /* End XCBuildConfiguration section */ 595 | 596 | /* Begin XCConfigurationList section */ 597 | CB469B3B1A50D8A40000A950 /* Build configuration list for PBXProject "Handmade Hero OSX" */ = { 598 | isa = XCConfigurationList; 599 | buildConfigurations = ( 600 | CB469B581A50D8A40000A950 /* Debug */, 601 | CB469B591A50D8A40000A950 /* Release */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | CB469B5A1A50D8A40000A950 /* Build configuration list for PBXNativeTarget "Handmade Hero OSX" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | CB469B5B1A50D8A40000A950 /* Debug */, 610 | CB469B5C1A50D8A40000A950 /* Release */, 611 | ); 612 | defaultConfigurationIsVisible = 0; 613 | defaultConfigurationName = Release; 614 | }; 615 | CB469B5D1A50D8A40000A950 /* Build configuration list for PBXNativeTarget "Handmade Hero OSXTests" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | CB469B5E1A50D8A40000A950 /* Debug */, 619 | CB469B5F1A50D8A40000A950 /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | /* End XCConfigurationList section */ 625 | }; 626 | rootObject = CB469B381A50D8A40000A950 /* Project object */; 627 | } 628 | --------------------------------------------------------------------------------