@JonB Very helpful, I was looking for a way to implement structs. I tried using the MTLClearColor struct code and I get a weird error saying the argument I’m passing in is of an incorrect type
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/14D63AD1-3BA3-4745-9D78-6A22517D275C/Pythonista3/Documents/test/metal/test.py", line 32, in <module>
mtlView.clearColor = Colors.clear
File "/var/containers/Bundle/Application/687ADCDB-6C3D-44D7-91BB-9E86748ECFAE/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 651, in __setattr__
setter_method(value)
File "/var/containers/Bundle/Application/687ADCDB-6C3D-44D7-91BB-9E86748ECFAE/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 898, in __call__
res = objc_msgSend(obj.ptr, sel(self.sel_name), *args)
ctypes.ArgumentError: argument 3: <class 'TypeError'>: expected __Structure instance instead of MTLClearColor
But when I use a normal tuple it works (I think...the error is gone) Any idea why this might be happening?
I think jumping into this without in depth knowledge of python, obj c, and metal may not have been wise lol. The last major hiccup I’m having is using the device we created earlier using MTLCreateSystemDefaultDevice. I’m following Ray Wenderlich’s tutorial on clearing the screen to a single color
https://youtu.be/Gqj2lP7qlAM
https://developer.apple.com/documentation/metal/basic_tasks_and_concepts/using_metal_to_draw_a_view_s_contents
I’m trying to use the device to create a command buffer but when trying to call the create function I get the error
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/14D63AD1-3BA3-4745-9D78-6A22517D275C/Pythonista3/Documents/test/metal/test.py", line 37, in <module>
commandQueue = device.makeCommandQueue()
AttributeError: 'ObjCInstanceMethodProxy' object has no attribute 'makeCommandQueue'
Stackoverflow suggested I invoke the method proxy to get the underlying data which in this case turns out to be an int. I'm not sure why the device is an int instead of some object, is this a metal thing or some kind of issue from the way i used objc_util? It creates a new error when trying to call the createCommandBuffer function on the int (which makes sense bc its an int, why is it an int)
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/14D63AD1-3BA3-4745-9D78-6A22517D275C/Pythonista3/Documents/test/metal/test.py", line 37, in <module>
commandQueue = device.makeCommandQueue()
File "/var/containers/Bundle/Application/687ADCDB-6C3D-44D7-91BB-9E86748ECFAE/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 798, in __call__
method_name, kwarg_order = resolve_instance_method(obj, self.name, args, kwargs)
File "/var/containers/Bundle/Application/687ADCDB-6C3D-44D7-91BB-9E86748ECFAE/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 405, in resolve_instance_method
raise AttributeError('No method found for %s' % (name,))
AttributeError: No method found for makeCommandQueue
I think this is the bare minimum code you’d need to clear the screen a given color, I’m including it so you can see the errors if you want to. Also any insight to whether I’m setting up the ui view correctly would be helpful. Currently I’m just adding my metal view as a subview to the ui view but I’ve seen later tutorials override the ui view’s layer property with a CAMetalLayer. Is there a preferred method? Also does it matter when I add my metal view as a subview, can I do it before creating the command queue?
Code:
from objc_util import *
import ui
import ctypes
load_framework('MetalKit')
MTKView = ObjCClass('MTKView')
MTLCreateSystemDefaultDevice = c.MTLCreateSystemDefaultDevice
MTLCreateSystemDefaultDevice.argtypes = []
MTLCreateSystemDefaultDevice.restype = c_void_p
class MTLClearColor(Structure):
_fields_ = [
('red', ctypes.c_double),
('blue', ctypes.c_double),
('green', ctypes.c_double),
('alpha', ctypes.c_double)
]
class Colors():
clear = MTLClearColor(0.2, 0.8, 0.44, 1.0)
main_view = ui.View()
w, h = ui.get_screen_size()
main_view.frame = (0,0,w,h)
main_view.name = 'Metal Demo'
view = ObjCInstance(main_view)
mtlView = MTKView.alloc().init()
# mtlView.clearColor = Colors.clear
mtlView.clearColor = (0.2, 0.8, 0.44, 1.0)
mtlView.device = MTLCreateSystemDefaultDevice()
device = mtlView.device()
commandQueue = device.makeCommandQueue()
commandBuffer = commandQueue.makeCommandBuffer()
commandEncoder = commandBuffer.makeRenderCommandEncoder(mtlView.currentRenderPassDescriptor)
commandEncoder.endEncoding()
commandBuffer.present(mtlView.currentDrawable)
commandBuffer.commit()
view.addSubview_(mtlView)
if __name__ == '__main__':
main_view.present(hide_title_bar=True)
Thanks again for your help!