use crate::{arc, cf, define_cls, define_obj_type, mtl, ns, objc};
#[cfg(feature = "cg")]
use crate::cg;
#[cfg(feature = "blocks")]
use crate::blocks;
define_obj_type!(
#[doc(alias = "MTKTextureLoader")]
pub TextureLoader(ns::Id)
);
define_obj_type!(
#[doc(alias = "MTKTextureLoaderOption")]
pub TextureLoaderOpt(ns::String)
);
impl TextureLoaderOpt {
#[doc(alias = "MTKTextureLoaderOptionAllocateMipmaps")]
#[inline]
pub fn allocate_mipmaps() -> &'static Self {
unsafe { MTKTextureLoaderOptionAllocateMipmaps }
}
#[doc(alias = "MTKTextureLoaderOptionGenerateMipmaps")]
#[inline]
pub fn generate_mipmaps() -> &'static Self {
unsafe { MTKTextureLoaderOptionGenerateMipmaps }
}
#[doc(alias = "MTKTextureLoaderOptionSRGB")]
#[inline]
pub fn srgb() -> &'static Self {
unsafe { MTKTextureLoaderOptionSRGB }
}
#[doc(alias = "MTKTextureLoaderOptionTextureUsage")]
pub fn texture_usage() -> &'static Self {
unsafe { MTKTextureLoaderOptionTextureUsage }
}
#[doc(alias = "MTKTextureLoaderOptionTextureCPUCacheMode")]
pub fn texture_cpu_cache_mode() -> &'static Self {
unsafe { MTKTextureLoaderOptionTextureCPUCacheMode }
}
#[doc(alias = "MTKTextureLoaderOptionTextureStorageMode")]
pub fn texture_storage_mode() -> &'static Self {
unsafe { MTKTextureLoaderOptionTextureStorageMode }
}
#[doc(alias = "MTKTextureLoaderOptionOrigin")]
pub fn origin() -> &'static Self {
unsafe { MTKTextureLoaderOptionOrigin }
}
#[doc(alias = "MTKTextureLoaderOptionLoadAsArray")]
pub fn load_as_array() -> &'static Self {
unsafe { MTKTextureLoaderOptionLoadAsArray }
}
}
define_obj_type!(
#[doc(alias = "MTKTextureLoaderCubeLayout")]
pub TextureLoaderCubeLayout(ns::String)
);
impl TextureLoaderCubeLayout {
#[doc(alias = "MTKTextureLoaderCubeLayoutVertical")]
#[inline]
pub fn vertical() -> &'static Self {
unsafe { MTKTextureLoaderCubeLayoutVertical }
}
}
define_obj_type!(
#[doc(alias = "MTKTextureLoaderOrigin")]
pub TextureLoaderOrigin(ns::String)
);
impl TextureLoaderOrigin {
#[doc(alias = "MTKTextureLoaderOriginTopLeft")]
#[inline]
pub fn top_left() -> &'static Self {
unsafe { MTKTextureLoaderOriginTopLeft }
}
#[doc(alias = "MTKTextureLoaderOriginBottomLeft")]
#[inline]
pub fn bottom_left() -> &'static Self {
unsafe { MTKTextureLoaderOriginBottomLeft }
}
#[doc(alias = "MTKTextureLoaderOriginFlippedVertically")]
#[inline]
pub fn flipped_vertically() -> &'static Self {
unsafe { MTKTextureLoaderOriginFlippedVertically }
}
}
#[doc(alias = "MTKTextureLoaderCallback")]
#[cfg(feature = "blocks")]
pub type TextureLoaderCb = blocks::ResultCh<mtl::Texture>;
#[doc(alias = "MTKTextureLoaderArrayCallback")]
#[cfg(feature = "blocks")]
pub type TextureLoaderArrayCb = blocks::ResultCh<ns::Array<mtl::Texture>>;
impl arc::A<TextureLoader> {
#[objc::msg_send(initWithDevice:)]
pub fn init_with_device(self, device: &mtl::Device) -> arc::R<TextureLoader>;
}
pub type Opts = ns::Dictionary<TextureLoaderOpt, ns::Id>;
impl TextureLoader {
define_cls!(MTK_TEXTURE_LOADER);
#[objc::msg_send(device)]
pub fn device(&self) -> arc::R<mtl::Device>;
pub fn with_device(device: &mtl::Device) -> arc::R<Self> {
Self::alloc().init_with_device(device)
}
pub fn with_sys_default_device() -> Option<arc::R<Self>> {
Some(Self::alloc().init_with_device(mtl::Device::sys_default().as_ref()?))
}
#[cfg(feature = "blocks")]
#[objc::msg_send(newTextureWithContentsOfURL:options:completionHandler:)]
pub fn new_texture_with_url_ch(
&self,
url: &ns::Url,
options: Option<&Opts>,
ch: &mut TextureLoaderCb,
);
#[objc::msg_send(newTextureWithContentsOfURL:options:error:)]
pub unsafe fn new_texture_with_url_err<'ear>(
&self,
url: &ns::Url,
options: Option<&Opts>,
error: *mut Option<&'ear ns::Error>,
) -> Option<arc::R<mtl::Texture>>;
pub fn new_texture_with_url<'ear>(
&self,
url: &ns::Url,
options: Option<&Opts>,
) -> ns::Result<'ear, arc::R<mtl::Texture>> {
ns::if_none(|err| unsafe { self.new_texture_with_url_err(url, options, err) })
}
#[objc::msg_send(newTexturesWithContentsOfURLs:options:error:)]
pub unsafe fn new_textures_with_urls_err<'ear>(
&self,
urls: &ns::Array<ns::Url>,
options: Option<&Opts>,
error: *mut Option<&'ear ns::Error>,
) -> arc::R<ns::Array<OptionTexture>>;
pub fn new_textures_with_urls<'ear>(
&self,
urls: &ns::Array<ns::Url>,
options: Option<&Opts>,
) -> (arc::R<ns::Array<OptionTexture>>, Option<&'ear ns::Error>) {
let mut err = None;
let textures = unsafe { self.new_textures_with_urls_err(urls, options, &mut err) };
(textures, err)
}
#[objc::msg_send(newTextureWithData:options:error:)]
pub unsafe fn new_texture_with_data_err<'ear>(
&self,
data: &ns::Data,
options: Option<&Opts>,
error: *mut Option<&'ear ns::Error>,
) -> Option<arc::R<mtl::Texture>>;
pub fn new_texture_with_data<'ear>(
&self,
data: &ns::Data,
options: Option<&Opts>,
) -> ns::Result<'ear, arc::R<mtl::Texture>> {
ns::if_none(|err| unsafe { self.new_texture_with_data_err(data, options, err) })
}
#[cfg(feature = "cg")]
#[objc::msg_send(newTextureWithCGImage:options:error:)]
pub unsafe fn new_texture_with_cg_image_err<'ear>(
&self,
image: &cg::Image,
options: Option<&Opts>,
error: *mut Option<&'ear ns::Error>,
) -> Option<arc::R<mtl::Texture>>;
#[cfg(feature = "cg")]
pub fn new_texture_with_cg_image<'ear>(
&self,
image: &cg::Image,
options: Option<&Opts>,
) -> ns::Result<'ear, arc::R<mtl::Texture>> {
ns::if_none(|err| unsafe { self.new_texture_with_cg_image_err(image, options, err) })
}
#[cfg(feature = "cg")]
#[objc::msg_send(newTextureWithName:scaleFactor:bundle:options:error:)]
pub unsafe fn new_texture_with_name_err<'ear>(
&self,
name: &ns::String,
scale_factor: cg::Float,
bundle: Option<&ns::Bundle>,
options: Option<&Opts>,
error: *mut Option<&'ear ns::Error>,
) -> Option<arc::R<mtl::Texture>>;
#[cfg(feature = "cg")]
pub fn new_texture_with_name<'ear>(
&self,
name: &ns::String,
scale_factor: cg::Float,
bundle: Option<&ns::Bundle>,
options: Option<&Opts>,
) -> ns::Result<'ear, arc::R<mtl::Texture>> {
ns::if_none(|err| unsafe {
self.new_texture_with_name_err(name, scale_factor, bundle, options, err)
})
}
#[doc(alias = "MTKTextureLoaderErrorKey")]
#[inline]
pub fn error_key() -> &'static ns::String {
unsafe { MTKTextureLoaderErrorKey }
}
}
define_obj_type!(
pub OptionTexture(ns::Id)
);
impl OptionTexture {
#[inline]
pub fn is_none(&self) -> bool {
unsafe { cf::Null::value().as_type_ptr() == self.as_type_ref().as_type_ptr() }
}
#[inline]
pub fn texture(&self) -> Option<&mtl::Texture> {
if self.is_none() {
None
} else {
Some(unsafe { std::mem::transmute(self) })
}
}
}
#[link(name = "mtk", kind = "static")]
unsafe extern "C" {
static MTK_TEXTURE_LOADER: &'static objc::Class<TextureLoader>;
}
impl ns::ErrorDomain {
#[doc(alias = "MTKTextureLoaderErrorDomain")]
pub fn texture_loader() -> &'static Self {
unsafe { MTKTextureLoaderErrorDomain }
}
}
#[link(name = "MetalKit", kind = "framework")]
unsafe extern "C" {
static MTKTextureLoaderErrorDomain: &'static ns::ErrorDomain;
static MTKTextureLoaderErrorKey: &'static ns::String;
static MTKTextureLoaderOptionAllocateMipmaps: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionGenerateMipmaps: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionSRGB: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionTextureUsage: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionTextureCPUCacheMode: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionTextureStorageMode: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionOrigin: &'static TextureLoaderOpt;
static MTKTextureLoaderOptionLoadAsArray: &'static TextureLoaderOpt;
static MTKTextureLoaderCubeLayoutVertical: &'static TextureLoaderCubeLayout;
static MTKTextureLoaderOriginTopLeft: &'static TextureLoaderOrigin;
static MTKTextureLoaderOriginBottomLeft: &'static TextureLoaderOrigin;
static MTKTextureLoaderOriginFlippedVertically: &'static TextureLoaderOrigin;
}
#[cfg(test)]
mod tests {
use crate::{mtk, mtl, ns};
#[test]
fn basics() {
let device = mtl::Device::sys_default().unwrap();
let loader = mtk::TextureLoader::with_device(&device);
let url = ns::Url::with_fs_path_str("unknown.png", false);
let err = loader
.new_texture_with_url(&url, None)
.expect_err("Should be err");
assert_eq!(&err.domain(), ns::ErrorDomain::texture_loader());
let user_info = err.user_info();
let _error = user_info.get(mtk::TextureLoader::error_key()).unwrap();
}
#[test]
fn batch() {
let device = mtl::Device::sys_default().unwrap();
let loader = mtk::TextureLoader::with_device(&device);
let url = ns::Url::with_fs_path_str("unknown.png", false);
let urls = ns::Array::from_slice_retained(&[url]);
let (textures, err) = loader.new_textures_with_urls(&urls, None);
assert_eq!(1, textures.len());
assert!(err.is_some());
assert!(textures.get(0).unwrap().is_none());
}
}