333 module.doc() = "Python bindings for the MXVK Vulkan framework.";
335 nb::exception<Exception>(module,
"MXVKError", PyExc_RuntimeError);
337 const std::filesystem::path module_directory = python_module_directory();
338 const std::array<std::filesystem::path, 3> shader_directories{module_directory /
"share" /
"mxvk" /
"shaders", module_directory /
"mxvk" /
"shaders", module_directory /
"shaders"};
339 for (
const std::filesystem::path &shader_directory : shader_directories) {
340 if (std::filesystem::is_directory(shader_directory)) {
346 module.attr("version") = nb::make_tuple(MXVK_VERSION_CODE_MAJOR, MXVK_VERSION_CODE_MINOR, MXVK_VERSION_CODE_PATCH);
347 module.attr("has_cv") = false;
348 module.attr("has_ffmpeg_capture") = false;
349 module.attr("has_mixer") = false;
350 module.attr("has_jpeg") = false;
351 module.attr("EVENT_KEY_DOWN") = static_cast<uint32_t>(SDL_EVENT_KEY_DOWN);
352 module.attr("EVENT_KEY_UP") = static_cast<uint32_t>(SDL_EVENT_KEY_UP);
353 module.attr("EVENT_MOUSE_MOTION") = static_cast<uint32_t>(SDL_EVENT_MOUSE_MOTION);
354 module.attr("EVENT_MOUSE_BUTTON_DOWN") = static_cast<uint32_t>(SDL_EVENT_MOUSE_BUTTON_DOWN);
355 module.attr("EVENT_MOUSE_BUTTON_UP") = static_cast<uint32_t>(SDL_EVENT_MOUSE_BUTTON_UP);
356 module.attr("EVENT_MOUSE_WHEEL") = static_cast<uint32_t>(SDL_EVENT_MOUSE_WHEEL);
357 module.attr("KEY_ESCAPE") = static_cast<int32_t>(SDLK_ESCAPE);
358 module.attr("MOUSE_BUTTON_LEFT") = SDL_BUTTON_LEFT;
359 module.attr("MOUSE_BUTTON_MIDDLE") = SDL_BUTTON_MIDDLE;
360 module.attr("MOUSE_BUTTON_RIGHT") = SDL_BUTTON_RIGHT;
361 module.attr("MOUSE_BUTTON_X1") = SDL_BUTTON_X1;
362 module.attr("MOUSE_BUTTON_X2") = SDL_BUTTON_X2;
363 module.attr("MOD_SHIFT") = static_cast<uint16_t>(SDL_KMOD_SHIFT);
364 module.attr("MOD_CTRL") = static_cast<uint16_t>(SDL_KMOD_CTRL);
365 module.attr("MOD_ALT") = static_cast<uint16_t>(SDL_KMOD_ALT);
366 module.attr("MOD_GUI") = static_cast<uint16_t>(SDL_KMOD_GUI);
368 module.def("set_default_enable_screenshot", &setDefaultEnableScreenshot, nb::arg("enabled"));
369 module.def("default_enable_screenshot", &defaultEnableScreenshot);
370 module.def("set_default_executable_name", &setDefaultExecutableName, nb::arg("name"));
371 module.def("default_executable_name", &defaultExecutableName, nb::rv_policy::copy);
372 module.def("set_default_shader_directory", &setDefaultShaderDirectory, nb::arg("directory"));
373 module.def("default_shader_directory", &defaultShaderDirectory, nb::rv_policy::copy);
376 [](const std::string &name) {
377 const SDL_Keycode key = SDL_GetKeyFromName(name.c_str());
378 if (key == SDLK_UNKNOWN)
379 throw std::invalid_argument(
"unknown SDL key name: " + name);
380 return static_cast<int32_t
>(key);
385 [](int32_t key) -> nb::object {
386 const char *name = SDL_GetKeyName(static_cast<SDL_Keycode>(key));
387 return name ==
nullptr || name[0] ==
'\0' ? nb::none() : nb::cast(std::string(name));
390 module.def("save_png_rgba", [](const std::string &path, nb::ndarray<uint8_t, nb::c_contig, nb::device::cpu> pixels, int width, int height) { return SavePNG_RGBA(path.c_str(), pixels.data(), width, height); }, nb::arg(
"path"), nb::arg(
"pixels"), nb::arg(
"width"), nb::arg(
"height"));
391 module.def("save_png_rgba16", [](const std::string &path, nb::ndarray<uint16_t, nb::c_contig, nb::device::cpu> pixels, int width, int height) { return SavePNG_RGBA16(path.c_str(), pixels.data(), width, height); }, nb::arg(
"path"), nb::arg(
"pixels"), nb::arg(
"width"), nb::arg(
"height"));
392 module.def("inspect_spirv_file", [](const std::string &path) { return inspect_spirv(load_spv(path)); }, nb::arg(
"path"));
394 nb::enum_<StorageImageFormat>(module,
"StorageImageFormat").value(
"unknown", StorageImageFormat::Unknown).value(
"rgba8", StorageImageFormat::Rgba8).value(
"rgba16_float", StorageImageFormat::Rgba16Float);
395 nb::class_<ShaderModuleInfo>(module,
"ShaderModuleInfo").def_ro(
"stage", &ShaderModuleInfo::stage).def_ro(
"local_size_x", &ShaderModuleInfo::localSizeX).def_ro(
"local_size_y", &ShaderModuleInfo::localSizeY).def_ro(
"local_size_z", &ShaderModuleInfo::localSizeZ).def_ro(
"uses_history_texture", &ShaderModuleInfo::usesHistoryTexture).def_ro(
"uses_spectrum_texture", &ShaderModuleInfo::usesSpectrumTexture).def_ro(
"uses_spectrum_history_texture", &ShaderModuleInfo::usesSpectrumHistoryTexture).def_ro(
"storage_image_format", &ShaderModuleInfo::storageImageFormat);
399 module.def("create_uniform_buffer", [](VK_Window &window, size_t size) { return std::make_shared<PythonBuffer>(window.context(), size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); }, nb::arg(
"window"), nb::arg(
"size"), nb::keep_alive<0, 1>());
400 module.def("create_storage_buffer", [](VK_Window &window, size_t size) { return std::make_shared<PythonBuffer>(window.context(), size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); }, nb::arg(
"window"), nb::arg(
"size"), nb::keep_alive<0, 1>());
401 module.def("load_texture", [](VK_Window &window, const std::string &path) { return std::make_shared<PythonTexture>(window.context(), path); }, nb::arg(
"window"), nb::arg(
"path"), nb::keep_alive<0, 1>());
407#if defined(MXVK_WITH_JPEG)
408 module.attr("has_jpeg") = true;
411 [](const std::string &path) -> nb::object {
412 SDL_Surface *loaded = VK_JPEG::Load(path.c_str());
413 if (loaded ==
nullptr)
415 SDL_Surface *rgba = SDL_ConvertSurface(loaded, SDL_PIXELFORMAT_RGBA32);
416 SDL_DestroySurface(loaded);
419 const size_t byte_count =
static_cast<size_t>(rgba->pitch) *
static_cast<size_t>(rgba->h);
420 nb::bytes pixels(
static_cast<const char *
>(rgba->pixels), byte_count);
421 nb::tuple result = nb::make_tuple(pixels, rgba->w, rgba->h, rgba->pitch);
422 SDL_DestroySurface(rgba);
428 [](const std::string &path, nb::ndarray<uint8_t, nb::c_contig, nb::device::cpu> pixels, int width, int height, int quality, int pitch) {
429 if (width <= 0 || height <= 0)
430 throw nb::value_error("width and height must be positive");
433 if (pitch <
width * 4 || pixels.nbytes() <
static_cast<size_t>(pitch) *
static_cast<size_t>(
height))
434 throw nb::value_error(
"RGBA buffer is smaller than pitch * height");
435 SDL_Surface *
surface = SDL_CreateSurfaceFrom(
width,
height, SDL_PIXELFORMAT_RGBA32, pixels.data(), pitch);
437 throw std::runtime_error(SDL_GetError());
438 const bool saved = VK_JPEG::SaveSurface(
surface, path.c_str(), quality);
446 nb::arg(
"quality") = 90,
447 nb::arg(
"pitch") = 0);
450#if defined(MXVK_WITH_MIXER)
451 module.attr("has_mixer") = true;
452 nb::class_<VK_Mixer>(module,
"Mixer").def(nb::init<>()).def(
"init", &VK_Mixer::init).def(
"load_wav", &VK_Mixer::loadWav, nb::arg(
"path")).def(
"load_music", &VK_Mixer::loadMusic, nb::arg(
"path")).def(
"play_music", &VK_Mixer::playMusic, nb::arg(
"id"), nb::arg(
"loops") = 0).def(
"play_wav", &VK_Mixer::playWav, nb::arg(
"id"), nb::arg(
"loops") = 0, nb::arg(
"channel") = -1).def(
"is_playing", &VK_Mixer::isPlaying, nb::arg(
"channel")).def(
"is_music_playing", &VK_Mixer::isMusicPlaying, nb::arg(
"id")).def(
"stop_music", &VK_Mixer::stopMusic).def(
"cleanup", &VK_Mixer::cleanup);
455#if defined(MXVK_WITH_CV)
456 module.attr("has_cv") = true;
457 nb::class_<VK_Capture>(module,
"Capture")
459 .def(
"open", nb::overload_cast<const std::string &>(&VK_Capture::open), nb::arg(
"path"))
460 .def(
"open_camera", nb::overload_cast<int, int>(&VK_Capture::open), nb::arg(
"index"), nb::arg(
"backend") = 0)
461 .def(
"close", &VK_Capture::close)
462 .def(
"is_open", &VK_Capture::is_open)
463 .def(
"reset_sprite", &VK_Capture::resetSprite)
464 .def(
"draw", nb::overload_cast<int, int>(&VK_Capture::draw), nb::arg(
"x"), nb::arg(
"y"))
465 .def(
"draw", nb::overload_cast<int, int, int, int>(&VK_Capture::draw), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"width"), nb::arg(
"height"))
466 .def(
"read", nb::overload_cast<>(&VK_Capture::read))
467 .def(
"grab", &VK_Capture::grab)
470 [](VK_Capture &capture,
bool flip_y) {
472 if (!capture.readRgba(frame, flip_y))
473 return nb::object(nb::none());
474 return opencv_rgba_array(std::move(frame));
476 nb::arg(
"flip_y") =
false)
477 .def(
"read_to_sprite", nb::overload_cast<VK_Sprite &>(&VK_Capture::readToSprite), nb::arg(
"sprite"))
478 .def(
"read_to_sprite", nb::overload_cast<VK_Sprite &, bool>(&VK_Capture::readToSprite), nb::arg(
"sprite"), nb::arg(
"flip_y"))
479 .def(
"read_to_model_texture", &VK_Capture::readToModelTexture, nb::arg(
"model"), nb::arg(
"flip_y") =
false)
480 .def(
"reload", &VK_Capture::reload, nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"vertex_shader_path"), nb::arg(
"fragment_shader_path"))
481 .def_prop_ro(
"sprite", &VK_Capture::getSprite, nb::rv_policy::reference_internal)
482 .def(
"set", &VK_Capture::set, nb::arg(
"property"), nb::arg(
"value"))
483 .def(
"get", &VK_Capture::get, nb::arg(
"property"))
484#if defined(MXVK_CUDA)
486 "read_gpu_rgba_to_host",
487 [](VK_Capture &capture,
bool flip_y) {
488 cv::cuda::GpuMat gpu;
489 if (!capture.readGpuRgba(gpu, flip_y))
490 return nb::object(nb::none());
492 gpu.download(host, capture.cudaStream());
493 capture.cudaStream().waitForCompletion();
494 return opencv_rgba_array(std::move(host));
496 nb::arg(
"flip_y") =
false)
501#if defined(MXVK_WITH_FFMPEG_CAPTURE)
502 module.attr("has_ffmpeg_capture") = true;
503 nb::class_<VK_FF_Capture>(module,
"FFmpegCapture")
505 .def(
"open", nb::overload_cast<const std::string &>(&VK_FF_Capture::open), nb::arg(
"path"))
506 .def(
"open", nb::overload_cast<const std::string &, int>(&VK_FF_Capture::open), nb::arg(
"path"), nb::arg(
"cuda_device"))
507 .def(
"seek_start", &VK_FF_Capture::seek_start)
508 .def(
"skip", &VK_FF_Capture::skip)
509 .def(
"close", &VK_FF_Capture::close)
510 .def(
"is_open", &VK_FF_Capture::is_open)
513 [](VK_FF_Capture &capture,
bool flip_y) -> nb::object {
514 std::vector<uint8_t> pixels;
516 if (!capture.readRgba(pixels,
width,
height, pitch, flip_y))
518 return ffmpeg_rgba8_array(std::move(pixels),
width,
height, pitch);
520 nb::arg(
"flip_y") =
false)
523 [](VK_FF_Capture &capture,
bool flip_y) -> nb::object {
524 std::vector<uint16_t> pixels;
526 if (!capture.readRgba16(pixels,
width,
height, pitch, flip_y))
528 return ffmpeg_rgba16_array(std::move(pixels),
width,
height, pitch);
530 nb::arg(
"flip_y") =
false)
531 .def_prop_ro(
"width", &VK_FF_Capture::width)
532 .def_prop_ro(
"height", &VK_FF_Capture::height)
533 .def_prop_ro(
"fps", &VK_FF_Capture::fps)
534 .def_prop_ro(
"using_hardware_decode", &VK_FF_Capture::using_hardware_decode)
535 .def_prop_ro(
"hardware_decode_device", &VK_FF_Capture::hardware_decode_device)
536#if defined(MXVK_CUDA)
538 "read_gpu_rgba_to_host",
539 [](VK_FF_Capture &capture,
bool flip_y) {
540 cv::cuda::GpuMat gpu;
541 cv::cuda::Stream stream;
542 if (!capture.readGpuRgba(gpu, stream, flip_y))
543 return nb::object(nb::none());
544 stream.waitForCompletion();
547 return opencv_rgba_array(std::move(host));
549 nb::arg(
"flip_y") =
false)
554 nb::class_<VK_ConfigItem>(module,
"ConfigItem").def(nb::init<>()).def_rw(
"key", &VK_ConfigItem::key).def_rw(
"value", &VK_ConfigItem::value);
556 nb::class_<VK_Config>(module,
"Config").def(nb::init<>()).def(nb::init<const std::string &>(), nb::arg(
"file_path")).def(
"item_at_key", &VK_Config::itemAtKey, nb::arg(
"section"), nb::arg(
"key"), nb::arg(
"default_value") =
"").def(
"set_item", &VK_Config::setItem, nb::arg(
"section"), nb::arg(
"key"), nb::arg(
"value")).def(
"load_file", &VK_Config::loadFile, nb::arg(
"path")).def(
"save_file", &VK_Config::saveFile, nb::arg(
"path")).def(
"split_by_comma", &VK_Config::splitByComma, nb::arg(
"value"));
558 nb::class_<VK_Joystick>(module,
"Joystick").def(nb::init<>()).def(
"open", &VK_Joystick::open, nb::arg(
"index")).def(
"close", &VK_Joystick::close).def(
"name", &VK_Joystick::name).def(
"index", &VK_Joystick::joystickIndex).def_static(
"count", &VK_Joystick::joysticks).def(
"num_buttons", &VK_Joystick::numButtons).def(
"num_hats", &VK_Joystick::numHats).def(
"num_axes", &VK_Joystick::numAxes).def(
"button", &VK_Joystick::getButton, nb::arg(
"index")).def(
"hat", &VK_Joystick::getHat, nb::arg(
"index")).def(
"axis", &VK_Joystick::getAxis, nb::arg(
"index"));
560 nb::class_<VK_Controller>(module,
"Controller").def(nb::init<>()).def(
"open", &VK_Controller::open, nb::arg(
"index")).def(
"close", &VK_Controller::close).def(
"name", &VK_Controller::name).def(
"index", &VK_Controller::controllerIndex).def_static(
"count", &VK_Controller::joysticks).def(
"button", [](
const VK_Controller &controller,
int button) {
return controller.getButton(
static_cast<SDL_GamepadButton
>(
button)); }, nb::arg(
"button")).def(
"hat", &VK_Controller::getHat, nb::arg(
"index")).def(
"axis", [](
const VK_Controller &controller,
int axis) {
return controller.getAxis(
static_cast<SDL_GamepadAxis
>(axis)); }, nb::arg(
"axis")).def(
"active", &VK_Controller::active);
562 nb::class_<VKVertex>(module,
"Vertex").def(nb::init<>()).def_prop_rw(
"position", [](
const VKVertex &value) {
return nb::make_tuple(value.pos[0], value.pos[1], value.pos[2]); }, [](VKVertex &value,
const std::array<float, 3> &position) { std::copy(position.begin(), position.end(), value.pos); }).def_prop_rw(
"tex_coord", [](
const VKVertex &value) {
return nb::make_tuple(value.texCoord[0], value.texCoord[1]); }, [](VKVertex &value,
const std::array<float, 2> &tex_coord) { std::copy(tex_coord.begin(), tex_coord.end(), value.texCoord); }).def_prop_rw(
"normal", [](
const VKVertex &value) {
return nb::make_tuple(value.normal[0], value.normal[1], value.normal[2]); }, [](VKVertex &value,
const std::array<float, 3> &normal) { std::copy(normal.begin(), normal.end(), value.normal); });
564 nb::class_<SubMesh>(module,
"SubMesh").def(nb::init<>()).def_rw(
"first_index", &SubMesh::firstIndex).def_rw(
"index_count", &SubMesh::indexCount).def_rw(
"texture_index", &SubMesh::textureIndex).def_rw(
"material_name", &SubMesh::materialName);
566 nb::class_<MXMaterial>(module,
"Material").def(nb::init<>()).def_rw(
"name", &MXMaterial::name).def_prop_rw(
"ambient", [](
const MXMaterial &value) {
return nb::make_tuple(value.ka[0], value.ka[1], value.ka[2]); }, [](MXMaterial &value,
const std::array<float, 3> &ambient) { std::copy(ambient.begin(), ambient.end(), value.ka); }).def_prop_rw(
"diffuse", [](
const MXMaterial &value) {
return nb::make_tuple(value.kd[0], value.kd[1], value.kd[2]); }, [](MXMaterial &value,
const std::array<float, 3> &diffuse) { std::copy(diffuse.begin(), diffuse.end(), value.kd); }).def_prop_rw(
"specular", [](
const MXMaterial &value) {
return nb::make_tuple(value.ks[0], value.ks[1], value.ks[2]); }, [](MXMaterial &value,
const std::array<float, 3> &specular) { std::copy(specular.begin(), specular.end(), value.ks); }).def_rw(
"shininess", &MXMaterial::ns).def_rw(
"opacity", &MXMaterial::d).def_rw(
"illumination_model", &MXMaterial::illum).def_rw(
"diffuse_map", &MXMaterial::map_kd);
568 nb::class_<MXModel>(module,
"Model")
570 .def(
"load", nb::overload_cast<const std::string &, float>(&MXModel::load), nb::arg(
"path"), nb::arg(
"position_scale") = 1.0F)
571 .def(
"load", nb::overload_cast<const std::string &, const std::string &, const std::string &, float>(&MXModel::load), nb::arg(
"path"), nb::arg(
"texture_manifest_path"), nb::arg(
"texture_base_path"), nb::arg(
"position_scale") = 1.0F)
572 .def(
"export_obj", nb::overload_cast<const std::string &, const std::string &>(&MXModel::exportOBJ, nb::const_), nb::arg(
"obj_path"), nb::arg(
"mtl_path") =
"")
573 .def_static(
"export_obj_from_file", nb::overload_cast<const std::string &, const std::string &, const std::string &, const std::string &, float>(&MXModel::exportOBJ), nb::arg(
"model_path"), nb::arg(
"texture_manifest_path"), nb::arg(
"texture_base_path"), nb::arg(
"obj_path"), nb::arg(
"position_scale") = 1.0F)
574 .def(
"compress_indices", &MXModel::compressIndices)
575 .def_prop_ro(
"vertices", &MXModel::vertices, nb::rv_policy::copy)
576 .def_prop_ro(
"indices", &MXModel::indices, nb::rv_policy::copy)
577 .def_prop_ro(
"index_count", &MXModel::indexCount)
578 .def_prop_ro(
"sub_mesh_count", &MXModel::subMeshCount)
579 .def_prop_ro(
"sub_meshes", &MXModel::subMeshes, nb::rv_policy::copy)
580 .def_prop_ro(
"materials", &MXModel::materials, nb::rv_policy::copy)
581 .def_prop_ro(
"material_library_path", &MXModel::mtlLibPath, nb::rv_policy::copy);
583 nb::class_<SDL_Color>(module,
"Color").def(nb::init<>()).def(nb::init<uint8_t, uint8_t, uint8_t, uint8_t>(), nb::arg(
"red"), nb::arg(
"green"), nb::arg(
"blue"), nb::arg(
"alpha") = 255).def_rw(
"red", &SDL_Color::r).def_rw(
"green", &SDL_Color::g).def_rw(
"blue", &SDL_Color::b).def_rw(
"alpha", &SDL_Color::a);
585 nb::class_<VK_Console>(module,
"Console")
587 .def(
"attach", &VK_Console::attach, nb::arg(
"window"), nb::arg(
"font_path"), nb::arg(
"font_size") = 18)
588 .def(
"set_font", &VK_Console::setFont, nb::arg(
"font_path"), nb::arg(
"font_size"))
589 .def(
"draw", &VK_Console::draw)
590 .def(
"print_line", &VK_Console::printLine, nb::arg(
"line"), nb::arg(
"color") = SDL_Color{255, 255, 255, 255})
591 .def(
"clear", &VK_Console::clear)
592 .def(
"set_prompt", &VK_Console::setPrompt, nb::arg(
"prompt"))
593 .def(
"set_visible", &VK_Console::setVisible, nb::arg(
"visible"))
594 .def(
"show", &VK_Console::show)
595 .def(
"hide", &VK_Console::hide)
596 .def(
"toggle", &VK_Console::toggle)
597 .def(
"visible", &VK_Console::isVisible)
598 .def(
"set_max_lines", &VK_Console::setMaxLines, nb::arg(
"count"))
599 .def(
"set_max_visible_lines", &VK_Console::setMaxVisibleLines, nb::arg(
"count"))
600 .def(
"set_sprite_y_origin_top_left", &VK_Console::setSpriteYOriginTopLeft, nb::arg(
"enabled"))
601 .def_prop_ro(
"input_buffer", &VK_Console::inputBuffer, nb::rv_policy::copy);
603 nb::class_<PointSpriteVertex>(module,
"PointSpriteVertex").def(nb::init<>()).def_prop_rw(
"position", [](
const PointSpriteVertex &value) {
return nb::make_tuple(value.position[0], value.position[1], value.position[2]); }, [](PointSpriteVertex &value,
const std::array<float, 3> &position) { std::copy(position.begin(), position.end(), value.position); }).def_rw(
"size", &PointSpriteVertex::size).def_prop_rw(
"color", [](
const PointSpriteVertex &value) {
return nb::make_tuple(value.color[0], value.color[1], value.color[2], value.color[3]); }, [](PointSpriteVertex &value,
const std::array<float, 4> &color) { std::copy(color.begin(), color.end(), value.color); });
605 nb::class_<VK_PointSpriteBatch>(module,
"PointSpriteBatch")
607 .def(
"load", &VK_PointSpriteBatch::load, nb::arg(
"window"), nb::arg(
"texture_path"), nb::arg(
"vertex_shader_path"), nb::arg(
"fragment_shader_path"), nb::arg(
"max_vertices"))
608 .def(
"resize", &VK_PointSpriteBatch::resize, nb::arg(
"window"))
609 .def(
"cleanup", &VK_PointSpriteBatch::cleanup)
612 [](VK_PointSpriteBatch &batch,
const std::vector<PointSpriteVertex> &vertices) { batch.upload_vertices(vertices.data(), vertices.size()); },
614 .def(
"set_additive_blending", &VK_PointSpriteBatch::set_additive_blending, nb::arg(
"enabled"))
615 .def(
"set_depth_test_enabled", &VK_PointSpriteBatch::set_depth_test_enabled, nb::arg(
"enabled"))
616 .def(
"set_depth_write_enabled", &VK_PointSpriteBatch::set_depth_write_enabled, nb::arg(
"enabled"))
617 .def_prop_ro(
"loaded", &VK_PointSpriteBatch::loaded)
618 .def_prop_ro(
"capacity", &VK_PointSpriteBatch::capacity)
619 .def_prop_ro(
"vertex_count", &VK_PointSpriteBatch::vertex_count);
621 nb::class_<BufferResource>(module,
"BufferResource").def(nb::init<>()).def_rw(
"size", &BufferResource::size).def_prop_ro(
"buffer", [](
const BufferResource &value) {
return reinterpret_cast<uintptr_t
>(value.buffer); }).def_prop_ro(
"memory", [](
const BufferResource &value) {
return reinterpret_cast<uintptr_t
>(value.memory); }).def_prop_ro(
"mapped", [](
const BufferResource &value) {
return reinterpret_cast<uintptr_t
>(value.mapped); });
623 nb::class_<TextureResource>(module,
"TextureResource").def(nb::init<>()).def_rw(
"width", &TextureResource::width).def_rw(
"height", &TextureResource::height).def_prop_ro(
"image", [](
const TextureResource &value) {
return reinterpret_cast<uintptr_t
>(value.image); }).def_prop_ro(
"memory", [](
const TextureResource &value) {
return reinterpret_cast<uintptr_t
>(value.memory); }).def_prop_ro(
"view", [](
const TextureResource &value) {
return reinterpret_cast<uintptr_t
>(value.view); }).def_prop_ro(
"sampler", [](
const TextureResource &value) {
return reinterpret_cast<uintptr_t
>(value.sampler); });
625 nb::class_<VK_Stencil::PushConstants>(module,
"StencilPushConstants").def(nb::init<>()).def_rw(
"time", &VK_Stencil::PushConstants::time).def_rw(
"aspect", &VK_Stencil::PushConstants::aspect).def_rw(
"phase", &VK_Stencil::PushConstants::phase).def_rw(
"scale", &VK_Stencil::PushConstants::scale);
627 nb::class_<VK_Stencil>(module,
"Stencil")
629 .def(
"destroy", &VK_Stencil::destroy)
635 .def(
"valid", &VK_Stencil::valid)
636 .def_prop_ro(
"format", [](
const VK_Stencil &value) {
return static_cast<int>(value.stencil_format()); })
637 .def_prop_ro(
"extent", [](
const VK_Stencil &value) {
638 const auto extent = value.extent();
639 return nb::make_tuple(extent.width, extent.height);
642 nb::class_<Font>(module,
"Font").def(nb::init<>()).def(nb::init<const std::string &, int>(), nb::arg(
"path"), nb::arg(
"size")).def(
"reset", nb::overload_cast<>(&Font::reset)).def(
"reset", nb::overload_cast<const std::string &, int>(&Font::reset), nb::arg(
"path"), nb::arg(
"size")).def(
"valid", [](
const Font &font) {
return static_cast<bool>(font); }).def_prop_ro(
"path", &Font::path).def_prop_ro(
"size", &Font::size);
644 nb::class_<UniformBufferObject>(module,
"ModelUniforms").def(nb::init<>()).def_prop_rw(
"model", [](
const UniformBufferObject &value) {
return matrix_to_rows(value.model); }, [](UniformBufferObject &value,
const std::array<float, 16> &
matrix) { value.model =
matrix_from_rows(
matrix); }).def_prop_rw(
"view", [](
const UniformBufferObject &value) {
return matrix_to_rows(value.view); }, [](UniformBufferObject &value,
const std::array<float, 16> &
matrix) { value.view =
matrix_from_rows(
matrix); }).def_prop_rw(
"projection", [](
const UniformBufferObject &value) {
return matrix_to_rows(value.proj); }, [](UniformBufferObject &value,
const std::array<float, 16> &
matrix) { value.proj =
matrix_from_rows(
matrix); }).def_prop_rw(
"effects", [](
const UniformBufferObject &value) {
return vector4_array(value.fx); }, [](UniformBufferObject &value,
const std::array<float, 4> &effects) { value.fx =
vector4(effects); });
646 nb::class_<ModelFragmentPushConstants>(module,
"ModelFragmentPushConstants").def(nb::init<>()).def_rw(
"screen_width", &ModelFragmentPushConstants::screenWidth).def_rw(
"screen_height", &ModelFragmentPushConstants::screenHeight).def_rw(
"sprite_x", &ModelFragmentPushConstants::spritePosX).def_rw(
"sprite_y", &ModelFragmentPushConstants::spritePosY).def_rw(
"sprite_width", &ModelFragmentPushConstants::spriteSizeW).def_rw(
"sprite_height", &ModelFragmentPushConstants::spriteSizeH).def_rw(
"effects_enabled", &ModelFragmentPushConstants::effectsOn).def_prop_rw(
"params", [](
const ModelFragmentPushConstants &value) {
return vector4_array(value.params); }, [](ModelFragmentPushConstants &value,
const std::array<float, 4> ¶ms) { value.params =
vector4(params); });
648 nb::class_<ModelFragmentUniforms>(module,
"ModelFragmentUniforms")
652 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.mouse); },
653 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.mouse =
vector4(data); })
656 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.u0); },
657 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.u0 =
vector4(data); })
660 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.u1); },
661 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.u1 =
vector4(data); })
664 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.u2); },
665 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.u2 =
vector4(data); })
668 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.u3); },
669 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.u3 =
vector4(data); })
672 [](
const ModelFragmentUniforms &value) {
673 std::vector<std::array<float, 4>> result;
674 result.reserve(value.custom_uniforms.size());
675 for (
const auto &entry : value.custom_uniforms)
679 [](ModelFragmentUniforms &value,
const std::vector<std::array<float, 4>> &data) {
680 if (data.size() > value.custom_uniforms.size())
681 throw nb::value_error(
"at most 16 custom uniforms are supported");
682 value.custom_uniforms.fill(glm::vec4{0.0F});
683 for (
size_t index = 0; index < data.size(); ++index)
684 value.custom_uniforms[index] =
vector4(data[index]);
688 [](
const ModelFragmentUniforms &value) {
return vector4_array(value.audio_bands); },
689 [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.audio_bands =
vector4(data); })
690 .def_prop_rw(
"audio_history", [](
const ModelFragmentUniforms &value) {
return vector4_array(value.audio_history); }, [](ModelFragmentUniforms &value,
const std::array<float, 4> &data) { value.audio_history =
vector4(data); });
692 nb::class_<VKAbstractModel>(module,
"AbstractModel")
694 .def(
"load", nb::overload_cast<VK_Window *, const std::string &, const std::string &, const std::string &, float>(&VKAbstractModel::load), nb::arg(
"window"), nb::arg(
"model_path"), nb::arg(
"texture_manifest_path") =
"", nb::arg(
"texture_base_path") =
"", nb::arg(
"scale") = 1.0F, nb::keep_alive<1, 2>())
695 .def(
"set_shaders", &VKAbstractModel::setShaders, nb::arg(
"window"), nb::arg(
"vertex_shader_path"), nb::arg(
"fragment_shader_path"))
696 .def(
"update_uniforms", &VKAbstractModel::updateUBO, nb::arg(
"image_index"), nb::arg(
"uniforms"))
697 .def(
"enable_extended_fragment_uniforms", &VKAbstractModel::enableExtendedFragmentUniforms)
698 .def(
"update_fragment_uniforms", &VKAbstractModel::updateFragmentUBO, nb::arg(
"image_index"), nb::arg(
"uniforms"))
699 .def(
"set_fragment_push_constants", &VKAbstractModel::setFragmentPushConstants, nb::arg(
"constants"))
701 "update_primary_texture",
702 [](VKAbstractModel &
model, nb::ndarray<uint8_t, nb::c_contig, nb::device::cpu> pixels,
int width,
int height,
int pitch) {
704 throw nb::value_error(
"width and height must be positive");
707 if (pitch <
width * 4 || pixels.nbytes() <
static_cast<size_t>(pitch) *
static_cast<size_t>(
height))
708 throw nb::value_error(
"RGBA buffer is smaller than pitch * height");
714 nb::arg(
"pitch") = 0)
717 [](
const VKAbstractModel &
model, nb::capsule command_buffer, uint32_t image_index,
bool wireframe) {
718 auto command =
static_cast<VkCommandBuffer
>(command_buffer.data());
719 if (command == VK_NULL_HANDLE)
720 throw nb::value_error(
"command_buffer capsule must contain a VkCommandBuffer pointer");
721 model.render(command, image_index, wireframe);
723 nb::arg(
"command_buffer"),
724 nb::arg(
"image_index"),
725 nb::arg(
"wireframe") =
false)
727 "render_with_push_constants",
728 [](VKAbstractModel &
model, nb::capsule command_buffer, uint32_t image_index,
size_t texture_index,
const UniformBufferObject &uniforms,
bool wireframe) {
729 auto command =
static_cast<VkCommandBuffer
>(command_buffer.data());
730 if (command == VK_NULL_HANDLE)
731 throw nb::value_error(
"command_buffer capsule must contain a VkCommandBuffer pointer");
732 model.renderWithPushConstants(command, image_index, texture_index, uniforms, wireframe);
734 nb::arg(
"command_buffer"),
735 nb::arg(
"image_index"),
736 nb::arg(
"texture_index"),
738 nb::arg(
"wireframe") =
false)
739 .def(
"resize", &VKAbstractModel::resize, nb::arg(
"window"))
740 .def(
"cleanup", &VKAbstractModel::cleanup, nb::arg(
"window"))
741 .def(
"set_backface_culling", &VKAbstractModel::setBackfaceCulling, nb::arg(
"enabled"))
742 .def(
"set_alpha_blending", &VKAbstractModel::setAlphaBlending, nb::arg(
"enabled"))
744 "set_color_attachment_format",
745 [](VKAbstractModel &
model,
int format) {
model.setColorAttachmentFormat(
static_cast<VkFormat
>(format)); },
747 .def_prop_ro(
"model", &VKAbstractModel::model, nb::rv_policy::reference_internal)
748 .def_prop_ro(
"center_offset",
749 [](
const VKAbstractModel &
model) {
750 const auto value =
model.modelCenterOffset();
751 return nb::make_tuple(value.x, value.y, value.z);
753 .def_prop_ro(
"render_scale", &VKAbstractModel::modelRenderScale)
754 .def_prop_ro(
"axis_extent",
755 [](
const VKAbstractModel &
model) {
756 const auto value =
model.modelAxisExtent();
757 return nb::make_tuple(value.x, value.y, value.z);
759 .def_prop_ro(
"loaded", &VKAbstractModel::isLoaded);
761 auto sprite = nb::class_<VK_Sprite>(module,
"Sprite");
762 sprite.def(
"load", nb::overload_cast<const std::string &, const std::string &>(&VK_Sprite::loadSprite), nb::arg(
"path"), nb::arg(
"fragment_shader_path") =
"")
763 .def(
"create_empty", &VK_Sprite::createEmptySprite, nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"vertex_shader_path") =
"", nb::arg(
"fragment_shader_path") =
"")
764 .def(
"create_empty_rgba16", &VK_Sprite::createEmptySpriteRgba16, nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"vertex_shader_path") =
"", nb::arg(
"fragment_shader_path") =
"")
765 .def(
"draw", nb::overload_cast<int, int>(&VK_Sprite::drawSprite), nb::arg(
"x"), nb::arg(
"y"))
766 .def(
"draw", nb::overload_cast<int, int, float, float>(&VK_Sprite::drawSprite), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"scale_x"), nb::arg(
"scale_y"))
767 .def(
"draw_rotated", nb::overload_cast<int, int, float, float, float>(&VK_Sprite::drawSprite), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"scale_x"), nb::arg(
"scale_y"), nb::arg(
"rotation"))
768 .def(
"draw_rect", &VK_Sprite::drawSpriteRect, nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"width"), nb::arg(
"height"))
771 [](VK_Sprite &value, nb::ndarray<uint8_t, nb::c_contig, nb::device::cpu> pixels,
int width,
int height,
int pitch) { value.updateTexture(pixels.data(),
width,
height, pitch); },
775 nb::arg(
"pitch") = 0)
777 "update_texture_rgba16",
778 [](VK_Sprite &value, nb::ndarray<uint16_t, nb::c_contig, nb::device::cpu> pixels,
int width,
int height,
int pitch) { value.updateTextureRgba16(pixels.data(),
width,
height, pitch); },
782 nb::arg(
"pitch") = 0)
783 .def(
"set_shader_params", &VK_Sprite::setShaderParams, nb::arg(
"p1") = 0.0F, nb::arg(
"p2") = 0.0F, nb::arg(
"p3") = 0.0F, nb::arg(
"p4") = 0.0F)
784 .def(
"set_effects_enabled", &VK_Sprite::setEffectsEnabled, nb::arg(
"enabled"))
785 .def(
"effects_enabled", &VK_Sprite::getEffectsEnabled)
786 .def(
"clear_queue", &VK_Sprite::clearQueue)
787 .def(
"set_vertex_shader_path", &VK_Sprite::setVertexShaderPath, nb::arg(
"path"))
788 .def(
"set_fragment_shader_path", &VK_Sprite::setFragmentShaderPath, nb::arg(
"path"))
789 .def(
"enable_compute_shader", &VK_Sprite::enableComputeShader, nb::arg(
"path"), nb::arg(
"local_size_x"), nb::arg(
"local_size_y"), nb::arg(
"local_size_z") = 1)
790 .def(
"enable_instancing", &VK_Sprite::enableInstancing, nb::arg(
"max_instances"), nb::arg(
"vertex_shader_path"), nb::arg(
"fragment_shader_path"))
791 .def(
"instancing_enabled", &VK_Sprite::isInstancingEnabled)
792 .def(
"enable_extended_ubo", &VK_Sprite::enableExtendedUBO)
793 .def(
"extended_ubo_enabled", &VK_Sprite::isExtendedUBOEnabled)
794 .def(
"set_mouse_state", &VK_Sprite::setMouseState, nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"pressed"), nb::arg(
"reserved") = 0.0F)
795 .def(
"set_uniform0", &VK_Sprite::setUniform0)
796 .def(
"set_uniform1", &VK_Sprite::setUniform1)
797 .def(
"set_uniform2", &VK_Sprite::setUniform2)
798 .def(
"set_uniform3", &VK_Sprite::setUniform3)
799 .def(
"set_audio_bands", &VK_Sprite::setAudioBands, nb::arg(
"low"), nb::arg(
"mid"), nb::arg(
"high"), nb::arg(
"reserved") = 0.0F)
800 .def(
"set_custom_uniforms", &VK_Sprite::setCustomUniforms, nb::arg(
"values"))
801 .def(
"enable_history_texture", &VK_Sprite::enableHistoryTexture, nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"layers"))
802 .def(
"enable_history_texture_rgba16", &VK_Sprite::enableHistoryTextureRgba16Float, nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"layers"))
803 .def(
"share_history_texture", &VK_Sprite::shareHistoryTexture, nb::arg(
"source"))
804 .def(
"enable_spectrum_texture", &VK_Sprite::enableSpectrumTexture, nb::arg(
"bins"))
805 .def(
"enable_spectrum_history_texture", &VK_Sprite::enableSpectrumHistoryTexture, nb::arg(
"bins"), nb::arg(
"layers"))
806 .def_prop_ro(
"width", &VK_Sprite::getWidth)
807 .def_prop_ro(
"height", &VK_Sprite::getHeight)
808 .def_prop_ro(
"has_own_pipeline", &VK_Sprite::hasOwnPipeline);
810 auto sprite3d = nb::class_<VK_Sprite3D>(module,
"Sprite3D");
811 sprite3d.def(nb::init<>())
812 .def(
"load", nb::overload_cast<VK_Window *, const std::string &, const std::string &, const std::string &>(&VK_Sprite3D::load), nb::arg(
"window"), nb::arg(
"path"), nb::arg(
"vertex_shader_path") =
"", nb::arg(
"fragment_shader_path") =
"")
815 [](VK_Sprite3D &value, uint32_t image_index,
const std::array<float, 16> &view,
const std::array<float, 16> &projection) { value.updateCamera(image_index,
matrix_from_rows(view),
matrix_from_rows(projection)); },
816 nb::arg(
"image_index"),
818 nb::arg(
"projection"))
821 [](VK_Sprite3D &value,
const std::array<float, 3> &position,
const std::array<float, 2> &
size,
const std::array<float, 4> &color,
float rotation) { value.drawSprite(glm::vec3{position[0], position[1], position[2]}, glm::vec2{
size[0],
size[1]},
vector4(color), rotation); },
824 nb::arg(
"color") = std::array<float, 4>{1.0F, 1.0F, 1.0F, 1.0F},
825 nb::arg(
"rotation") = 0.0F)
828 [](VK_Sprite3D &value, nb::capsule command_buffer, uint32_t image_index) {
829 auto command =
static_cast<VkCommandBuffer
>(command_buffer.data());
830 if (command == VK_NULL_HANDLE)
831 throw nb::value_error(
"command_buffer capsule must contain a VkCommandBuffer pointer");
832 value.render(command, image_index);
834 nb::arg(
"command_buffer"),
835 nb::arg(
"image_index"))
836 .def(
"clear_queue", &VK_Sprite3D::clearQueue)
837 .def(
"set_depth_test_enabled", &VK_Sprite3D::setDepthTestEnabled, nb::arg(
"enabled"))
838 .def(
"set_depth_write_enabled", &VK_Sprite3D::setDepthWriteEnabled, nb::arg(
"enabled"))
839 .def(
"set_alpha_discard_threshold", &VK_Sprite3D::setAlphaDiscardThreshold, nb::arg(
"threshold"))
840 .def(
"resize", &VK_Sprite3D::resize, nb::arg(
"window"))
841 .def(
"cleanup", &VK_Sprite3D::cleanup)
842 .def_prop_ro(
"loaded", &VK_Sprite3D::loaded)
843 .def_prop_ro(
"width", &VK_Sprite3D::getWidth)
844 .def_prop_ro(
"height", &VK_Sprite3D::getHeight);
846 nb::enum_<ShaderStage>(module,
"ShaderStage").value(
"unknown", ShaderStage::Unknown).value(
"vertex", ShaderStage::Vertex).value(
"fragment", ShaderStage::Fragment).value(
"compute", ShaderStage::Compute);
848 nb::enum_<VK_Window::PresentModePreference>(module,
"PresentModePreference").value(
"low_latency", VK_Window::PresentModePreference::LowLatency).value(
"vsync", VK_Window::PresentModePreference::Vsync);
850 nb::enum_<VK_Window::RuntimeMode>(module,
"RuntimeMode").value(
"windowed", VK_Window::RuntimeMode::Windowed).value(
"headless", VK_Window::RuntimeMode::Headless);
852 nb::class_<VulkanContext>(module,
"VulkanContext").def_prop_ro(
"device", [](
const VulkanContext &context) {
return reinterpret_cast<uintptr_t
>(context.device); }).def_prop_ro(
"physical_device", [](
const VulkanContext &context) {
return reinterpret_cast<uintptr_t
>(context.physical_device); }).def_prop_ro(
"graphics_queue", [](
const VulkanContext &context) {
return reinterpret_cast<uintptr_t
>(context.graphics_queue); }).def_prop_ro(
"command_pool", [](
const VulkanContext &context) {
return reinterpret_cast<uintptr_t
>(context.command_pool); });
854 nb::class_<VK_Window::PostProcessingEffect>(module,
"PostProcessingEffect").def(nb::init<>()).def_rw(
"fragment_shader_path", &VK_Window::PostProcessingEffect::fragmentShaderPath).def_rw(
"params", &VK_Window::PostProcessingEffect::params).def_rw(
"time_enabled", &VK_Window::PostProcessingEffect::timeEnabled).def_rw(
"spectrum_bin_count", &VK_Window::PostProcessingEffect::spectrumBinCount).def_rw(
"spectrum_history_layer_count", &VK_Window::PostProcessingEffect::spectrumHistoryLayerCount).def_rw(
"stage", &VK_Window::PostProcessingEffect::stage).def_rw(
"history_source", &VK_Window::PostProcessingEffect::historySource);
856 nb::class_<VK_Window, PythonWindow>(module,
"Window")
858 .def(nb::init<const std::string &, int, int, bool, bool, VK_Window::PresentModePreference, VK_Window::RuntimeMode>(), nb::arg(
"title"), nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"fullscreen") =
false, nb::arg(
"validation") =
true, nb::arg(
"present_mode") = VK_Window::PresentModePreference::LowLatency, nb::arg(
"runtime_mode") = VK_Window::RuntimeMode::Windowed)
859 .def(nb::init<const std::string &, int, int, bool, bool, bool>(), nb::arg(
"title"), nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"fullscreen"), nb::arg(
"validation"), nb::arg(
"enable_vsync"))
860 .def(
"release", &VK_Window::release)
861 .def(
"wait_idle", [](VK_Window &window) {
862 const VkDevice device = window.getDevice();
863 if (device == VK_NULL_HANDLE)
866 const VkResult result = vkDeviceWaitIdle(device);
867 if (result != VK_SUCCESS)
868 throw std::runtime_error(
"vkDeviceWaitIdle failed");
870 .def(
"request_exit", [](VK_Window &window) {
871 auto *python_window =
dynamic_cast<PythonWindow *
>(&window);
872 if (python_window ==
nullptr)
873 throw nb::type_error(
"request_exit requires a Python subclass of Window");
874 python_window->request_exit();
876 .def(
"init_vulkan", &VK_Window::initVulkan, nb::arg(
"validation") =
true)
879 [](VK_Window &window, nb::capsule
event) {
880 auto *sdl_event =
static_cast<SDL_Event *
>(
event.data());
881 if (sdl_event ==
nullptr)
882 throw nb::value_error(
"event capsule must contain an SDL_Event pointer");
883 window.event(*sdl_event);
886 .def(
"loop", &VK_Window::loop)
887 .def(
"render", &VK_Window::render)
888 .def(
"on_swapchain_recreated", [](VK_Window &) {})
889 .def(
"on_frame_readback_scheduled", [](VK_Window &) {})
890 .def(
"on_frame_readback", [](VK_Window &, nb::ndarray<nb::numpy, std::uint8_t>, uint32_t, uint32_t) {}, nb::arg(
"pixels"), nb::arg(
"width"), nb::arg(
"height"))
892 "flush_frame_readbacks",
893 [](VK_Window &window) {
894 auto *python_window =
dynamic_cast<PythonWindow *
>(&window);
895 if (python_window ==
nullptr)
896 throw nb::type_error(
"flush_frame_readbacks requires a Python subclass of Window");
897 python_window->flush_frame_readbacks();
899 .def(
"on_record_custom_rendering", [](VK_Window &, nb::capsule, uint32_t) {}, nb::arg(
"command_buffer"), nb::arg(
"image_index"))
901 "on_prepare_frame_rendering",
902 [](VK_Window &window, nb::capsule command_buffer, uint32_t image_index) {
903 auto command_buffer_handle =
static_cast<VkCommandBuffer
>(command_buffer.data());
904 if (command_buffer_handle == VK_NULL_HANDLE)
905 throw nb::value_error(
"command_buffer capsule must contain a VkCommandBuffer pointer");
906 window.onPrepareFrameRendering(command_buffer_handle, image_index);
908 nb::arg(
"command_buffer"),
909 nb::arg(
"image_index"))
910 .def(
"proc", &VK_Window::proc)
911 .def(
"save_snapshot", &VK_Window::saveSnapshot, nb::arg(
"path"))
912 .def(
"set_font", &VK_Window::setFont, nb::arg(
"path"), nb::arg(
"size") = 24)
913 .def(
"set_preview_font", &VK_Window::setPreviewFont, nb::arg(
"path"), nb::arg(
"size") = 24)
914 .def(
"print_text", nb::overload_cast<const std::string &, int, int, const SDL_Color &>(&VK_Window::printText), nb::arg(
"text"), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"color"))
915 .def(
"print_text", nb::overload_cast<const std::string &, int, int, const SDL_Color &, const Font &>(&VK_Window::printText), nb::arg(
"text"), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"color"), nb::arg(
"font"))
916 .def(
"print_preview_text", nb::overload_cast<const std::string &, int, int, const SDL_Color &>(&VK_Window::printPreviewText), nb::arg(
"text"), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"color"))
917 .def(
"print_preview_text", nb::overload_cast<const std::string &, int, int, const SDL_Color &, const Font &>(&VK_Window::printPreviewText), nb::arg(
"text"), nb::arg(
"x"), nb::arg(
"y"), nb::arg(
"color"), nb::arg(
"font"))
918 .def(
"clear_text_queue", &VK_Window::clearTextQueue)
919 .def(
"set_clear_color", &VK_Window::setClearColor, nb::arg(
"red"), nb::arg(
"green"), nb::arg(
"blue"), nb::arg(
"alpha") = 1.0F)
920 .def(
"set_enable_screenshot", &VK_Window::setEnableScreenshot, nb::arg(
"enabled"))
921 .def(
"screenshot_enabled", &VK_Window::screenshotEnabled)
922 .def(
"set_frame_readback_enabled", &VK_Window::setFrameReadbackEnabled, nb::arg(
"enabled"))
923 .def(
"set_frame_readback_rgba16_enabled", &VK_Window::setFrameReadbackRgba16Enabled, nb::arg(
"enabled"))
924 .def(
"set_hdr_render_intermediates_enabled", &VK_Window::setHdrRenderIntermediatesEnabled, nb::arg(
"enabled"))
925 .def(
"set_render_extent", &VK_Window::setRenderExtent, nb::arg(
"width"), nb::arg(
"height"))
926 .def(
"headless", &VK_Window::headless)
927 .def(
"ensure_render_resources", &VK_Window::ensureRenderResources)
928 .def(
"trim_memory", &VK_Window::trimMemory)
930 "get_text_dimensions",
931 [](VK_Window &window,
const std::string &
text) -> nb::object {
940 "get_text_dimensions",
941 [](VK_Window &window,
const std::string &
text,
const Font &font) -> nb::object {
952 [](VK_Window &window,
const std::string &path,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path) {
return window.createSprite(path, vertex_shader_path, fragment_shader_path); },
954 nb::arg(
"vertex_shader_path") =
"",
955 nb::arg(
"fragment_shader_path") =
"",
956 nb::rv_policy::reference_internal)
958 "create_sprite_from_surface",
959 [](VK_Window &window, nb::capsule
surface,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path) {
960 auto *sdl_surface =
static_cast<SDL_Surface *
>(
surface.data());
961 if (sdl_surface ==
nullptr)
962 throw nb::value_error(
"surface capsule must contain an SDL_Surface pointer");
963 return window.createSprite(sdl_surface, vertex_shader_path, fragment_shader_path);
966 nb::arg(
"vertex_shader_path") =
"",
967 nb::arg(
"fragment_shader_path") =
"",
968 nb::rv_policy::reference_internal)
971 [](VK_Window &window,
int width,
int height,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path, uint32_t spectrum_bin_count) {
return window.createSprite(
width,
height, vertex_shader_path, fragment_shader_path, spectrum_bin_count); },
974 nb::arg(
"vertex_shader_path") =
"",
975 nb::arg(
"fragment_shader_path") =
"",
976 nb::arg(
"spectrum_bin_count") = 0,
977 nb::rv_policy::reference_internal)
979 "create_sprite_with_spectrum_history",
980 [](VK_Window &window,
int width,
int height,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path, uint32_t spectrum_bin_count, uint32_t spectrum_history_layer_count) {
return window.createSprite(
width,
height, vertex_shader_path, fragment_shader_path, spectrum_bin_count, spectrum_history_layer_count); },
983 nb::arg(
"vertex_shader_path"),
984 nb::arg(
"fragment_shader_path"),
985 nb::arg(
"spectrum_bin_count"),
986 nb::arg(
"spectrum_history_layer_count"),
987 nb::rv_policy::reference_internal)
988 .def(
"attach_post_processing_shader", &VK_Window::attachPostProcessingShader, nb::arg(
"fragment_shader_path"), nb::arg(
"p1") = 0.0F, nb::arg(
"p2") = 0.0F, nb::arg(
"p3") = 0.0F, nb::arg(
"p4") = 0.0F, nb::rv_policy::reference_internal)
989 .def(
"attach_post_processing_shaders", &VK_Window::attachPostProcessingShaders, nb::arg(
"effects"), nb::rv_policy::reference_internal)
990 .def(
"detach_post_processing_shader", &VK_Window::detachPostProcessingShader)
991 .def(
"set_post_processing_shader_params", nb::overload_cast<float, float, float, float>(&VK_Window::setPostProcessingShaderParams), nb::arg(
"p1") = 0.0F, nb::arg(
"p2") = 0.0F, nb::arg(
"p3") = 0.0F, nb::arg(
"p4") = 0.0F)
992 .def(
"set_post_processing_effect_params", nb::overload_cast<size_t, float, float, float, float>(&VK_Window::setPostProcessingShaderParams), nb::arg(
"effect_index"), nb::arg(
"p1") = 0.0F, nb::arg(
"p2") = 0.0F, nb::arg(
"p3") = 0.0F, nb::arg(
"p4") = 0.0F)
993 .def(
"set_post_processing_shader_time_enabled", nb::overload_cast<bool>(&VK_Window::setPostProcessingShaderTimeEnabled), nb::arg(
"enabled"))
994 .def(
"set_post_processing_effect_time_enabled", nb::overload_cast<size_t, bool>(&VK_Window::setPostProcessingShaderTimeEnabled), nb::arg(
"effect_index"), nb::arg(
"enabled"))
995 .def(
"enable_post_processing", &VK_Window::enablePostProcessing, nb::arg(
"sprite"))
996 .def(
"set_post_processing_enabled", &VK_Window::setPostProcessingEnabled, nb::arg(
"enabled"))
997 .def(
"set_post_processing_texture_consumer_enabled", &VK_Window::setPostProcessingTextureConsumerEnabled, nb::arg(
"enabled"))
998 .def(
"set_post_processing_present_fragment_shader", &VK_Window::setPostProcessingPresentFragmentShader, nb::arg(
"path"))
1001 [](VK_Window &window,
const std::string &path,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path) {
return window.createSprite3D(path, vertex_shader_path, fragment_shader_path); },
1003 nb::arg(
"vertex_shader_path") =
"",
1004 nb::arg(
"fragment_shader_path") =
"",
1005 nb::rv_policy::reference_internal)
1007 "create_sprite3d_from_surface",
1008 [](VK_Window &window, nb::capsule
surface,
const std::string &vertex_shader_path,
const std::string &fragment_shader_path) {
1009 auto *sdl_surface =
static_cast<SDL_Surface *
>(
surface.data());
1010 if (sdl_surface ==
nullptr)
1011 throw nb::value_error(
"surface capsule must contain an SDL_Surface pointer");
1012 return window.createSprite3D(sdl_surface, vertex_shader_path, fragment_shader_path);
1015 nb::arg(
"vertex_shader_path") =
"",
1016 nb::arg(
"fragment_shader_path") =
"",
1017 nb::rv_policy::reference_internal)
1018 .def(
"show_cursor", &VK_Window::showCursor, nb::arg(
"visible"))
1019 .def(
"validation_enabled", &VK_Window::validationEnabled)
1020 .def(
"context", &VK_Window::context)
1021 .def_prop_ro(
"sdl_window", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getSDLWindow()); })
1022 .def_prop_ro(
"device", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getDevice()); })
1023 .def_prop_ro(
"physical_device", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getPhysicalDevice()); })
1024 .def_prop_ro(
"graphics_queue", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getGraphicsQueue()); })
1025 .def_prop_ro(
"command_pool", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getCommandPool()); })
1026 .def_prop_ro(
"pipeline_cache", [](
const VK_Window &window) {
return reinterpret_cast<uintptr_t
>(window.getPipelineCache()); })
1027 .def_prop_ro(
"swapchain_format", [](
const VK_Window &window) {
return static_cast<int>(window.getSwapchainFormat()); })
1028 .def_prop_ro(
"scene_color_format", [](
const VK_Window &window) {
return static_cast<int>(window.getSceneColorFormat()); })
1029 .def_prop_ro(
"depth_format", [](
const VK_Window &window) {
return static_cast<int>(window.getDepthFormat()); })
1030 .def_prop_ro(
"swapchain_extent",
1031 [](
const VK_Window &window) {
1032 const VkExtent2D extent = window.getSwapchainExtent();
1033 return nb::make_tuple(extent.width, extent.height);
1035 .def_prop_ro(
"render_extent",
1036 [](
const VK_Window &window) {
1037 const VkExtent2D extent = window.getRenderExtent();
1038 return nb::make_tuple(extent.width, extent.height);
1040 .def_prop_ro(
"swapchain_image_count", &VK_Window::getSwapchainImageCount);
1042 nb::class_<PythonEvent>(module,
"Event").def_prop_ro(
"type", &
PythonEvent::type).def_prop_ro(
"timestamp", &
PythonEvent::timestamp).def_prop_ro(
"key", &
PythonEvent::key).def_prop_ro(
"scancode", &
PythonEvent::scancode).def_prop_ro(
"modifiers", &
PythonEvent::modifiers).def_prop_ro(
"key_down", &
PythonEvent::key_down).def_prop_ro(
"key_up", &
PythonEvent::key_up).def_prop_ro(
"down", &
PythonEvent::down).def_prop_ro(
"repeat", &
PythonEvent::repeat).def_prop_ro(
"text", &
PythonEvent::text).def_prop_ro(
"mouse_motion", &
PythonEvent::mouse_motion).def_prop_ro(
"mouse_button_down", &
PythonEvent::mouse_button_down).def_prop_ro(
"mouse_button_up", &
PythonEvent::mouse_button_up).def_prop_ro(
"mouse_wheel", &
PythonEvent::mouse_wheel).def_prop_ro(
"x", &
PythonEvent::x).def_prop_ro(
"y", &
PythonEvent::y).def_prop_ro(
"relative_x", &
PythonEvent::relative_x).def_prop_ro(
"relative_y", &
PythonEvent::relative_y).def_prop_ro(
"button", &
PythonEvent::button).def_prop_ro(
"clicks", &
PythonEvent::clicks).def_prop_ro(
"wheel_x", &
PythonEvent::wheel_x).def_prop_ro(
"wheel_y", &
PythonEvent::wheel_y).def_prop_ro(
"wheel_ticks_x", &
PythonEvent::wheel_ticks_x).def_prop_ro(
"wheel_ticks_y", &
PythonEvent::wheel_ticks_y).def_prop_ro(
"wheel_flipped", &
PythonEvent::wheel_flipped);
1044 nb::class_<VK_IOWindow, VK_Window, PythonIOWindow>(module,
"IOWindow")
1045 .def(nb::init<const std::string &, const std::string &, int, int, bool, bool>(), nb::arg(
"path"), nb::arg(
"title"), nb::arg(
"width"), nb::arg(
"height"), nb::arg(
"fullscreen") =
false, nb::arg(
"enable_vsync") =
false)
1046 .def(
"print", &VK_IOWindow::print, nb::arg(
"text"), nb::arg(
"color") = SDL_Color{255, 255, 255, 255})
1047 .def(
"request_exit", &VK_IOWindow::requestExit)
1048 .def(
"console_proc", &VK_IOWindow::console_proc)
1051 [](VK_IOWindow &window, nb::capsule
event) {
1052 auto *value =
static_cast<SDL_Event *
>(
event.data());
1053 if (value ==
nullptr)
1054 throw nb::value_error(
"event capsule must contain an SDL_Event pointer");
1055 window.console_event(*value);
1058 .def_prop_ro(
"visible", &VK_IOWindow::visible);
1060 module.attr("VK_Window") = module.attr("Window");
1061 module.attr("VK_IOWindow") = module.attr("IOWindow");