Browse Source

Add MetalKit; Add NSApplication NSMenu NSMenuItem; Improve Metal classes

gingerBill 3 years ago
parent
commit
51db46551e

+ 95 - 0
vendor/darwin/Foundation/NSApplication.odin

@@ -0,0 +1,95 @@
+package objc_Foundation
+
+import "core:intrinsics"
+
+ActivationPolicy :: enum UInteger {
+	Regular    = 0,
+	Accessory  = 1,
+	Prohibited = 2,
+}
+
+ApplicationDelegate :: struct {
+	willFinishLaunching:                  proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
+	didFinishLaunching:                   proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
+	shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application),
+
+	user_data: rawptr,
+}
+
+@(objc_class="NSApplication")
+Application :: struct {using _: Object}
+
+@(objc_type=Application, objc_name="sharedApplication", objc_is_class_method=true)
+Application_sharedApplication :: proc() -> ^Application {
+	return msgSend(^Application, Application, "sharedApplication")
+}
+
+@(objc_type=Application, objc_name="setDelegate")
+Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelegate) {
+	willFinishLaunching :: proc "c" (self: ^Value, _: SEL, notification: ^Notification) {
+		del := (^ApplicationDelegate)(self->pointerValue())
+		del->willFinishLaunching(notification)
+	}
+	didFinishLaunching :: proc "c" (self: ^Value, _: SEL, notification: ^Notification) {
+		del := (^ApplicationDelegate)(self->pointerValue())
+		del->didFinishLaunching(notification)
+	}
+	shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) {
+		del := (^ApplicationDelegate)(self->pointerValue())
+		del->shouldTerminateAfterLastWindowClosed(application)
+	}
+
+	wrapper := Value.valueWithPointer(delegate)
+
+	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationWillFinishLaunching:"),                  auto_cast willFinishLaunching,                  "v@:@")
+	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationDidFinishLaunching:"),                   auto_cast didFinishLaunching,                   "v@:@")
+	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast shouldTerminateAfterLastWindowClosed, "B@:@")
+
+	msgSend(nil, self, "setDelegate:", wrapper)
+}
+
+@(objc_type=Application, objc_name="setActivationPolicy")
+Application_setActivationPolicy :: proc(self: ^Application, activationPolicy: ActivationPolicy) -> BOOL {
+	return msgSend(BOOL, self, "setActivationPolicy:", activationPolicy)
+}
+
+@(objc_type=Application, objc_name="activateIgnoringOtherApps")
+Application_activateIgnoringOtherApps :: proc(self: ^Application, ignoreOtherApps: BOOL) {
+	msgSend(nil, self, "activateIgnoringOtherApps:", ignoreOtherApps)
+}
+
+@(objc_type=Application, objc_name="setMainMenu")
+Application_setMainMenu :: proc(self: ^Application, menu: ^Menu) {
+	msgSend(nil, self, "setMainMenu:", menu)
+}
+
+@(objc_type=Application, objc_name="windows")
+Application_windows :: proc(self: ^Application) -> ^Array {
+	return msgSend(^Array, self, "windows")
+}
+
+@(objc_type=Application, objc_name="run")
+Application_run :: proc(self: ^Application) {
+	msgSend(nil, self, "run")
+}
+
+
+@(objc_type=Application, objc_name="terminate")
+Application_terminate :: proc(self: ^Application, sender: ^Object) {
+	msgSend(nil, self, "terminate:", sender)
+}
+
+
+
+@(objc_class="NSRunningApplication")
+RunningApplication :: struct {using _: Object}
+
+@(objc_type=RunningApplication, objc_name="currentApplication", objc_is_class_method=true)
+RunningApplication_currentApplication :: proc() -> ^RunningApplication {
+	return msgSend(^RunningApplication, RunningApplication, "currentApplication")
+}
+
+@(objc_type=RunningApplication, objc_name="localizedName")
+RunningApplication_localizedName :: proc(self: ^RunningApplication) -> ^String {
+	return msgSend(^String, self, "localizedName")
+}

+ 103 - 0
vendor/darwin/Foundation/NSMenu.odin

@@ -0,0 +1,103 @@
+package objc_Foundation
+
+import "core:builtin"
+import "core:intrinsics"
+
+KeyEquivalentModifierFlag :: enum UInteger {
+	CapsLock   = 16, // Set if Caps Lock key is pressed.
+	Shift      = 17, // Set if Shift key is pressed.
+	Control    = 18, // Set if Control key is pressed.
+	Option     = 19, // Set if Option or Alternate key is pressed.
+	Command    = 20, // Set if Command key is pressed.
+	NumericPad = 21, // Set if any key in the numeric keypad is pressed.
+	Help       = 22, // Set if the Help key is pressed.
+	Function   = 23, // Set if any function key is pressed.
+}
+KeyEquivalentModifierMask :: distinct bit_set[KeyEquivalentModifierFlag; UInteger]
+
+// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information.
+KeyEventModifierFlagDeviceIndependentFlagsMask := transmute(KeyEquivalentModifierMask)_KeyEventModifierFlagDeviceIndependentFlagsMask
+@(private) _KeyEventModifierFlagDeviceIndependentFlagsMask := UInteger(0xffff0000)
+
+
+MenuItemCallback :: proc "c" (unused: rawptr, name: SEL, sender: ^Object)
+
+
+@(objc_class="NSMenuItem")
+MenuItem :: struct {using _: Object} 
+
+@(objc_type=MenuItem, objc_name="alloc", objc_is_class_method=true)
+MenuItem_alloc :: proc() -> ^MenuItem {
+	return msgSend(^MenuItem, MenuItem, "alloc")
+}
+@(objc_type=MenuItem, objc_name="registerActionCallback", objc_is_class_method=true)
+MenuItem_registerActionCallback :: proc(name: cstring, callback: MenuItemCallback) -> SEL {
+	s := string(name)
+	n := len(s)
+	sel: SEL
+	if n > 0 && s[n-1] != ':' {
+		col_name := intrinsics.alloca(n+2, 1)
+		builtin.copy(col_name[:n], s)
+		col_name[n] = ':'
+		col_name[n+1] = 0
+		sel = sel_registerName(cstring(col_name))
+	} else {
+		sel = sel_registerName(name)
+	}
+	if callback != nil {
+		class_addMethod(intrinsics.objc_find_class("NSObject"), sel, auto_cast callback, "v@:@")
+	}
+	return sel
+}
+
+@(objc_type=MenuItem, objc_name="init")
+MenuItem_init :: proc(self: ^MenuItem) -> ^MenuItem {
+	return msgSend(^MenuItem, self, "init")
+}
+
+@(objc_type=MenuItem, objc_name="setKeyEquivalentModifierMask")
+MenuItem_setKeyEquivalentModifierMask :: proc(self: ^MenuItem, modifierMask: KeyEquivalentModifierMask) {
+	msgSend(nil, self, "setKeyEquivalentModifierMask:", modifierMask)
+}
+
+@(objc_type=MenuItem, objc_name="keyEquivalentModifierMask")
+MenuItem_keyEquivalentModifierMask :: proc(self: ^MenuItem) -> KeyEquivalentModifierMask {
+	return msgSend(KeyEquivalentModifierMask, self, "keyEquivalentModifierMask")
+}
+
+@(objc_type=MenuItem, objc_name="setSubmenu")
+MenuItem_setSubmenu :: proc(self: ^MenuItem, submenu: ^Menu) {
+	msgSend(nil, self, "setSubmenu:", submenu)
+}
+
+
+
+
+@(objc_class="NSMenu")
+Menu :: struct {using _: Object} 
+
+@(objc_type=Menu, objc_name="alloc", objc_is_class_method=true)
+Menu_alloc :: proc() -> ^Menu {
+	return msgSend(^Menu, Menu, "alloc")
+}
+
+@(objc_type=Menu, objc_name="init")
+Menu_init :: proc(self: ^Menu) -> ^Menu {
+	return msgSend(^Menu, self, "init")
+}
+
+@(objc_type=Menu, objc_name="initWithTitle")
+Menu_initWithTitle :: proc(self: ^Menu, title: ^String) -> ^Menu {
+	return msgSend(^Menu, self, "initWithTitle:", title)
+}
+
+
+@(objc_type=Menu, objc_name="addItem")
+Menu_addItem :: proc(self: ^Menu, item: ^MenuItem) {
+	msgSend(nil, self, "addItem:", item)
+}
+
+@(objc_type=Menu, objc_name="addItemWithTitle")
+Menu_addItemWithTitle :: proc(self: ^Menu, title: ^String, selector: SEL, keyEquivalent: ^String) -> ^MenuItem {
+	return msgSend(^MenuItem, self, "addItemWithTitle:action:keyEquivalent:", title, selector, keyEquivalent)
+}

+ 3 - 3
vendor/darwin/Foundation/NSNumber.odin

@@ -48,17 +48,17 @@ Value_getValue :: proc(self: ^Value, value: rawptr, size: UInteger) {
 
 
 @(objc_type=Value, objc_name="objCType")
-Value_objCType :: proc(self: ^Value) -> cstring {
+Value_objCType :: proc "c" (self: ^Value) -> cstring {
 	return msgSend(cstring, self, "objCType")
 }
 
 @(objc_type=Value, objc_name="isEqualToValue")
-Value_isEqualToValue :: proc(self, other: ^Value) -> BOOL {
+Value_isEqualToValue :: proc "c" (self, other: ^Value) -> BOOL {
 	return msgSend(BOOL, self, "isEqualToValue:", other)
 }
 
 @(objc_type=Value, objc_name="pointerValue")
-Value_pointerValue :: proc(self: ^Value) -> rawptr {
+Value_pointerValue :: proc "c" (self: ^Value) -> rawptr {
 	return msgSend(rawptr, self, "pointerValue")
 }
 

+ 4 - 1
vendor/darwin/Foundation/NSObject.odin

@@ -53,7 +53,10 @@ autorelease :: proc(self: ^Object) {
 retainCount :: proc(self: ^Object) -> UInteger {
 	return msgSend(UInteger, self, "retainCount")
 }
-
+@(objc_type=Object, objc_name="class")
+class :: proc(self: ^Object) -> Class {
+	return msgSend(Class, self, "class")
+}
 
 @(objc_type=Object, objc_name="hash")
 hash :: proc(self: ^Object) -> UInteger {

+ 4 - 0
vendor/darwin/Foundation/NSString.odin

@@ -49,6 +49,10 @@ StringCompareOption :: enum UInteger {
 
 unichar :: distinct u16
 
+@(link_prefix="NS", default_calling_convention="c")
+foreign Foundation {
+	StringFromClass :: proc(cls: Class) -> ^String ---
+}
 
 AT :: MakeConstantString
 MakeConstantString :: proc "c" (#const c: cstring) -> ^String {

+ 7 - 0
vendor/darwin/Foundation/NSTypes.odin

@@ -33,3 +33,10 @@ ComparisonResult :: enum Integer {
 }
 
 NotFound :: IntegerMax
+
+Float :: distinct (f32 when size_of(uint) == 4 else f64)
+
+Size :: struct {
+	width:  Float,
+	height: Float,
+}

+ 82 - 5
vendor/darwin/Foundation/NSWindow.odin

@@ -7,18 +7,75 @@ Rect :: struct {
 	width, height: f64,
 }
 
+WindowStyleFlag :: enum NS.UInteger {
+	Titled                 = 0,
+	Closable               = 1,
+	Miniaturizable         = 2,
+	Resizable              = 3,
+	TexturedBackground     = 8,
+	UnifiedTitleAndToolbar = 12,
+	FullScreen             = 14,
+	FullSizeContentView    = 15,
+	UtilityWindow          = 4,
+	DocModalWindow         = 6,
+	NonactivatingPanel     = 7,
+	HUDWindow              = 13,
+}
+WindowStyleMask :: distinct bit_set[WindowStyleFlag; NS.UInteger]
+WindowStyleMaskBorderless             :: WindowStyleMask{}
+WindowStyleMaskTitled                 :: WindowStyleMask{.Titled}
+WindowStyleMaskClosable               :: WindowStyleMask{.Closable}
+WindowStyleMaskMiniaturizable         :: WindowStyleMask{.Miniaturizable}
+WindowStyleMaskResizable              :: WindowStyleMask{.Resizable}
+WindowStyleMaskTexturedBackground     :: WindowStyleMask{.TexturedBackground}
+WindowStyleMaskUnifiedTitleAndToolbar :: WindowStyleMask{.UnifiedTitleAndToolbar}
+WindowStyleMaskFullScreen             :: WindowStyleMask{.FullScreen}
+WindowStyleMaskFullSizeContentView    :: WindowStyleMask{.FullSizeContentView}
+WindowStyleMaskUtilityWindow          :: WindowStyleMask{.UtilityWindow}
+WindowStyleMaskDocModalWindow         :: WindowStyleMask{.DocModalWindow}
+WindowStyleMaskNonactivatingPanel     :: WindowStyleMask{.NonactivatingPanel}
+WindowStyleMaskHUDWindow              :: WindowStyleMask{.HUDWindow}
+
+BackingStoreType :: enum NS.UInteger {
+	Retained    = 0,
+	Nonretained = 1,
+	Buffered    = 2,
+}
+
 @(objc_class="NSColor")
 Color :: struct {using _: Object}
 
 @(objc_class="CALayer")
 Layer :: struct { using _: NS.Object }
 
+@(objc_type=Layer, objc_name="contentsScale")
+Layer_contentsScale :: proc(self: ^Layer) -> Float {
+	return msgSend(Float, self, "contentsScale")
+}
+@(objc_type=Layer, objc_name="setContentsScale")
+Layer_setContentsScale :: proc(self: ^Layer, scale: Float) {
+	msgSend(nil, self, "setContentsScale:", scale)
+}
+@(objc_type=Layer, objc_name="frame")
+Layer_frame :: proc(self: ^Layer) -> Rect {
+	return msgSend(Rect, self, "frame")
+}
+@(objc_type=Layer, objc_name="addSublayer")
+Layer_addSublayer :: proc(self: ^Layer, layer: ^Layer) {
+	msgSend(nil, self, "addSublayer:", layer)
+}
+
 @(objc_class="NSResponder")
 Responder :: struct {using _: Object}
 
 @(objc_class="NSView")
 View :: struct {using _: Responder}
 
+
+@(objc_type=View, objc_name="initWithFrame")
+View_initWithFrame :: proc(self: ^View, frame: Rect) -> ^View {
+	return msgSend(^View, self, "initWithFrame:", frame)
+}
 @(objc_type=View, objc_name="layer")
 View_layer :: proc(self: ^View) -> ^Layer {
 	return msgSend(^Layer, self, "layer")
@@ -27,10 +84,6 @@ View_layer :: proc(self: ^View) -> ^Layer {
 View_setLayer :: proc(self: ^View, layer: ^Layer) {
 	msgSend(nil, self, "setLayer:", layer)
 }
-@(objc_type=View, objc_name="setSubLayer")
-View_setSubLayer :: proc(self: ^View, layer: ^Layer) {
-	msgSend(nil, self, "setSubLayer:", layer)
-}
 @(objc_type=View, objc_name="wantsLayer")
 View_wantsLayer :: proc(self: ^View) -> BOOL {
 	return msgSend(BOOL, self, "wantsLayer")
@@ -40,14 +93,26 @@ View_setWantsLayer :: proc(self: ^View, wantsLayer: BOOL) {
 	msgSend(nil, self, "setWantsLayer:", wantsLayer)
 }
 
-
 @(objc_class="NSWindow")
 Window :: struct {using _: Responder}
 
+@(objc_type=Window, objc_name="alloc", objc_is_class_method=true)
+Window_alloc :: proc() -> ^Window {
+	return msgSend(^Window, Window, "alloc")
+}
+
+@(objc_type=Window, objc_name="initWithContentRect")
+Window_initWithContentRect :: proc(self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: bool) -> ^Window {
+	return msgSend(^Window, self, "initWithContentRect:styleMask:backing:defer:", contentRect, styleMask, backing, doDefer)
+}
 @(objc_type=Window, objc_name="contentView")
 Window_contentView :: proc(self: ^Window) -> ^View {
 	return msgSend(^View, self, "contentView")
 }
+@(objc_type=Window, objc_name="setContentView")
+Window_setContentView :: proc(self: ^Window, content_view: ^View) {
+	msgSend(nil, self, "setContentView:", content_view)
+}
 @(objc_type=Window, objc_name="frame")
 Window_frame :: proc(self: ^Window) -> Rect {
 	return msgSend(Rect, self, "frame")
@@ -72,3 +137,15 @@ Window_backgroundColor :: proc(self: ^Window) -> ^NS.Color {
 Window_setBackgroundColor :: proc(self: ^Window, color: ^NS.Color) {
 	msgSend(nil, self, "setBackgroundColor:", color)
 }
+@(objc_type=Window, objc_name="makeKeyAndOrderFront")
+Window_makeKeyAndOrderFront :: proc(self: ^Window, key: ^NS.Object) {
+	msgSend(nil, self, "makeKeyAndOrderFront:", key)
+}
+@(objc_type=Window, objc_name="setTitle")
+Window_setTitle :: proc(self: ^Window, title: ^NS.String) {
+	msgSend(nil, self, "setTitle:", title)
+}
+@(objc_type=Window, objc_name="close")
+Window_close :: proc(self: ^Window) {
+	msgSend(nil, self, "close")
+}

+ 73 - 0
vendor/darwin/Foundation/objc.odin

@@ -0,0 +1,73 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+
+import "core:intrinsics"
+import "core:c"
+
+IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id
+
+foreign Foundation {
+	objc_lookUpClass       :: proc "c" (name: cstring) -> Class ---
+	sel_registerName       :: proc "c" (name: cstring) -> SEL ---
+	objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) ---
+
+	class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL ---
+}
+
+
+@(objc_class="NSZone")
+Zone :: struct {using _: Object}
+
+@(link_prefix="NS")
+foreign Foundation {
+	AllocateObject   :: proc "c" (aClass: Class, extraBytes: UInteger, zone: ^Zone) -> id ---
+	DeallocateObject :: proc "c" (object: id) ---
+}
+
+Method :: ^objc_method
+objc_method :: struct {
+	method_name:  SEL,
+	method_types: cstring,
+	method_imp:   IMP,
+}
+objc_method_list :: struct {}
+
+objc_ivar :: struct {}
+objc_ivar_list :: struct {}
+
+objc_cache :: struct {
+	mask:     u32,
+	occupied: u32,
+	buckets:  [1]Method,
+}
+
+objc_protocol_list :: struct {
+	next:  ^objc_protocol_list,
+	count: c.int,
+	list:  [1]^Protocol,
+}
+
+@(objc_class="Protocol")
+Protocol :: struct{using _: intrinsics.objc_object}
+
+objc_object_internals :: struct {
+	isa: ^objc_class_internals,
+}
+
+
+objc_class_internals :: struct {
+	isa:           Class,
+	super_class:   Class,
+	name:          cstring,
+	version:       c.long,
+	info:          c.long,
+	instance_size: c.long,
+	ivars:         ^objc_ivar_list,
+	
+	methodLists:   ^^objc_method_list,
+
+	cache:         rawptr,
+	protocols:     rawptr,
+
+}

+ 7 - 7
vendor/darwin/Metal/MetalClasses.odin

@@ -4474,16 +4474,16 @@ TextureDescriptor_storageMode :: #force_inline proc(self: ^TextureDescriptor) ->
 TextureDescriptor_swizzle :: #force_inline proc(self: ^TextureDescriptor) -> TextureSwizzleChannels {
 	return msgSend(TextureSwizzleChannels, self, "swizzle")
 }
-@(objc_type=TextureDescriptor, objc_name="texture2DDescriptor", objc_is_class_method=true)
-TextureDescriptor_texture2DDescriptor :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, height: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor {
+@(objc_type=TextureDescriptor, objc_name="texture2DDescriptorWithPixelFormat", objc_is_class_method=true)
+TextureDescriptor_texture2DDescriptorWithPixelFormat :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, height: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor {
 	return msgSend(^TextureDescriptor, TextureDescriptor, "texture2DDescriptorWithPixelFormat:width:height:mipmapped:", pixelFormat, width, height, mipmapped)
 }
-@(objc_type=TextureDescriptor, objc_name="textureBufferDescriptor", objc_is_class_method=true)
-TextureDescriptor_textureBufferDescriptor :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, resourceOptions: ResourceOptions, usage: TextureUsage) -> ^TextureDescriptor {
+@(objc_type=TextureDescriptor, objc_name="textureBufferDescriptorWithPixelFormat", objc_is_class_method=true)
+TextureDescriptor_textureBufferDescriptorWithPixelFormat :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, resourceOptions: ResourceOptions, usage: TextureUsage) -> ^TextureDescriptor {
 	return msgSend(^TextureDescriptor, TextureDescriptor, "textureBufferDescriptorWithPixelFormat:width:resourceOptions:usage:", pixelFormat, width, resourceOptions, usage)
 }
-@(objc_type=TextureDescriptor, objc_name="textureCubeDescriptor", objc_is_class_method=true)
-TextureDescriptor_textureCubeDescriptor :: #force_inline proc(pixelFormat: PixelFormat, size: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor {
+@(objc_type=TextureDescriptor, objc_name="textureCubeDescriptorWithPixelFormat", objc_is_class_method=true)
+TextureDescriptor_textureCubeDescriptorWithPixelFormat :: #force_inline proc(pixelFormat: PixelFormat, size: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor {
 	return msgSend(^TextureDescriptor, TextureDescriptor, "textureCubeDescriptorWithPixelFormat:size:mipmapped:", pixelFormat, size, mipmapped)
 }
 @(objc_type=TextureDescriptor, objc_name="textureType")
@@ -7683,7 +7683,7 @@ RenderCommandEncoder_drawPrimitivesWithInstanceCount :: #force_inline proc(self:
 	msgSend(nil, self, "drawPrimitives:vertexStart:vertexCount:instanceCount:", primitiveType, vertexStart, vertexCount, instanceCount)
 }
 @(objc_type=RenderCommandEncoder, objc_name="drawPrimitivesWithInstances")
-RenderCommandEncoder_drawPrimitivesWithInstance :: #force_inline proc(self: ^RenderCommandEncoder, primitiveType: PrimitiveType, vertexStart: NS.UInteger, vertexCount: NS.UInteger, instanceCount: NS.UInteger, baseInstance: NS.UInteger) {
+RenderCommandEncoder_drawPrimitivesWithInstances :: #force_inline proc(self: ^RenderCommandEncoder, primitiveType: PrimitiveType, vertexStart: NS.UInteger, vertexCount: NS.UInteger, instanceCount: NS.UInteger, baseInstance: NS.UInteger) {
 	msgSend(nil, self, "drawPrimitives:vertexStart:vertexCount:instanceCount:baseInstance:", primitiveType, vertexStart, vertexCount, instanceCount, baseInstance)
 }
 @(objc_type=RenderCommandEncoder, objc_name="executeCommandsInBuffer")

+ 259 - 0
vendor/darwin/MetalKit/MetalKit.odin

@@ -0,0 +1,259 @@
+package objc_MetalKit
+
+import NS "vendor:darwin/Foundation"
+import MTL "vendor:darwin/Metal"
+import CA "vendor:darwin/QuartzCore"
+import "core:intrinsics"
+
+@(require)
+foreign import "system:MetalKit.framework"
+
+@(private)
+msgSend :: intrinsics.objc_send
+
+ColorSpaceRef :: struct {}
+
+ViewDelegate :: struct {
+	drawInMTKView:          proc "c" (self: ^ViewDelegate, view: ^View),
+	drawableSizeWillChange: proc "c" (self: ^ViewDelegate, view: ^View, size: NS.Size),
+
+	user_data: rawptr,
+}
+
+@(objc_class="MTKView")
+View :: struct {using _: NS.View}
+
+@(objc_type=View, objc_name="alloc", objc_is_class_method=true)
+View_alloc :: proc() -> ^View {
+	return msgSend(^View, View, "alloc")
+}
+@(objc_type=View, objc_name="initWithFrame")
+View_initWithFrame :: proc(self: ^View, frame: NS.Rect, device: ^MTL.Device) -> ^View {
+	return msgSend(^View, self, "initWithFrame:device:", frame, device)
+}
+@(objc_type=View, objc_name="initWithCoder")
+View_initWithCoder :: proc(self: ^View, coder: ^NS.Coder) -> ^View {
+	return msgSend(^View, self, "initWithCoder:", coder)
+}
+
+@(objc_type=View, objc_name="setDevice")
+View_setDevice :: proc(self: ^View, device: ^MTL.Device) {
+	msgSend(nil, self, "setDevice:", device)
+}
+@(objc_type=View, objc_name="device")
+View_device :: proc(self: ^View) -> ^MTL.Device {
+	return msgSend(^MTL.Device, self, "device")
+}
+
+@(objc_type=View, objc_name="draw")
+View_draw :: proc(self: ^View) {
+	msgSend(nil, self, "draw")
+}
+
+@(objc_type=View, objc_name="setDelegate")
+View_setDelegate :: proc(self: ^View, delegate: ^ViewDelegate) {
+	drawDispatch :: proc "c" (self: ^NS.Value, cmd: NS.SEL, view: ^View) {
+		del := (^ViewDelegate)(self->pointerValue())
+		del->drawInMTKView(view)
+	}
+	drawableSizeWillChange :: proc "c" (self: ^NS.Value, cmd: NS.SEL, view: ^View, size: NS.Size) {
+		del := (^ViewDelegate)(self->pointerValue())
+		del->drawableSizeWillChange(view, size)
+	}
+
+	wrapper := NS.Value.valueWithPointer(delegate)
+
+	NS.class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("drawInMTKView:"), auto_cast drawDispatch, "v@:@")
+
+	cbparams :: "v@:@{CGSize=ff}" when size_of(NS.Float) == size_of(f32) else "v@:@{CGSize=dd}"
+	NS.class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("mtkView:drawableSizeWillChange:"), auto_cast drawableSizeWillChange, cbparams)
+
+	msgSend(nil, self, "setDelegate:", wrapper)
+}
+
+@(objc_type=View, objc_name="delegate")
+View_delegate :: proc(self: ^View) -> ^ViewDelegate {
+	wrapper := msgSend(^NS.Value, self, "delegate")
+	if wrapper != nil {
+		return (^ViewDelegate)(wrapper->pointerValue())
+	}
+	return nil
+}
+
+@(objc_type=View, objc_name="currentDrawable")
+View_currentDrawable :: proc(self: ^View) -> ^CA.MetalDrawable {
+	return msgSend(^CA.MetalDrawable, self, "currentDrawable")
+}
+
+@(objc_type=View, objc_name="setFramebufferOnly")
+View_setFramebufferOnly :: proc(self: ^View, framebufferOnly: bool) {
+	msgSend(nil, self, "setFramebufferOnly:", framebufferOnly)
+}
+@(objc_type=View, objc_name="framebufferOnly")
+View_framebufferOnly :: proc(self: ^View) -> bool {
+	return msgSend(bool, self, "framebufferOnly")
+}
+
+@(objc_type=View, objc_name="setDepthStencilAttachmentTextureUsage")
+View_setDepthStencilAttachmentTextureUsage :: proc(self: ^View, textureUsage: MTL.TextureUsage) {
+	msgSend(nil, self, "setDepthStencilAttachmentTextureUsage:", textureUsage)
+}
+@(objc_type=View, objc_name="depthStencilAttachmentTextureUsage")
+View_depthStencilAttachmentTextureUsage :: proc(self: ^View) -> MTL.TextureUsage {
+	return msgSend(MTL.TextureUsage, self, "depthStencilAttachmentTextureUsage")
+}
+
+@(objc_type=View, objc_name="setMultisampleColorAttachmentTextureUsage")
+View_setMultisampleColorAttachmentTextureUsage :: proc(self: ^View, textureUsage: MTL.TextureUsage) {
+	msgSend(nil, self, "setMultisampleColorAttachmentTextureUsage:", textureUsage)
+}
+@(objc_type=View, objc_name="multisampleColorAttachmentTextureUsage")
+View_multisampleColorAttachmentTextureUsage :: proc(self: ^View) -> MTL.TextureUsage {
+	return msgSend(MTL.TextureUsage, self, "multisampleColorAttachmentTextureUsage")
+}
+
+@(objc_type=View, objc_name="setPresentsWithTransaction")
+View_setPresentsWithTransaction :: proc(self: ^View, presentsWithTransaction: bool) {
+	msgSend(nil, self, "setPresentsWithTransaction:", presentsWithTransaction)
+}
+@(objc_type=View, objc_name="presentsWithTransaction")
+View_presentsWithTransaction :: proc(self: ^View) -> bool {
+	return msgSend(bool, self, "presentsWithTransaction")
+}
+
+@(objc_type=View, objc_name="setColorPixelFormat")
+View_setColorPixelFormat :: proc(self: ^View, colorPixelFormat: MTL.PixelFormat) {
+	msgSend(nil, self, "setColorPixelFormat:", colorPixelFormat)
+}
+@(objc_type=View, objc_name="colorPixelFormat")
+View_colorPixelFormat :: proc(self: ^View) -> MTL.PixelFormat {
+	return msgSend(MTL.PixelFormat, self, "colorPixelFormat")
+}
+
+@(objc_type=View, objc_name="setDepthStencilPixelFormat")
+View_setDepthStencilPixelFormat :: proc(self: ^View, colorPixelFormat: MTL.PixelFormat) {
+	msgSend(nil, self, "setDepthStencilPixelFormat:", colorPixelFormat)
+}
+@(objc_type=View, objc_name="depthStencilPixelFormat")
+View_depthStencilPixelFormat :: proc(self: ^View) -> MTL.PixelFormat {
+	return msgSend(MTL.PixelFormat, self, "depthStencilPixelFormat")
+}
+
+@(objc_type=View, objc_name="setSampleCount")
+View_setSampleCount :: proc(self: ^View, sampleCount: NS.UInteger) {
+	msgSend(nil, self, "setSampleCount:", sampleCount)
+}
+@(objc_type=View, objc_name="sampleCount")
+View_sampleCount :: proc(self: ^View) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "sampleCount")
+}
+
+@(objc_type=View, objc_name="setClearColor")
+View_setClearColor :: proc(self: ^View, clearColor: MTL.ClearColor) {
+	msgSend(nil, self, "setClearColor:", clearColor)
+}
+@(objc_type=View, objc_name="clearColor")
+View_clearColor :: proc(self: ^View) -> MTL.ClearColor {
+	return msgSend(MTL.ClearColor, self, "clearColor")
+}
+
+@(objc_type=View, objc_name="setClearDepth")
+View_setClearDepth :: proc(self: ^View, clearDepth: f64) {
+	msgSend(nil, self, "setClearDepth:", clearDepth)
+}
+@(objc_type=View, objc_name="clearDepth")
+View_clearDepth :: proc(self: ^View) -> f64 {
+	return msgSend(f64, self, "clearDepth")
+}
+
+@(objc_type=View, objc_name="setClearStencil")
+View_setClearStencil :: proc(self: ^View, clearStencil: u32) {
+	msgSend(nil, self, "setClearStencil:", clearStencil)
+}
+@(objc_type=View, objc_name="clearStencil")
+View_clearStencil :: proc(self: ^View) -> u32 {
+	return msgSend(u32, self, "clearStencil")
+}
+
+@(objc_type=View, objc_name="depthStencilTexture")
+View_depthStencilTexture :: proc(self: ^View) -> ^MTL.Texture {
+	return msgSend(^MTL.Texture, self, "depthStencilTexture")
+}
+@(objc_type=View, objc_name="multisampleColorTexture")
+View_multisampleColorTexture :: proc(self: ^View) -> ^MTL.Texture {
+	return msgSend(^MTL.Texture, self, "multisampleColorTexture")
+}
+
+@(objc_type=View, objc_name="releaseDrawables")
+View_releaseDrawables :: proc(self: ^View) {
+	msgSend(nil, self, "releaseDrawables")
+}
+
+@(objc_type=View, objc_name="currentRenderPassDescriptor")
+View_currentRenderPassDescriptor :: proc(self: ^View) -> ^MTL.RenderPassDescriptor {
+	return msgSend(^MTL.RenderPassDescriptor, self, "currentRenderPassDescriptor")
+}
+
+@(objc_type=View, objc_name="setPreferredFramesPerSecond")
+View_setPreferredFramesPerSecond :: proc(self: ^View, preferredFramesPerSecond: NS.Integer) {
+	msgSend(nil, self, "setPreferredFramesPerSecond:", preferredFramesPerSecond)
+}
+@(objc_type=View, objc_name="preferredFramesPerSecond")
+View_preferredFramesPerSecond :: proc(self: ^View) -> NS.Integer {
+	return msgSend(NS.Integer, self, "preferredFramesPerSecond")
+}
+
+@(objc_type=View, objc_name="setEnableSetNeedsDisplay")
+View_setEnableSetNeedsDisplay :: proc(self: ^View, enableSetNeedsDisplay: bool) {
+	msgSend(nil, self, "setEnableSetNeedsDisplay:", enableSetNeedsDisplay)
+}
+@(objc_type=View, objc_name="enableSetNeedsDisplay")
+View_enableSetNeedsDisplay :: proc(self: ^View) -> bool {
+	return msgSend(bool, self, "enableSetNeedsDisplay")
+}
+
+@(objc_type=View, objc_name="setAutoresizeDrawable")
+View_setAutoresizeDrawable :: proc(self: ^View, autoresizeDrawable: bool) {
+	msgSend(nil, self, "setAutoresizeDrawable:", autoresizeDrawable)
+}
+@(objc_type=View, objc_name="autoresizeDrawable")
+View_autoresizeDrawable :: proc(self: ^View) -> bool {
+	return msgSend(bool, self, "autoresizeDrawable")
+}
+
+@(objc_type=View, objc_name="setDrawableSize")
+View_setDrawableSize :: proc(self: ^View, drawableSize: NS.Size) {
+	msgSend(nil, self, "setDrawableSize:", drawableSize)
+}
+@(objc_type=View, objc_name="drawableSize")
+View_drawableSize :: proc(self: ^View) -> NS.Size {
+	return msgSend(NS.Size, self, "drawableSize")
+}
+
+@(objc_type=View, objc_name="preferredDrawableSize")
+View_preferredDrawableSize :: proc(self: ^View) -> NS.Size {
+	return msgSend(NS.Size, self, "preferredDrawableSize")
+}
+
+@(objc_type=View, objc_name="preferredDevice")
+View_preferredDevice :: proc(self: ^View) -> ^MTL.Device {
+	return msgSend(^MTL.Device, self, "preferredDevice")
+}
+
+@(objc_type=View, objc_name="setPaused")
+View_setPaused :: proc(self: ^View, isPaused: bool) {
+	msgSend(nil, self, "setPaused:", isPaused)
+}
+@(objc_type=View, objc_name="isPaused")
+View_isPaused :: proc(self: ^View) -> bool {
+	return msgSend(bool, self, "isPaused")
+}
+
+@(objc_type=View, objc_name="setColorSpace")
+View_setColorSpace :: proc(self: ^View, colorSpace: ColorSpaceRef) {
+	msgSend(nil, self, "setColorSpace:", colorSpace)
+}
+@(objc_type=View, objc_name="colorSpace")
+View_colorSpace :: proc(self: ^View) -> ColorSpaceRef {
+	return msgSend(ColorSpaceRef, self, "colorSpace")
+}