Compare commits

..

2 Commits

Author SHA1 Message Date
Vladimír Vondruš 64cecd92f9 ? 7 years ago
Vladimír Vondruš bc50a55a3e [wip] 7 years ago
  1. 1
      .circleci/config.yml
  2. 2
      .editorconfig
  3. 1
      .travis.yml
  4. 212
      CMakeLists.txt
  5. 5
      COPYING
  6. 10
      README.md
  7. 15
      doc/python/conf-public.py
  8. 211
      doc/python/conf.py
  9. 425
      doc/python/corrade.containers.rst
  10. 40
      doc/python/corrade.pluginmanager.rst
  11. 50
      doc/python/corrade.rst
  12. 37
      doc/python/corrade.utility.rst
  13. 71
      doc/python/magnum.gl.rst
  14. 43
      doc/python/magnum.materialtools.rst
  15. 613
      doc/python/magnum.math.rst
  16. 97
      doc/python/magnum.meshtools.rst
  17. 28
      doc/python/magnum.platform.rst
  18. 70
      doc/python/magnum.primitives.rst
  19. 280
      doc/python/magnum.rst
  20. 3
      doc/python/magnum.scenegraph.rst
  21. 75
      doc/python/magnum.scenetools.rst
  22. 132
      doc/python/magnum.shaders.rst
  23. 169
      doc/python/magnum.text.rst
  24. 1479
      doc/python/magnum.trade.rst
  25. BIN
      doc/python/numpy.inv
  26. 128
      doc/python/pages/api-conventions.rst
  27. 95
      doc/python/pages/building.rst
  28. 238
      doc/python/pages/changelog.rst
  29. 81
      doc/python/pages/credits.rst
  30. 80
      doc/python/pages/developers.rst
  31. 21
      doc/python/pages/index.rst
  32. BIN
      doc/python/python.inv
  33. 16
      modules/CMakeLists.txt
  34. 520
      modules/FindCorrade.cmake
  35. 86
      modules/FindEGL.cmake
  36. 94
      modules/FindGLFW.cmake
  37. 832
      modules/FindMagnum.cmake
  38. 162
      modules/FindMagnumBindings.cmake
  39. 78
      modules/FindOpenGLES2.cmake
  40. 92
      modules/FindOpenGLES3.cmake
  41. 173
      modules/FindSDL2.cmake
  42. 3
      modules/MagnumBindingsConfig.cmake
  43. 2
      package/archlinux/.gitignore
  44. 1
      package/archlinux/.kateconfig
  45. 37
      package/archlinux/PKGBUILD
  46. 23
      package/archlinux/PKGBUILD-coverage
  47. 41
      package/archlinux/magnum-bindings-git/PKGBUILD
  48. 141
      package/ci/appveyor-desktop-gles.bat
  49. 151
      package/ci/appveyor-desktop.bat
  50. 143
      package/ci/appveyor.yml
  51. 499
      package/ci/circleci.yml
  52. 8
      package/ci/codecov.yml
  53. 13
      package/ci/setup-pybind11.sh
  54. 80
      package/ci/travis-desktop-gles.sh
  55. 74
      package/ci/travis-desktop.sh
  56. 146
      package/ci/travis.yml
  57. 117
      package/ci/unix-desktop-gles.sh
  58. 122
      package/ci/unix-desktop.sh
  59. 12
      package/git/README.md
  60. 24
      package/homebrew/magnum-bindings.rb
  61. 7
      package/sync-modules.sh
  62. 8
      src/CMakeLists.txt
  63. 20
      src/Corrade/CMakeLists.txt
  64. 15
      src/Corrade/Containers/CMakeLists.txt
  65. 63
      src/Corrade/Containers/OptionalPythonBindings.h
  66. 10
      src/Corrade/Containers/Python.h
  67. 203
      src/Corrade/Containers/StridedArrayViewPythonBindings.h
  68. 72
      src/Corrade/PluginManager/PythonBindings.h
  69. 34
      src/Corrade/Python.h
  70. 67
      src/Magnum/CMakeLists.txt
  71. 10
      src/Magnum/GL/CMakeLists.txt
  72. 9
      src/Magnum/GL/Python.h
  73. 20
      src/Magnum/Python.h
  74. 10
      src/Magnum/SceneGraph/CMakeLists.txt
  75. 29
      src/Magnum/SceneGraph/Python.h
  76. 119
      src/Magnum/StridedArrayViewPythonBindings.h
  77. 30
      src/Magnum/Test/CMakeLists.txt
  78. 67
      src/Magnum/Test/VersionTest.cpp
  79. 30
      src/Magnum/Trade/CMakeLists.txt
  80. 103
      src/Magnum/Trade/PythonBindings.h
  81. 39
      src/Magnum/versionBindings.h.cmake
  82. 33
      src/python/CMakeLists.txt
  83. 108
      src/python/corrade/CMakeLists.txt
  84. 3
      src/python/corrade/EnumOperators.h
  85. 13
      src/python/corrade/PyBuffer.h
  86. 29
      src/python/corrade/__init__.py
  87. 82
      src/python/corrade/__init__.py.in
  88. 22
      src/python/corrade/bootstrap.h
  89. 1043
      src/python/corrade/containers.cpp
  90. 107
      src/python/corrade/corrade.cpp
  91. 190
      src/python/corrade/pluginmanager.cpp
  92. 102
      src/python/corrade/pluginmanager.h
  93. 30
      src/python/corrade/staticconfigure.h.cmake
  94. 36
      src/python/corrade/test/CMakeLists.txt
  95. 8
      src/python/corrade/test/__init__.py
  96. 1
      src/python/corrade/test/broken.conf
  97. 6
      src/python/corrade/test/file.conf
  98. 1718
      src/python/corrade/test/test_containers.py
  99. 186
      src/python/corrade/test/test_containers_numpy.py
  100. 76
      src/python/corrade/test/test_optional.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

1
.circleci/config.yml

@ -1 +0,0 @@
../package/ci/circleci.yml

2
.editorconfig

@ -5,6 +5,6 @@ indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
[*.{css,html,yml,rb,gltf}]
[*.{css,html,yml,rb}]
indent_style = space
indent_size = 2

1
.travis.yml

@ -0,0 +1 @@
package/ci/travis.yml

212
CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,41 +23,14 @@
# DEALINGS IN THE SOFTWARE.
#
# Matches Corrade requirement, see its root CMakeLists for more information.
cmake_minimum_required(VERSION 3.5...3.10)
cmake_minimum_required(VERSION 3.1)
# CMake 3.12+ uses the policy max version specified in
# cmake_minimum_required(), meaning that with ...3.10, everything until CMP0071
# gets set to NEW implicitly. We however want to keep compatibility with
# versions before 3.12, so the NEW policies are still being hand-picked. Also
# don't want to do a blanket cmake_policy(VERSION) because that may break
# behavior for existing projects that rely on the OLD behavior.
# Don't restrict INTERPROCEDURAL_OPTIMIZATION only for icc on Linux
if(POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
# If CMAKE_AUTOMOC is set, all uses of corrade_add_resource() would otherwise
# complain on 3.10 that AUTOMOC is not processing GENERATED files
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
# Allow <PackageName>_ROOT to be used on 3.12+ to point to per-package install
# locations that find_package(PackageName) subsequently picks up
if(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
# Allow also <PACKAGENAME>_ROOT (i.e., uppercase), on 3.27+
if(POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
# Configuration fails on < 3.4 if only C++ is enabled (CheckFunctionExists
# macro called from FindX11)
if(NOT CMAKE_VERSION VERSION_LESS 3.4.0)
set(LANG CXX)
endif()
# Superprojects can use just set(MAGNUM_WITH_BLAH ON) without FORCE CACHE on
# 3.13+
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
project(MagnumBindings CXX)
project(MagnumBindings ${LANG})
# Use folders for nice tree in Visual Studio and XCode
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -68,178 +40,10 @@ find_package(Magnum REQUIRED)
include(CMakeDependentOption)
# Options that used to be unprefixed. New options shouldn't be added to this
# list.
set(_MAGNUMBINDINGS_DEPRECATED_UNPREFIXED_OPTIONS
WITH_PYTHON
BUILD_TESTS)
# If during the first run (i.e., when the variable isn't in cache yet), check
# if any of the prefixed options are already set. If so, we assume the user is
# already switched to the prefixed options and won't accept the deprecated
# unprefixed options for backwards compatibility. This way it's possible for
# projects to reuse these variables for other purposes without affecting
# Corrade in any way.
if(NOT DEFINED _MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS)
set(_MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS ON CACHE INTERNAL "")
foreach(option ${_MAGNUMBINDINGS_DEPRECATED_UNPREFIXED_OPTIONS})
if(DEFINED MAGNUM_${option})
set(_MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS OFF CACHE INTERNAL "")
break()
endif()
endforeach()
endif()
# Libraries to build
option(MAGNUM_WITH_PYTHON "Build Python bindings" OFF)
# There's no global MAGNUM_BUILD_PLUGINS_STATIC option (only exposed as
# per-plugin define), so not checking it.
if(MAGNUM_WITH_PYTHON AND MAGNUM_BUILD_STATIC)
set(MAGNUM_PYTHON_BINDINGS_STATIC_PLUGINS "" CACHE STRING "Static plugins to link to Magnum Python bindings")
endif()
option(MAGNUM_BUILD_TESTS "Build unit tests" OFF)
if(MAGNUM_WITH_PYTHON AND MAGNUM_BUILD_STATIC AND UNIX)
# See src/python/corrade/__init__.py.in and the corresponding CMakeLists
# for details
option(MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL "Build Python bindings linking to static libraries with RTLD_GLOBAL enabled for loading" ON)
endif()
# Python since version 3.8 doesn't take dependency DLLs implicitly from PATH
# anymore, and one has to either place them right next to the Python modules,
# into system locations, or add extra paths via os.add_dll_directory().
#
# Be nice to the user and implicitly populate that with Corrade and Magnum DLL
# directories, if found, on the first run. Anything else (such as SDL or GLFW
# DLL path) has to be specified by the user.
if(MAGNUM_WITH_PYTHON AND WIN32)
# Do this lookup only on the first ever run. But add the option always, so
# in case it's passed via command line in the initial CMake run, it
# actually becomes a cached option with a help text and not just a loose
# variable.
if(NOT MAGNUM_PYTHON_BINDINGS_DLL_PATH)
set(dll_path )
foreach(dll_variable CORRADE_UTILITY_DLL_DEBUG CORRADE_UTILITY_DLL_RELEASE MAGNUM_DLL_DEBUG MAGNUM_DLL_RELEASE)
if(${dll_variable})
get_filename_component(dll_directory ${${dll_variable}} DIRECTORY)
list(APPEND dll_path ${dll_directory})
endif()
endforeach()
list(REMOVE_DUPLICATES dll_path)
# If no DLLs were found, it means Corrade and Magnum is static and thus no
# DLL directories may need to be passed
if(dll_path)
message(STATUS "Autodetected ${dll_path} as directories to pass to Python for finding Corrade, Magnum and other dependency DLLs. Update the MAGNUM_PYTHON_BINDINGS_DLL_PATH variable if needed.")
endif()
endif()
# This variable is then used in src/python/corrade/__init__.py.in
set(MAGNUM_PYTHON_BINDINGS_DLL_PATH "${dll_path}" CACHE STRING "Semicolon-separated directories where to look for Corrade, Magnum and other dependency DLLs")
endif()
# Backwards compatibility for unprefixed CMake options. If the user isn't
# explicitly using prefixed options in the first run already, accept the
# unprefixed options, and remember this decision for subsequent runs
if(NOT DEFINED _MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS)
set(_MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS ON CACHE INTERNAL "")
endif()
# If the user wasn't explicitly using prefixed options in the first run and the
# MAGNUM_BUILD_DEPRECATED option is not currently disabled (which can get
# changed subsequently), accept the unprefixed options and print a warning if
# they're different from the prefixed ones.
if(_MAGNUMBINDINGS_ACCEPT_DEPRECATED_UNPREFIXED_OPTIONS AND MAGNUM_BUILD_DEPRECATED)
set(_MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION )
foreach(option ${_MAGNUMBINDINGS_DEPRECATED_UNPREFIXED_OPTIONS})
if(DEFINED ${option})
# CMake has no comparison of boolean values (EQUAL returns false if
# comparing ON and 1 or OFF and FALSE, STREQUAL also), so we have
# to do it this way. Also warn only on the first encountered
# variable so people can fix it, reconfigure and go to the next one
# that warns.
if((${option} AND NOT MAGNUM_${option}) OR
(NOT ${option} AND MAGNUM_${option}) AND NOT _MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION)
set(_MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION ${option})
endif()
set(MAGNUM_${option} ${${option}})
# If variables specified on the command line don't match any
# options, they're kept in cache but set as UNINITIALIZED, meaning
# they don't appear in cmake-gui or ccmake, so there's no way to
# fix the warning apart from hand-enditing the CMakeCache.txt or
# recreating the build dir. Update their cached type to be BOOL to
# make them appear.
set(${option} ${${option}} CACHE BOOL "Deprecated, use MAGNUM_${option} instead" FORCE)
endif()
endforeach()
if(_MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION)
message(DEPRECATION "Unprefixed options such as ${_MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION} are deprecated, use MAGNUM_${_MAGNUMBINDINGS_WARN_DEPRECATED_UNPREFIXED_OPTION} instead. Delete the unprefixed variable from CMake cache or set both to the same value to silence this warning.")
endif()
endif()
if(MAGNUM_BUILD_TESTS)
find_package(Corrade REQUIRED TestSuite)
if(CORRADE_TARGET_IOS)
set(CORRADE_TESTSUITE_BUNDLE_IDENTIFIER_PREFIX "cz.mosra.magnum-bindings")
endif()
enable_testing()
# If CORRADE_TESTSUITE_TEST_TARGET is set, tests aren't built by default
# (in the ALL target) but instead set as dependencies of a target named
# after the value of CORRADE_TESTSUITE_TEST_TARGET. This is a copy of
# what's done in corrade_add_test(), because we also build various test
# libraries and plugins in addition to the test executables.
if(CORRADE_TESTSUITE_TEST_TARGET)
if(NOT TARGET ${CORRADE_TESTSUITE_TEST_TARGET})
add_custom_target(${CORRADE_TESTSUITE_TEST_TARGET})
endif()
set(EXCLUDE_FROM_ALL_IF_TEST_TARGET EXCLUDE_FROM_ALL)
endif()
endif()
option(WITH_PYTHON "Build Python bindings" OFF)
set(MAGNUMBINDINGS_CMAKE_MODULE_INSTALL_DIR share/cmake/MagnumBindings)
# Library version. MAGNUMBINDINGS_VERSION_YEAR/MONTH is used in
# src/Magnum/CMakeLists.txt to generate the versionBindings.h header.
set(MAGNUMBINDINGS_VERSION_YEAR 2020)
set(MAGNUMBINDINGS_VERSION_MONTH 6)
# A single output location. After a decade of saying NO THIS IS A NON-SOLUTION
# TO A NON-PROBLEM I reconsidered my views and enabled this, because:
#
# - On Windows (which don't have RPATH), this makes test execution finally
# possible without having to install all the stuff first (including the
# test-only libs, which is ugh).
# - With CMake subprojects, this makes it finally possible to use dynamic
# plugins directly from the build dir (again without installing anything) ---
# all plugins are put into the same place, so PluginManager has a single
# place to look into; and thanks to the dynamic libraries being there as
# well, this location can be automagically detected as relative to
# Utility::Path::libraryLocation().
# - Thanks to the $<CONFIG> being part of the output path, you are always sure
# you never accidentally mix up debug/release libraries when switching
# CMAKE_BUILD_TYPE in an existing build dir.
#
# The runtime location is set to CMAKE_BINARY_DIR and not PROJECT_BINARY_DIR
# because have one runtime location per CMake subproject would not solve much
# either. If the user already provides CMAKE_RUNTIME_OUTPUT_DIRECTORY (even
# empty), it's respected and nothing is being done.
#
# Explicitly using a generator expression to ensure plugins are added to e.g.
# <CONFIG>/lib/magnum/importers/ instead of lib/magnum/importers/<CONFIG>. Also
# adding this to cache, making superprojects pick that up implicitly as well,
# without forcing them to explicitly mirror this setting.
if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY AND NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY AND NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/bin CACHE PATH "" FORCE)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib CACHE PATH "" FORCE)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib CACHE PATH "" FORCE)
# There should be no need for the "90% use case" user to adjust these, so
# don't show them in the default view
mark_as_advanced(
CMAKE_RUNTIME_OUTPUT_DIRECTORY
CMAKE_LIBRARY_OUTPUT_DIRECTORY
CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
endif()
add_subdirectory(modules)
add_subdirectory(src)

5
COPYING

@ -1,6 +1,5 @@
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz> and contributors
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

10
README.md

@ -1,9 +1,8 @@
This repository contains bindings of the Magnum C++11 graphics engine into
other languages such as Python.
This repository contains bindings of the Magnum C++11/C++14 graphics engine
into other languages such as Python.
[![Join the chat at https://gitter.im/mosra/magnum](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mosra/magnum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://circleci.com/gh/mosra/magnum-bindings.svg?style=shield)](https://circleci.com/gh/mosra/magnum-bindings)
[![Build status](https://ci.appveyor.com/api/projects/status/utnexv0i8jbwfhff/branch/master?svg=true)](https://ci.appveyor.com/project/mosra/magnum-bindings/branch/master)
[![Build Status](https://travis-ci.org/mosra/magnum-bindings.svg?branch=master)](https://travis-ci.org/mosra/magnum-bindings)
[![Coverage Status](https://codecov.io/gh/mosra/magnum-bindings/branch/master/graph/badge.svg)](https://codecov.io/gh/mosra/magnum-bindings)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
@ -34,7 +33,8 @@ right away!
- E-mail — info@magnum.graphics
- Google Groups mailing list — magnum-engine@googlegroups.com
([archive](https://groups.google.com/forum/#!forum/magnum-engine))
- Bluesky — https://bsky.app/profile/mosra.cz
- Twitter — https://twitter.com/czmosra and the
[#MagnumEngine](https://twitter.com/hashtag/MagnumEngine) hashtag
See also the Magnum Project [Contact & Support page](https://magnum.graphics/contact/)
for further information.

15
doc/python/conf-public.py

@ -22,19 +22,6 @@ STYLESHEETS = [
FAVICON = 'https://doc.magnum.graphics/favicon.ico'
SEARCH_DOWNLOAD_BINARY = 'searchdata-v1.bin'
SEARCH_DOWNLOAD_BINARY = True
SEARCH_BASE_URL = 'https://doc.magnum.graphics/python/'
SEARCH_EXTERNAL_URL = 'https://google.com/search?q=site:doc.magnum.graphics+Magnum+Python+{query}'
def URL_FORMATTER(type, path):
# Put static files into the root, everything else into subdirs
if type.name == 'STATIC':
prefix = os.path.basename(path[0])
return prefix, '/python/' + prefix
# And special casing for index, of course
if type.name == 'PAGE' and len(path) == 1 and path[0] == 'index':
return 'index.html', '/python/'
prefix = '/'.join(path) + '/'
return prefix + 'index.html', '/python/' + prefix

211
doc/python/conf.py

@ -1,21 +1,14 @@
import os
import sys
from typing import List
# TODO make this less brittle
sys.path = [
os.path.join(os.path.dirname(__file__), '../../build/src/python/'),
os.path.join(os.path.dirname(__file__), '../../build/src/python/Release')
] + sys.path
sys.path = [os.path.join(os.path.dirname(__file__), '../../build/src/python/')] + sys.path
import corrade
import corrade.containers
import corrade.pluginmanager
import corrade.utility
import magnum
import magnum.gl
import magnum.materialtools
import magnum.meshtools
import magnum.platform
import magnum.platform.egl
@ -25,164 +18,28 @@ import magnum.platform.sdl2
import magnum.primitives
import magnum.shaders
import magnum.scenegraph
import magnum.scenetools
import magnum.text
import magnum.trade
# So the doc see everything
# TODO: use just +=, m.css should reorder this on its own
corrade.__all__ = ['containers', 'pluginmanager', 'utility', 'BUILD_DEPRECATED', 'BUILD_STATIC', 'BUILD_MULTITHREADED', 'TARGET_UNIX', 'TARGET_APPLE', 'TARGET_IOS', 'TARGET_IOS_SIMULATOR', 'TARGET_WINDOWS', 'TARGET_WINDOWS_RT', 'TARGET_EMSCRIPTEN', 'TARGET_ANDROID']
magnum.__all__ = ['math', 'gl', 'materialtools', 'meshtools', 'platform', 'primitives', 'shaders', 'scenegraph', 'scenetools', 'text', 'trade', 'BUILD_DEPRECATED', 'BUILD_STATIC', 'TARGET_GL', 'TARGET_GLES', 'TARGET_GLES2', 'TARGET_WEBGL', 'TARGET_EGL', 'TARGET_VK'] + magnum.__all__
# hide values of the preprocessor defines to avoid confusion by assigning a
# class without __repr__ to them
# TODO: more systematic solution directly in m.css
class DoNotPrintValue: pass
corrade.BUILD_DEPRECATED = DoNotPrintValue()
corrade.BUILD_STATIC = DoNotPrintValue()
corrade.BUILD_MULTITHREADED = DoNotPrintValue()
corrade.TARGET_UNIX = DoNotPrintValue()
corrade.TARGET_APPLE = DoNotPrintValue()
corrade.TARGET_IOS = DoNotPrintValue()
corrade.TARGET_IOS_SIMULATOR = DoNotPrintValue()
corrade.TARGET_WINDOWS = DoNotPrintValue()
corrade.TARGET_WINDOWS_RT = DoNotPrintValue()
corrade.TARGET_EMSCRIPTEN = DoNotPrintValue()
corrade.TARGET_ANDROID = DoNotPrintValue()
magnum.BUILD_DEPRECATED = DoNotPrintValue()
magnum.BUILD_STATIC = DoNotPrintValue()
magnum.TARGET_GL = DoNotPrintValue()
magnum.TARGET_GLES = DoNotPrintValue()
magnum.TARGET_GLES2 = DoNotPrintValue()
magnum.TARGET_WEBGL = DoNotPrintValue()
magnum.TARGET_EGL = DoNotPrintValue()
magnum.TARGET_VK = DoNotPrintValue()
# TODO ugh... can this be expressed directly in pybind? and the docs parsed
# from it so i don't need to repeat them in docs/*.rst files?
for i in [magnum.text.AbstractFont,
magnum.trade.AbstractImporter,
magnum.trade.AbstractImageConverter,
magnum.trade.AbstractSceneConverter]:
i.__annotations__ = {
'plugin_interface': str,
'plugin_search_paths': List[str],
'plugin_suffix': str,
'plugin_metadata_suffix': str
}
# Don't show the values. Without delattr() first it complains that the
# attribute can't be set
for key in i.__annotations__:
delattr(i, key)
setattr(i, key, DoNotPrintValue())
corrade.__all__ = ['containers']
magnum.__all__ = ['math', 'gl', 'meshtools', 'platform', 'primitives', 'shaders', 'scenegraph', 'trade'] + magnum.__all__
# TODO ugh... can this be expressed directly in pybind?
corrade.__annotations__ = {
'BUILD_DEPRECATED': bool,
'BUILD_STATIC': bool,
'BUILD_MULTITHREADED': bool,
'TARGET_UNIX': bool,
'TARGET_APPLE': bool,
'TARGET_IOS': bool,
'TARGET_IOS_SIMULATOR': bool,
'TARGET_WINDOWS': bool,
'TARGET_WINDOWS_RT': bool,
'TARGET_EMSCRIPTEN': bool,
'TARGET_ANDROID': bool
}
magnum.__annotations__ = {
'BUILD_DEPRECATED': bool,
'BUILD_STATIC': bool,
'TARGET_GL': bool,
'TARGET_GLES': bool,
'TARGET_GLES2': bool,
'TARGET_WEBGL': bool,
'TARGET_VK': bool
}
magnum.gl.__annotations__ = {
'default_framebuffer': magnum.gl.DefaultFramebuffer
}
magnum.shaders.DistanceFieldVectorGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.DistanceFieldVectorGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.FlatGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute,
'COLOR3': magnum.gl.Attribute,
'COLOR4': magnum.gl.Attribute,
'TRANSFORMATION_MATRIX': magnum.gl.Attribute,
'TEXTURE_OFFSET': magnum.gl.Attribute,
}
magnum.shaders.FlatGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute,
'COLOR3': magnum.gl.Attribute,
'COLOR4': magnum.gl.Attribute,
'TRANSFORMATION_MATRIX': magnum.gl.Attribute,
'TEXTURE_OFFSET': magnum.gl.Attribute,
}
magnum.shaders.VertexColorGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'COLOR3': magnum.gl.Attribute,
'COLOR4': magnum.gl.Attribute
}
magnum.shaders.VertexColorGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'COLOR3': magnum.gl.Attribute,
'COLOR4': magnum.gl.Attribute
}
magnum.shaders.PhongGL.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'NORMAL': magnum.gl.Attribute,
'TANGENT': magnum.gl.Attribute,
'TANGENT4': magnum.gl.Attribute,
'BITANGENT': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute,
'COLOR3': magnum.gl.Attribute,
'COLOR4': magnum.gl.Attribute,
'TRANSFORMATION_MATRIX': magnum.gl.Attribute,
'TEXTURE_OFFSET': magnum.gl.Attribute,
}
magnum.shaders.VectorGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.VectorGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
# An extremely hacky way to remove noise for shader docs. It doesn't hide
# those, but at least puts them way down in the page, removing all docs.
# TODO needs a better solution directly in m.css
for shader in [magnum.shaders.DistanceFieldVectorGL2D,
magnum.shaders.DistanceFieldVectorGL3D,
magnum.shaders.FlatGL2D,
magnum.shaders.FlatGL3D,
magnum.shaders.VertexColorGL2D,
magnum.shaders.VertexColorGL3D,
magnum.shaders.PhongGL,
magnum.shaders.VectorGL2D,
magnum.shaders.VectorGL3D]:
shader.attach_shader = DoNotPrintValue()
shader.bind_attribute_location = DoNotPrintValue()
shader.bind_fragment_data_location = DoNotPrintValue()
shader.bind_fragment_data_location_indexed = DoNotPrintValue()
shader.dispatch_compute = DoNotPrintValue()
shader.link = DoNotPrintValue()
shader.retrievable_binary = DoNotPrintValue()
shader.separable = DoNotPrintValue()
shader.set_uniform_block_binding = DoNotPrintValue()
shader.set_uniform = DoNotPrintValue()
shader.uniform_block_index = DoNotPrintValue()
shader.uniform_location = DoNotPrintValue()
shader.TransformFeedbackBufferMode = DoNotPrintValue()
magnum.gl.__annotations__ = {}
magnum.gl.__annotations__['default_framebuffer'] = magnum.gl.DefaultFramebuffer
magnum.shaders.VertexColor2D.__annotations__ = {}
magnum.shaders.VertexColor2D.__annotations__['POSITION'] = magnum.gl.Attribute
magnum.shaders.VertexColor2D.__annotations__['COLOR3'] = magnum.gl.Attribute
magnum.shaders.VertexColor2D.__annotations__['COLOR4'] = magnum.gl.Attribute
magnum.shaders.VertexColor3D.__annotations__ = {}
magnum.shaders.VertexColor3D.__annotations__['POSITION'] = magnum.gl.Attribute
magnum.shaders.VertexColor3D.__annotations__['COLOR3'] = magnum.gl.Attribute
magnum.shaders.VertexColor3D.__annotations__['COLOR4'] = magnum.gl.Attribute
magnum.shaders.Phong.__annotations__ = {}
magnum.shaders.Phong.__annotations__['POSITION'] = magnum.gl.Attribute
magnum.shaders.Phong.__annotations__['TEXTURE_COORDINATES'] = magnum.gl.Attribute
magnum.shaders.Phong.__annotations__['NORMAL'] = magnum.gl.Attribute
PROJECT_TITLE = 'Magnum'
PROJECT_SUBTITLE = 'Python docs'
@ -192,30 +49,18 @@ INPUT_PAGES = [
'pages/index.rst',
'pages/building.rst',
'pages/api-conventions.rst',
'pages/changelog.rst',
'pages/credits.rst',
'pages/developers.rst',
'../../../magnum-examples/doc/python/examples.rst'
]
INPUT_DOCS = [
'corrade.rst',
'corrade.containers.rst',
'corrade.pluginmanager.rst',
'corrade.utility.rst',
'magnum.rst',
'magnum.gl.rst',
'magnum.math.rst',
'magnum.materialtools.rst',
'magnum.meshtools.rst',
'magnum.platform.rst',
'magnum.primitives.rst',
'magnum.scenegraph.rst',
'magnum.scenetools.rst',
'magnum.shaders.rst',
'magnum.text.rst',
'magnum.trade.rst',
'magnum.shaders.rst'
]
LINKS_NAVBAR2 = [
@ -242,16 +87,11 @@ STYLESHEETS = [
FAVICON = '../favicon.ico'
M_DOX_TAGFILES = [
('../../../corrade/build/doc-mcss/corrade.tag', '../../../../corrade/build/doc-mcss/html/', ['Corrade::'], ['m-doc-external']),
('../../../magnum/build/doc-mcss/magnum.tag', '../../../../magnum/build/doc-mcss/html/', ['Magnum::'], ['m-doc-external'])
]
M_SPHINX_INVENTORY_OUTPUT = 'objects.inv'
M_SPHINX_INVENTORIES = [
('python.inv', 'https://docs.python.org/3/', [], ['m-doc-external']),
('numpy.inv', 'https://docs.scipy.org/doc/numpy/', [], ["m-doc-external"])
# TODO: the path should be relative to this file
(os.path.join(os.path.dirname(__file__), '../../../corrade/build/doc-mcss/corrade.tag'), '../../../../corrade/build/doc-mcss/html/', ['Corrade::'], ['m-doc-external']),
(os.path.join(os.path.dirname(__file__), '../../../magnum/build/doc-mcss/magnum.tag'), '../../../../magnum/build/doc-mcss/html/', ['Magnum::'], ['m-doc-external'])
]
M_HTMLSANITY_SMART_QUOTES = True
M_MATH_CACHE = 'm.math.cache'
PYBIND11_COMPATIBILITY = True
@ -260,14 +100,15 @@ OUTPUT = '../../build/doc/python/'
PAGE_HEADER = """
.. container:: m-note m-success
Welcome to Python-flavored Magnum! Please note that, while already being
rather stable, this functionality is still considered *experimental* and
some APIs might get changed without preserving full backwards compatibility.
Welcome to the exciting new Python-flavored future of Magnum! Have fun, but
please note this functionality is *heavily experimental* at the moment.
Most APIs are missing, documentation is very sparse and everything is still
evolving. **Use at your own risk.**
"""
FINE_PRINT = """
| Magnum Python docs. Part of the `Magnum project <https://magnum.graphics/>`_,
copyright © `Vladimír Vondruš <https://mosra.cz/>`_ and contributors, 2010--2026.
copyright © `Vladimír Vondruš <http://mosra.cz/>`_ and contributors, 20102019.
| Generated by `m.css Python doc generator <https://mcss.mosra.cz/documentation/python/>`_.
Contact the team via `GitHub <https://github.com/mosra/magnum>`_,
`Gitter <https://gitter.im/mosra/magnum>`_,

425
doc/python/corrade.containers.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -26,39 +25,34 @@
.. doctest setup
>>> from corrade import containers
>>> import array
.. py:class:: corrade.containers.ArrayView
Provides an untyped one-dimensional read-only view on a contiguous memory
range. Convertible both to and from Python objects supporting the Buffer
Protocol. The buffer type is lost in the conversion process and the memory
is always treated as plain bytes:
Provides one-dimensional tightly packed view on a memory range. Convertible
both from and to Python objects supporting the Buffer Protocol, with one
dimension and stride of :py:`1`. See `StridedArrayView1D` and others for
more generic views. `ArrayView` is immutable, see `MutableArrayView` for
the mutable alterantive. All slicing operations are supported, specifying a
non-trivial stride will return `StridedArrayView1D` instead of `ArrayView`.
Example usage:
.. code:: pycon
>>> a = b'hello'
>>> b = containers.ArrayView(a)
>>> chr(b[2])
>>> b[2]
'l'
>>> bytes(b[1:4])
b'ell'
See the :ref:`StridedArrayView1D` and its multi-dimensional variants for an
alternative that can provide typed access. The :ref:`ArrayView` is
immutable, see :ref:`MutableArrayView` for the mutable alternative. All
slicing operations are supported, specifying a non-trivial stride will
return :ref:`StridedArrayView1D` instead of :ref:`ArrayView`.
`Memory ownership and reference counting`_
==========================================
Unlike in C++, the view keeps a reference to the original memory owner
object in the :ref:`owner` field, meaning that calling :py:`del` on the
original object will *not* invalidate the view. Slicing a view creates a
new view referencing the same original object, without any dependency on
the previous view. That means a long chained slicing operation will not
cause increased memory usage.
object, meaning that calling :py:`del` on the original object will *not*
invalidate the view. Slicing a view creates a new view referencing the same
original object, without any dependency on the previous view. That means a
long chained slicing operation will not cause increased memory usage.
.. code:: pycon
@ -67,408 +61,51 @@
>>> b[1:4][:-1].owner is a
True
The :py:`owner` is :py:`None` if the view is empty.
`Comparison to Python's memoryview`_
====================================
The :ref:`ArrayView` class is equivalent to one-dimensional
:ref:`memoryview` with a stride of :py:`1`. For multiple dimensions and
non-trivial strides, :ref:`StridedArrayView1D` and friends provide a
superset of :ref:`memoryview` features.
The `ArrayView` class is equivalent to one-dimensional `memoryview` with a
stride of :py:`1`. For multiple dimensions and non-trivial strides,
`StridedArrayView1D` and friends provide a superset of `memoryview`
features.
.. py:class:: corrade.containers.MutableArrayView
Equivalent to :ref:`ArrayView`, but implementing :ref:`__setitem__()` as
well.
Equivalent to `ArrayView`, but implementing `__setitem__()` as well.
.. py:class:: corrade.containers.StridedArrayView1D
Provides a typed one-dimensional read-only view on a memory range with
custom stride values. Convertible both to and from Python objects
supporting the Buffer Protocol, preserving the dimensionality, type and
stride information:
.. code:: pycon
>>> a = array.array('f', [2.5, 3.14, -1.75, 53.2])
>>> b = containers.StridedArrayView1D(memoryview(a)[::2])
>>> b[0]
2.5
>>> b[1]
-1.75
See :ref:`StridedArrayView2D`, :ref:`StridedArrayView3D`,
:ref:`StridedArrayView4D`, :ref:`MutableStridedArrayView1D` and others for
multi-dimensional and mutable equivalents.
`Memory ownership and reference counting`_
==========================================
Similarly to :ref:`ArrayView`, the view keeps a reference to the original
memory owner object in the :ref:`owner` field. Slicing a view creates a
new view referencing the same original object, without any dependency on
the previous view. The :py:`owner` is :py:`None` if the view is empty.
Provides one-dimensional read-only view on a memory range with custom
stride values. See `StridedArrayView2D`, `StridedArrayView3D`,
`MutableStridedArrayView1D` and others for multi-dimensional and mutable
equivalents.
`Comparison to Python's memoryview`_
====================================
The :ref:`StridedArrayView1D` and its multi-dimensional variants are
equivalent to any :ref:`memoryview`, but additionally supporting
multi-dimensional slicing as well (which raises :ref:`NotImplementedError`
in Py3.7 :ref:`memoryview`).
.. py:function:: corrade.containers.StridedArrayView1D.__getitem__(self, i: int)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <StridedArrayView1D.format>` is not one of :py:`'b'`,
:py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`, :py:`'q'`,
:py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.StridedArrayView1D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.StridedArrayView1D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.StridedArrayView1D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
The `StridedArrayView1D` and its multi-dimensional variants are equivalent
to any `memoryview`, but additionally supporting multi-dimensional slicing
as well (which raises `NotImplementedError` in Py3.7 `memoryview`).
.. py:class:: corrade.containers.MutableStridedArrayView1D
Equivalent to :ref:`StridedArrayView1D`, but implementing
:ref:`__setitem__()` as well.
.. py:function:: corrade.containers.MutableStridedArrayView1D.__getitem__(self, i: int)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView1D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView1D.__setitem__(self, i: int, value: object)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView1D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView1D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.MutableStridedArrayView1D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.MutableStridedArrayView1D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
Equivalent to `StridedArrayView1D`, but implementing `__setitem__()` as
well.
.. py:class:: corrade.containers.StridedArrayView2D
See :ref:`StridedArrayView1D` for more information.
.. py:function:: corrade.containers.StridedArrayView2D.__getitem__(self, i: tuple[int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <StridedArrayView2D.format>` is not one of :py:`'b'`,
:py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`, :py:`'q'`,
:py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.StridedArrayView2D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.StridedArrayView2D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.StridedArrayView2D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0` or :py:`1` or if
they're the same
.. py:function:: corrade.containers.StridedArrayView2D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
See `StridedArrayView1D` for more information.
.. py:class:: corrade.containers.MutableStridedArrayView2D
See :ref:`StridedArrayView1D` and :ref:`MutableStridedArrayView1D` for more
See `StridedArrayView1D` and `MutableStridedArrayView1D` for more
information.
.. py:function:: corrade.containers.MutableStridedArrayView2D.__getitem__(self, i: tuple[int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView2D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView2D.__setitem__(self, i: tuple[int, int], value: object)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView2D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView2D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.MutableStridedArrayView2D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.MutableStridedArrayView2D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0` or :py:`1` or if
they're the same
.. py:function:: corrade.containers.MutableStridedArrayView2D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.StridedArrayView3D
See :ref:`StridedArrayView1D` for more information.
.. py:function:: corrade.containers.StridedArrayView3D.__getitem__(self, i: tuple[int, int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <StridedArrayView3D.format>` is not one of :py:`'b'`,
:py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`, :py:`'q'`,
:py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.StridedArrayView3D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.StridedArrayView3D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.StridedArrayView3D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` or :py:`2`
or if they're the same
.. py:function:: corrade.containers.StridedArrayView3D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
See `StridedArrayView1D` for more information.
.. py:class:: corrade.containers.MutableStridedArrayView3D
See :ref:`StridedArrayView1D` and :ref:`MutableStridedArrayView1D` for more
information.
.. py:function:: corrade.containers.MutableStridedArrayView3D.__getitem__(self, i: tuple[int, int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView3D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView3D.__setitem__(self, i: tuple[int, int, int], value: object)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView3D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView3D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.MutableStridedArrayView3D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.MutableStridedArrayView3D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` or :py:`2`
or if they're the same
.. py:function:: corrade.containers.MutableStridedArrayView3D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.StridedArrayView4D
See :ref:`StridedArrayView1D` for more information.
.. py:function:: corrade.containers.StridedArrayView4D.__getitem__(self, i: tuple[int, int, int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <StridedArrayView4D.format>` is not one of :py:`'b'`,
:py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`, :py:`'q'`,
:py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.StridedArrayView4D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.StridedArrayView4D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.StridedArrayView4D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` :py:`2` or
:py:`3` or if they're the same
.. py:class:: corrade.containers.MutableStridedArrayView4D
See :ref:`StridedArrayView1D` and :ref:`MutableStridedArrayView1D` for more
See `StridedArrayView1D` and `MutableStridedArrayView1D` for more
information.
.. py:function:: corrade.containers.MutableStridedArrayView4D.__getitem__(self, i: tuple[int, int, int, int])
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView4D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView4D.__setitem__(self, i: tuple[int, int, int, int], value: object)
:raise IndexError: If :p:`i` is out of range
:raise NotImplementedError: If the view was created from a buffer and
:ref:`format <MutableStridedArrayView4D.format>` is not one of
:py:`'b'`, :py:`'B'`, :py:`'h'`, :py:`'H'`, :py:`'i'`, :py:`'I'`,
:py:`'q'`, :py:`'Q'`, :py:`'f'` or :py:`'d'`
.. py:function:: corrade.containers.MutableStridedArrayView4D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.MutableStridedArrayView4D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.MutableStridedArrayView4D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` :py:`2` or
:py:`3` or if they're the same
.. py:class:: corrade.containers.BitArray
An owning counterpart to :ref:`BitArrayView` / :ref:`MutableBitArrayView`.
Holds its own data buffer, thus doesn't have an equivalent to
:ref:`BitArrayView.owner`. Implicitly convertible to :ref:`BitArrayView`,
:ref:`MutableBitArrayView`, :ref:`StridedBitArrayView1D` and
:ref:`MutableStridedBitArrayView1D`, so all APIs consuming (strided) bit
array views work with this type as well.
.. py:class:: corrade.containers.BitArrayView
Comparex to an :ref:`ArrayView`, which operates with byte-sized types,
provides a view on individual bits. Convertible from a :ref:`BitArrayView`.
See :ref:`StridedBitArrayView1D` and others for more generic bit views. :ref:`BitArrayView` is immutable, see :ref:`MutableBitArrayView` for the
mutable alternative. All slicing operations are supported, specifying a
non-trivial stride will return a :ref:`StridedBitArrayView1D` instead of a :ref:`BitArrayView`.
`Memory ownership and reference counting`_
==========================================
Similarly to :ref:`ArrayView`, the view keeps a reference to the original
memory owner object in the :ref:`owner` field. Slicing a view creates a
new view referencing the same original object, without any dependency on
the previous view. The :py:`owner` is :py:`None` if the view is empty.
.. py:class:: corrade.containers.MutableBitArrayView
Equivalent to :ref:`BitArrayView`, but implementing :ref:`__setitem__()` as
well.
.. py:class:: corrade.containers.StridedBitArrayView1D
Provides one-dimensional read-only view on a memory range with custom
stride values. See :ref:`StridedBitArrayView2D`,
:ref:`StridedBitArrayView3D`, :ref:`StridedBitArrayView4D`,
:ref:`MutableStridedBitArrayView1D` and others for multi-dimensional and
mutable equivalents.
`Memory ownership and reference counting`_
==========================================
Similarly to :ref:`BitArrayView`, the view keeps a reference to the
original memory owner object in the :ref:`owner` field. Slicing a view
creates a new view referencing the same original object, without any
dependency on the previous view. The :py:`owner` is :py:`None` if the view
is empty.
.. py:function:: corrade.containers.StridedBitArrayView1D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.StridedBitArrayView1D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.StridedBitArrayView1D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.MutableStridedBitArrayView1D
Equivalent to :ref:`StridedBitArrayView1D`, but implementing
:ref:`__setitem__()` as well.
.. py:function:: corrade.containers.MutableStridedBitArrayView1D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.MutableStridedBitArrayView1D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`
.. py:function:: corrade.containers.MutableStridedBitArrayView1D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.StridedBitArrayView2D
See :ref:`StridedBitArrayView1D` for more information.
.. py:function:: corrade.containers.StridedBitArrayView2D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.StridedBitArrayView2D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.StridedBitArrayView2D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0` or :py:`1` or if
they're the same
.. py:function:: corrade.containers.StridedBitArrayView2D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.MutableStridedBitArrayView2D
See :ref:`StridedBitArrayView1D` and :ref:`MutableStridedBitArrayView1D`
for more information.
.. py:function:: corrade.containers.MutableStridedBitArrayView2D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.MutableStridedBitArrayView2D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
.. py:function:: corrade.containers.MutableStridedBitArrayView2D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0` or :py:`1` or if
they're the same
.. py:function:: corrade.containers.MutableStridedBitArrayView2D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0` or :py:`1`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.StridedBitArrayView3D
See :ref:`StridedBitArrayView1D` for more information.
.. py:function:: corrade.containers.StridedBitArrayView3D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.StridedBitArrayView3D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.StridedBitArrayView3D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` or :py:`2`
or if they're the same
.. py:function:: corrade.containers.StridedBitArrayView3D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.MutableStridedBitArrayView3D
See :ref:`StridedBitArrayView1D` and :ref:`MutableStridedBitArrayView1D`
for more information.
.. py:function:: corrade.containers.MutableStridedBitArrayView3D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.MutableStridedBitArrayView3D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
.. py:function:: corrade.containers.MutableStridedBitArrayView3D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` or :py:`2`
or if they're the same
.. py:function:: corrade.containers.MutableStridedBitArrayView3D.expanded
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` or :py:`2`
:raise ValueError: If product of :p:`size` is not equal to size in
:p:`dimension`
.. py:class:: corrade.containers.StridedBitArrayView4D
See :ref:`StridedBitArrayView1D` for more information.
.. py:function:: corrade.containers.StridedBitArrayView4D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.StridedBitArrayView4D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.StridedBitArrayView4D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` :py:`2` or
:py:`3` or if they're the same
.. py:class:: corrade.containers.MutableStridedBitArrayView4D
See :ref:`StridedBitArrayView1D` and :ref:`MutableStridedBitArrayView1D`
for more information.
.. py:function:: corrade.containers.MutableStridedBitArrayView4D.flipped
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.MutableStridedBitArrayView4D.broadcasted
:raise IndexError: If :p:`dimension` is not :py:`0`, :py:`1` :py:`2` or
:py:`3`
.. py:function:: corrade.containers.MutableStridedBitArrayView4D.transposed
:raise IndexError: If :p:`a` or :p:`b` is not :py:`0`, :py:`1` :py:`2` or
:py:`3` or if they're the same

40
doc/python/corrade.pluginmanager.rst

@ -1,40 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:class:: corrade.pluginmanager.AbstractManager
:data VERSION: Plugin ABI version
.. py:function:: corrade.pluginmanager.AbstractManager.load
:raise RuntimeError: When loading fails
:return: :ref:`LoadState.LOADED`, possibly combined with other flags such
as :ref:`LoadState.STATIC`
.. py:function:: corrade.pluginmanager.AbstractManager.unload
:raise RuntimeError: When unloading fails
:return: Either :ref:`LoadState.NOT_LOADED` or :ref:`LoadState.STATIC`
.. py:function:: corrade.pluginmanager.AbstractManager.set_preferred_plugins
:raise KeyError: If the alias doesn't exist

50
doc/python/corrade.rst

@ -1,50 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. roles used for all other docs
.. role:: cpp(code)
:language: c++
.. role:: py(code)
:language: py
.. role:: sh(code)
:language: sh
.. doctest setup
>>> from corrade import *
.. py:module:: corrade
:data BUILD_DEPRECATED: Build with deprecated features enabled
:data BUILD_STATIC: Static library build
:data BUILD_MULTITHREADED: Multi-threaded build
:data TARGET_UNIX: Unix target
:data TARGET_APPLE: Apple target
:data TARGET_IOS: iOS target
:data TARGET_IOS_SIMULATOR: iOS simulator target
:data TARGET_WINDOWS: Windows target
:data TARGET_WINDOWS_RT: Windows RT target
:data TARGET_EMSCRIPTEN: Emscripten target
:data TARGET_ANDROID: Android target

37
doc/python/corrade.utility.rst

@ -1,37 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:function:: corrade.utility.copy
:raise AssertionError: If :p:`src` and :p:`dst` sizes, type sizes or types are different
.. py:function:: corrade.utility.ConfigurationGroup.group
:raise KeyError: If group :p:`name` doesn't exist
.. py:function:: corrade.utility.Configuration.__init__(self, filename: str)
:raise IOError: If :p:`filename` contains a parse error
.. py:function:: corrade.utility.Configuration.save
:raise IOError: If the file can't be saved

71
doc/python/magnum.gl.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -24,76 +23,12 @@
DEALINGS IN THE SOFTWARE.
..
.. py:module:: magnum.gl
:data default_framebuffer: Default framebuffer instance
:TODO: remove this line once m.css stops ignoring first caption on a page
`NoCreate constructors`_
========================
.. TODO: link to NoCreate once m.dox handles variables properly
Compared to C++, the Python APIs don't have an alternative to the
:dox:`NoCreate <NoCreateT>` constructor tag. In C++ these make it possible
to have class members initialized before a GL context is present, but in
Python there's no such limitation so these don't make sense.
.. py:function:: magnum.gl.AbstractShaderProgram.link
:raise RuntimeError: If linking fails
.. py:function:: magnum.gl.AbstractShaderProgram.uniform_location
:raise ValueError: If there's no uniform of that name
.. py:function:: magnum.gl.AbstractShaderProgram.uniform_block_index
:raise ValueError: If there's no uniform block of that name
.. py:function:: magnum.gl.Shader.compile
:raise RuntimeError: If compilation fails
.. py:class:: magnum.gl.Mesh
:TODO: remove this line once m.css stops ignoring first caption on a page
`Buffer ownership and reference counting`_
==========================================
Unlike in C++, where a :dox:`GL::Buffer` is either :dox:`std::move()`\ d
into the mesh or referenced externally (with the user being responsible for
its lifetime), the :ref:`gl.Mesh` object keeps references to all buffers
added to it.
.. py:property:: magnum.gl.Mesh.primitive
While querying this property will always give back a :ref:`gl.MeshPrimitive`,
this property can be set using either :ref:`magnum.MeshPrimitive` or
:ref:`gl.MeshPrimitive`, similarly to how the overloaded
:dox:`GL::Mesh::setPrimitive()` works.
.. py:property:: magnum.gl.Texture1D.minification_filter
See :ref:`Texture2D.minification_filter` for more information.
.. py:property:: magnum.gl.Texture2D.minification_filter
This property accepts either a tuple of :ref:`magnum.SamplerFilter` /
:ref:`gl.SamplerFilter` and :ref:`magnum.SamplerMipmap` /
:ref:`gl.SamplerMipmap` values or just :ref:`magnum.SamplerFilter` / :ref:`gl.SamplerFilter` alone in which case :ref:`gl.SamplerMipmap.BASE`
will be used implicitly; similarly to how the overloaded
:dox:`GL::Texture::setMinificationFilter()` works.
.. py:property:: magnum.gl.Texture3D.minification_filter
See :ref:`Texture2D.minification_filter` for more information.
.. py:property:: magnum.gl.Texture1D.magnification_filter
See :ref:`Texture2D.magnification_filter` for more information.
.. py:property:: magnum.gl.Texture2D.magnification_filter
This property accepts either :ref:`magnum.SamplerFilter` or
:ref:`gl.SamplerFilter`, similarly to how the overloaded
:dox:`GL::Texture::setMagnificationFilter()`
works.
.. py:property:: magnum.gl.Texture3D.magnification_filter
See :ref:`Texture2D.magnification_filter` for more information.
its lifetime), the `gl.Mesh` object keeps references to all buffers added
to it.

43
doc/python/magnum.materialtools.rst

@ -1,43 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:function:: magnum.materialtools.filter_attributes
:raise AssertionError: If size of :p:`attributes_to_keep` is different than
:ref:`trade.MaterialData.attribute_data_offset()` for
:ref:`trade.MaterialData.layer_count`
.. py:function:: magnum.materialtools.filter_layers
:raise AssertionError: If size of :p:`layers_to_keep` is different than
:ref:`trade.MaterialData.layer_count`
.. py:function:: magnum.materialtools.filter_attributes_layers
:raise AssertionError: If size of :p:`attributes_to_keep` is different than
:ref:`trade.MaterialData.attribute_data_offset()` for
:ref:`trade.MaterialData.layer_count`
:raise AssertionError: If size of :p:`layers_to_keep` is different than
:ref:`trade.MaterialData.layer_count`
.. py:function:: magnum.materialtools.merge
:raise RuntimeError: If merge failed due to a conflict
.. py:function:: magnum.materialtools.phong_to_pbr_metallic_roughness
:raise RuntimeError: If conversion failed

613
doc/python/magnum.math.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -25,21 +24,11 @@
..
.. py:module:: magnum.math
:data pi: :math:`\pi`
:data pi_half: Half of a :math:`\pi`
:data pi_quarter: Quarter of a :math:`\pi`
:data tau: :math:`\tau`, or :math:`2 \pi`
:data e: Euler's number
:data sqrt2: Square root of 2
:data sqrt3: Square root of 3
:data sqrt_half: Square root of :math:`\frac{1}{2}`
:data nan: Quiet NaN
:data inf: Positive :math:`\infty`
In the C++ API, math types are commonly used via :cpp:`typedef`\ s in the
root namespace, only library-level generic code uses things like
:dox:`Math::Vector<size, T> <Math::Vector>`. Since Python doesn't have
templates or generics, there are no generic variants in the :ref:`magnum.math`
templates or generics, there are no generic variants in the `magnum.math`
module, all the concrete types are in the root module with the same names
as in the C++ variant.
@ -83,7 +72,7 @@
As shown above, all math types are constructible from a (nested) tuple of
matching type, matching the convenience of C++11 uniform initializers. As
another example, a function accepting a :ref:`Quaternion` will accept a
another example, a function accepting a `Quaternion` will accept a
:py:`((x, y, z), w)` tuple as well, but not :py:`(x, y, z, w)`, as that is
not convertible to a pair of a three-component vector and a scalar.
@ -94,12 +83,12 @@
Currently, doing :py:`from magnum import math` will bring in the
Magnum's math module which at the moment *does not* contain the
well-known Python APIs and constants. In particular, calling
:ref:`magnum.math.sin()` expects an explicit :ref:`Deg` / :ref:`Rad`
type, while Python's :ref:`math.sin()` doesn't. This will get resolved
either by making all Python overloads present in the same module or
giving the user an option whether to use Magnum math or Python math.
For now, to avoid confusion, do for example this:
well-known Python APIs and constants. In particular, calling `math.sin()`
expects an explicit `Deg` / `Rad` type, while Python's :py:`math.sin()`
doesn't. This will get resolved either by making all Python overloads
present in the same module or giving the user an option whether to use
Magnum math or Python math. For now, to avoid confusion, do for example
this:
.. code:: pycon
@ -115,10 +104,9 @@
Since Python doesn't really differentiate between 32bit and 64bit doubles,
all *scalar* functions taking or returning a floating-point type (such as
the :ref:`Deg` / :ref:`Rad` types, :ref:`math.pi <magnum.math.pi>` or
:ref:`math.sin <magnum.math.sin()>`) use the :cpp:`double` variant of the
underlying C++ API --- the extra arithmetic cost is negligible to the
Python-to-C++ function call overhead.
the `Deg` / `Rad` types, `math.pi` or `math.sin()`) use the :cpp:`double`
variant of the underlying C++ API --- the extra arithmetic cost is
negligible to the Python-to-C++ function call overhead.
On the other hand, matrix and vector types are exposed in both the float
and double variants.
@ -129,7 +117,7 @@
All vector classes are implicitly convertible from a tuple of correct size
and type as well as from/to type implementing the buffer protocol, and
these can be also converted back to lists using list comprehensions. This
makes them fully compatible with :ref:`numpy.ndarray`, so the following
makes them fully compatible with `numpy.array`, so the following
expressions are completely valid:
..
@ -159,7 +147,7 @@
To simplify the implementation, Magnum matrices are convertible only from
32-bit and 64-bit floating-point types (:py:`'f'` and :py:`'d'` numpy
``dtype``). In the other direction, unless overridden using ``dtype`` or
``dtype``). In the other direction, unless overriden using ``dtype`` or
``order``, the created numpy array matches Magnum data type and layout:
.. code:: pycon
@ -171,34 +159,21 @@
>>> a[0] # first column
Vector(1, 4, 7)
..
In order to minimize floating-point printing differences across
architectures (ARM Mac has a different output below otherwise)
>>> np.set_printoptions(precision=5)
.. code:: pycon
>>> b = np.array(Matrix3.rotation(Deg(45.0)))
>>> b.strides[0] # column-major storage
4
>>> b[0] # first column, 32-bit floats
array([ 0.70711, -0.70711, 0. ], dtype=float32)
..
A bit longer for doubles
>>> np.set_printoptions(precision=7)
array([ 0.70710677, -0.70710677, 0. ], dtype=float32)
.. code:: pycon
>>> c = np.array(Matrix3.rotation(Deg(45.0)), order='C', dtype='d')
>>> c.strides[0] # row-major storage (overridden)
>>> c.strides[0] # row-major storage (overriden)
24
>>> c[0] # first column, 64-bit floats (overridden)
array([ 0.7071068, -0.7071068, 0. ])
..
Reset back
>>> np.set_printoptions()
>>> c[0] # first column, 64-bit floats (overriden)
array([ 0.70710677, -0.70710677, 0. ])
`Major differences to the C++ API`_
===================================
@ -206,508 +181,62 @@
- All vector and matrix classes implement :py:`len()`, which is used
instead of e.g. :dox:`Math::Vector::Size`. Works on both classes
and instances.
- :dox:`Math::Matrix3::from()` / :dox:`Math::Matrix4::from()` are named
:ref:`Matrix3.from_()` / :ref:`Matrix4.from_()` because :py:`from` is
a Python keyword and thus can't be used as a name.
- :dox:`Math::isInf()` and :dox:`Math::isNan()` are named
:ref:`math.isinf() <magnum.math.isinf()>` and
:ref:`math.isnan() <magnum.math.isnan()>` for consistency with the
Python :ref:`math` module
- :cpp:`Math::gather()` and :cpp:`Math::scatter()` operations are
implemented as real swizzles:
.. code:: pycon
>>> a = Vector4(1.5, 0.3, -1.0, 1.0)
>>> b = Vector4(7.2, 2.3, 1.1, 0.0)
>>> a.wxy = b.xwz
>>> a
Vector(0, 1.1, -1, 7.2)
- :py:`mat[a][b] = c` on matrices doesn't do the expected thing, use
:py:`mat[a, b] = c` instead
- :cpp:`Math::BitVector::set()` doesn't exist, use ``[]`` instead
- While both boolean and bitwise operations on :cpp:`Math::BitVector`
- :cpp:`Math::BoolVector::set()` doesn't exist, use ``[]`` instead
- While both boolean and bitwise operations on :cpp:`Math::BoolVector`
behave the same to ensure consistency in generic code, this is not
possible to do in Python. Here the boolean operations behave like
if :py:`any()` was applied before doing the operation.
`Static constructors and instance method / property overloads`_
---------------------------------------------------------------
While not common in Python, the :ref:`Matrix4.scaling()` /
:ref:`Matrix4.rotation()` methods mimic the C++ equivalent --- calling
:py:`Matrix4.scaling(vec)` will return a scaling matrix, while
:py:`mat.scaling()` returns the 3x3 scaling part of the matrix. With
:ref:`Matrix4.translation`, it's a bit more involved --- calling
:py:`Matrix4.translation(vec)` will return a translation matrix, while
:py:`mat.translation` is a read-write property accessing the fourth column
of the matrix. Similarly for the :ref:`Matrix3` class.
.. py:function:: magnum.Matrix2x2.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix2x2d.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix3x3.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix3x3d.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix4x4.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix4x4d.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix3.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix3d.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix4.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix4d.inverted_orthogonal
:raise ValueError: If the matrix is not orthogonal
.. py:function:: magnum.Matrix3.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Matrix3d.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Matrix4.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Matrix4d.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Matrix3.rotation(self)
:raise ValueError: If the normalized rotation part is not orthogonal
.. py:function:: magnum.Matrix3d.rotation(self)
:raise ValueError: If the normalized rotation part is not orthogonal
.. py:function:: magnum.Matrix4.rotation(self)
:raise ValueError: If the normalized rotation part is not orthogonal
.. py:function:: magnum.Matrix4d.rotation(self)
:raise ValueError: If the normalized rotation part is not orthogonal
.. py:function:: magnum.Matrix3.rotation_normalized
:raise ValueError: If the rotation part is not orthogonal
.. py:function:: magnum.Matrix3d.rotation_normalized
:raise ValueError: If the rotation part is not orthogonal
.. py:function:: magnum.Matrix4.rotation_normalized
:raise ValueError: If the rotation part is not orthogonal
.. py:function:: magnum.Matrix4d.rotation_normalized
:raise ValueError: If the rotation part is not orthogonal
.. py:function:: magnum.Matrix3.uniform_scaling_squared
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix3d.uniform_scaling_squared
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix4.uniform_scaling_squared
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix4d.uniform_scaling_squared
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix3.uniform_scaling
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix3d.uniform_scaling
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix4.uniform_scaling
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix4d.uniform_scaling
:raise ValueError: If the matrix doesn't have uniform scaling
.. py:function:: magnum.Matrix3.inverted_rigid
:raise ValueError: If the matrix doesn't represent a rigid transformation
.. py:function:: magnum.Matrix3d.inverted_rigid
:raise ValueError: If the matrix doesn't represent a rigid transformation
.. py:function:: magnum.Matrix4.inverted_rigid
:raise ValueError: If the matrix doesn't represent a rigid transformation
.. py:function:: magnum.Matrix4d.inverted_rigid
:raise ValueError: If the matrix doesn't represent a rigid transformation
.. py:function:: magnum.math.half_angle(normalized_a: magnum.Quaternion, normalized_b: magnum.Quaternion)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.half_angle(normalized_a: magnum.Quaterniond, normalized_b: magnum.Quaterniond)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.lerp(normalized_a: magnum.Quaternion, normalized_b: magnum.Quaternion, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.lerp(normalized_a: magnum.Quaterniond, normalized_b: magnum.Quaterniond, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.lerp_shortest_path(normalized_a: magnum.Quaternion, normalized_b: magnum.Quaternion, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.lerp_shortest_path(normalized_a: magnum.Quaterniond, normalized_b: magnum.Quaterniond, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.slerp(normalized_a: magnum.Quaternion, normalized_b: magnum.Quaternion, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.slerp(normalized_a: magnum.Quaterniond, normalized_b: magnum.Quaterniond, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.slerp_shortest_path(normalized_a: magnum.Quaternion, normalized_b: magnum.Quaternion, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.math.slerp_shortest_path(normalized_a: magnum.Quaterniond, normalized_b: magnum.Quaterniond, t: float)
:raise ValueError: If either of the quaternions is not normalized
.. py:function:: magnum.Quaternion.rotation(angle: magnum.Rad, normalized_axis: magnum.Vector3)
:raise ValueError: If :p:`normalized_axis` is not normalized
.. py:function:: magnum.Quaternion.rotation(normalized_from: magnum.Vector3, normalized_to: magnum.Vector3)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.Quaterniond.rotation(angle: magnum.Rad, normalized_axis: magnum.Vector3d)
:raise ValueError: If :p:`normalized_axis` is not normalized
.. py:function:: magnum.Quaternion.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Quaterniond.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Quaternion.from_matrix
:raise ValueError: If :p:`matrix` is not a rotation
.. py:function:: magnum.Quaterniond.from_matrix
:raise ValueError: If :p:`matrix` is not a rotation
.. py:function:: magnum.Quaternion.angle
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaterniond.angle
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaternion.axis
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaterniond.axis
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaternion.inverted_normalized
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaterniond.inverted_normalized
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaternion.transform_vector_normalized
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.Quaterniond.transform_vector_normalized
:raise ValueError: If the quaternion is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector2, normalized_b: magnum.Vector2)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector2d, normalized_b: magnum.Vector2d)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector3, normalized_b: magnum.Vector3)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector3d, normalized_b: magnum.Vector3d)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector4, normalized_b: magnum.Vector4)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.math.angle(normalized_a: magnum.Vector4d, normalized_b: magnum.Vector4d)
:raise ValueError: If either of the vectors is not normalized
.. py:function:: magnum.Vector2.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. py:function:: magnum.Vector2d.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. py:function:: magnum.Vector3.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. py:function:: magnum.Vector3d.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. py:function:: magnum.Vector4.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. py:function:: magnum.Vector4d.projected_onto_normalized
:raise ValueError: If :p:`line` is not normalized
.. For pickling, because py::pickle() doesn't seem to have a way to set the
__setstate__ / __getstate__ docs directly FFS
.. py:function:: magnum.Deg.__getstate__
:summary: Dumps the in-memory representation as a float
.. py:function:: magnum.Rad.__getstate__
:summary: Dumps the in-memory representation as a float
.. py:function:: magnum.BitVector2.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.BitVector3.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.BitVector4.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.Vector2.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Color3.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Color4.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Matrix2x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Quaternion.__getstate__
:summary: Dumps the in-memory representation of quaternion components
.. py:function:: magnum.Quaterniond.__getstate__
:summary: Dumps the in-memory representation of quaternion components
.. py:function:: magnum.Range1D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range1Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range1Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Deg.__setstate__
:summary: Uses the float as the in-memory representation
.. py:function:: magnum.Rad.__setstate__
:summary: Uses the float as the in-memory representation
.. py:function:: magnum.BitVector2.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.BitVector3.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.BitVector4.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Color3.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Color4.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Quaternion.__setstate__
:summary: Treats the data as the in-memory representation of quaternion
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Quaterniond.__setstate__
:summary: Treats the data as the in-memory representation of quaternion
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. block-warning:: Subject to change
The :dox:`Math::swizzle()` operation is not yet available in the Python
API. Thanks to better flexibility of the Python language this will get
implemented as a *real* swizzle, allowing for convenient expressions
like :py:`vec.xz = (3.5, 0.1)`.
`Static constructors and instance method overloads`_
----------------------------------------------------
While not common in Python, the `Matrix4.scaling()` / `Matrix4.rotation()`
methods mimic the C++ equivalent --- calling `Matrix4.scaling()` will
return a scaling matrix, while :py:`mat.scaling()` returns the 3x3 scaling
part of the matrix. Similarly for the `Matrix3` class.
.. block-warning:: Subject to change
On the other hand, there's currently just `Matrix3.translation()` and
the corresponding :py:`mat.translation` property is temporarily
available as an underscored `Matrix3._translation`. This will change
later.
.. py:data:: magnum.math.pi
:summary: :math:`\pi`
.. py:data:: magnum.math.pi_half
:summary: Half of a :math:`\pi`
.. py:data:: magnum.math.pi_quarter
:summary: Quarter of a :math:`\pi`
.. py:data:: magnum.math.tau
:summary: :math:`\tau`
.. py:data:: magnum.math.e
:summary: Euler's number
.. py:data:: magnum.math.sqrt2
:summary: Square root of 2
.. py:data:: magnum.math.sqrt3
:summary: Square root of 3
.. py:data:: magnum.math.sqrt_half
:summary: Square root of :math:`\frac{1}{2}`
.. py:data:: magnum.math.nan
:summary: Quiet NaN
.. py:data:: magnum.math.inf
:summary: Positive :math:`\infty`

97
doc/python/magnum.meshtools.rst

@ -1,97 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:function:: magnum.meshtools.compress_indices
:raise AssertionError: If :p:`mesh` is not indexed
.. py:function:: magnum.meshtools.concatenate
:raise AssertionError: If :p:`meshes` is empty
:raise AssertionError: If any of the :p:`meshes` is
:ref:`MeshPrimitive.LINE_STRIP`, :ref:`MeshPrimitive.LINE_LOOP`,
:ref:`MeshPrimitive.TRIANGLE_STRIP` or
:ref:`MeshPrimitive.TRIANGLE_FAN`
:raise AssertionError: If all :p:`meshes` don't have the same
:ref:`MeshPrimitive`
.. py:function:: magnum.meshtools.duplicate
:raise AssertionError: If :p:`mesh` is not indexed
.. py:function:: magnum.meshtools.filter_attributes
:raise AssertionError: If size of :p:`attributes_to_keep` is different than
:p:`mesh` attribute count
.. py:function:: magnum.meshtools.generate_indices
:raise AssertionError: If :p:`mesh` is not :ref:`MeshPrimitive.LINE_STRIP`,
:ref:`MeshPrimitive.LINE_LOOP`, :ref:`MeshPrimitive.TRIANGLE_STRIP` or
:ref:`MeshPrimitive.TRIANGLE_FAN`
.. py:function:: magnum.meshtools.interleave
:raise AssertionError: If any attribute in :p:`extra` has the data size
different from :p:`mesh` vertex count
.. py:function:: magnum.meshtools.transform2d
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.POSITION` of index :p:`id` (and in morph
target :p:`morph_target_id` if not :py:`-1`)
:raise AssertionError: If :ref:`trade.MeshAttribute.POSITION` are not 2D
.. py:function:: magnum.meshtools.transform2d_in_place
:raise AssertionError: If :p:`mesh` vertex data aren't
:ref:`trade.DataFlags.MUTABLE`
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.POSITION` of index :p:`id` (and in morph
target :p:`morph_target_id` if not :py:`-1`)
:raise AssertionError: If :ref:`trade.MeshAttribute.POSITION` are not
:ref:`VertexFormat.VECTOR2`
.. py:function:: magnum.meshtools.transform3d
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.POSITION` of index :p:`id` (and in morph
target :p:`morph_target_id` if not :py:`-1`)
:raise AssertionError: If :ref:`trade.MeshAttribute.POSITION` are not 3D
.. py:function:: magnum.meshtools.transform3d_in_place
:raise AssertionError: If :p:`mesh` vertex data aren't
:ref:`trade.DataFlags.MUTABLE`
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.POSITION` of index :p:`id` (and in morph
target :p:`morph_target_id` if not :py:`-1`)
:raise AssertionError: If :ref:`trade.MeshAttribute.POSITION` are not
:ref:`VertexFormat.VECTOR3`
.. py:function:: magnum.meshtools.transform_texture_coordinates2d
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.TEXTURE_COORDINATES` of index :p:`id` (and in
morph target :p:`morph_target_id` if not :py:`-1`)
.. py:function:: magnum.meshtools.transform_texture_coordinates2d_in_place
:raise AssertionError: If :p:`mesh` vertex data aren't
:ref:`trade.DataFlags.MUTABLE`
:raise KeyError: If :p:`mesh` doesn't have
:ref:`trade.MeshAttribute.TEXTURE_COORDINATES` of index :p:`id` (and in
morph target :p:`morph_target_id` if not :py:`-1`)
:raise AssertionError: If :ref:`trade.MeshAttribute.TEXTURE_COORDINATES`
are not :ref:`VertexFormat.VECTOR2`

28
doc/python/magnum.platform.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -26,16 +25,18 @@
.. py:module:: magnum.platform
Concrete implementations of :py:`Application` and :py:`WindowlessApplication`
classes are available in submodules, and it's up to you which one you
choose. For example:
While concrete implementations of :py:`Application` and
:py:`WindowlessApplication` classes are available in the submodules,
there's a convenience logic importing the most fitting implementation
that's available directly into the :py:`platform` module, meaning you can
do just this without having to think about a particular implementation,
for example:
.. code:: py
from magnum import platform
import magnum.platform.sdl2
class MyApp(platform.sdl2.Application):
class MyApp(platform.Application): # platform.sdl2.Application
...
The same goes for :py:`WindowlessApplication` implementations, for example:
@ -43,16 +44,11 @@
.. code:: py
from magnum import platform
import magnum.platform.egl
class MyApp(platform.egl.WindowlessApplication):
class MyApp(platform.WindowlessApplication): # platform.egl.WindowlessApp
...
Alternatively, if you want to narrow down the mention of a particular
toolkit to just one line, you can also do:
.. block-warning:: Subject to change
.. code:: py
from magnum.platform.sdl2 import Application
class MyApp(Application):
At the moment, there's no way to specify a different priority order or
disable the auto-import altogether.

70
doc/python/magnum.primitives.rst

@ -1,70 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:function:: magnum.primitives.capsule2d_wireframe
:raise AssertionError: If :p:`hemisphere_rings` is less than :py:`1`
:raise AssertionError: If :p:`cylinder_rings` is less than :py:`1`
.. py:function:: magnum.primitives.capsule3d_solid
:raise AssertionError: If :p:`hemisphere_rings` is less than :py:`1`
:raise AssertionError: If :p:`cylinder_rings` is less than :py:`1`
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.capsule3d_wireframe
:raise AssertionError: If :p:`hemisphere_rings` is less than :py:`1`
:raise AssertionError: If :p:`cylinder_rings` is less than :py:`1`
:raise AssertionError: If :p:`segments` is zero or not a multiple of
:py:`4`
.. py:function:: magnum.primitives.circle2d_solid
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.circle2d_wireframe
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.circle3d_solid
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.circle3d_wireframe
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.cone_solid
:raise AssertionError: If :p:`rings` is less than :py:`1`
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.cone_wireframe
:raise AssertionError: If :p:`segments` is zero or not a multiple of
:py:`4`
.. py:function:: magnum.primitives.cylinder_solid
:raise AssertionError: If :p:`rings` is less than :py:`1`
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.cylinder_wireframe
:raise AssertionError: If :p:`rings` is less than :py:`1`
:raise AssertionError: If :p:`segments` is zero or not a multiple of
:py:`4`
.. py:function:: magnum.primitives.uv_sphere_solid
:raise AssertionError: If :p:`rings` is less than :py:`2`
:raise AssertionError: If :p:`segments` is less than :py:`3`
.. py:function:: magnum.primitives.uv_sphere_wireframe
:raise AssertionError: If :p:`rings` is zero or not a multiple of :py:`2`
:raise AssertionError: If :p:`segments` is zero or not a multiple of
:py:`4`

280
doc/python/magnum.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -26,274 +25,15 @@
.. roles used for all other docs
.. role:: cpp(code)
:language: c++
.. role:: py(code)
:language: py
.. role:: link-ref(link)
:class: m-doc
.. doctest setup
>>> from magnum import *
.. py:module:: magnum
:data BUILD_DEPRECATED: Build with deprecated features enabled
:data BUILD_STATIC: Static library build
:data TARGET_GL: OpenGL interoperability
:data TARGET_GLES: OpenGL ES target
:data TARGET_GLES2: OpenGL ES 2.0 target
:data TARGET_WEBGL: WebGL target
:data TARGET_EGL: EGL target
:data TARGET_VK: Vulkan interoperability
.. py:enum:: magnum.PixelFormat
The ``size``, ``channel_format``, ``channel_count``, ``is_normalized``,
``is_integral``, ``is_floating_point``, ``is_srgb``,
``is_depth_or_stencil`` and ``is_implementation_specific`` properties match
:dox:`pixelFormatSize()`, :dox:`pixelFormatChannelFormat()` and other
helpers.
.. code:: pycon
>>> PixelFormat.RGB8_SRGB.channel_count
3
>>> PixelFormat.RGB16F.is_floating_point
True
.. py:enum:: magnum.CompressedPixelFormat
The ``block_size``, ``block_data_size`` and ``is_implementation_specific``
properties match :dox:`compressedPixelFormatBlockSize()`,
:dox:`compressedPixelFormatBlockDataSize()` and other helpers.
.. code:: pycon
>>> CompressedPixelFormat.ASTC_6X5_RGBA_SRGB.block_size
Vector(6, 5, 1)
>>> CompressedPixelFormat.ASTC_6X5_RGBA_SRGB.block_data_size
16
.. py:class:: magnum.Image1D
See :ref:`Image2D` for more information.
.. py:class:: magnum.Image2D
An owning counterpart to :ref:`ImageView2D` / :ref:`MutableImageView2D`.
Holds its own data buffer, thus doesn't have an equivalent to
:ref:`ImageView2D.owner`. The :ref:`data` and :ref:`pixels` views allow
mutable access. Implicitly convertible to :ref:`ImageView2D` /
:ref:`MutableImageView2D`, so all APIs consuming image views work with this
type as well.
.. py:class:: magnum.Image3D
See :ref:`Image2D` for more information.
.. py:class:: magnum.CompressedImage1D
See :ref:`CompressedImage2D` for more information.
.. py:class:: magnum.CompressedImage2D
An owning counterpart to :ref:`CompressedImageView2D` /
:ref:`MutableCompressedImageView2D`. Holds its own data buffer, thus
doesn't have an equivalent to :ref:`CompressedImageView2D.owner`. The
:ref:`data` view allows mutable access. Implicitly convertible to
:ref:`CompressedImageView2D` / :ref:`MutableCompressedImageView2D`, so all
APIs consuming image views work with this type as well.
.. py:class:: magnum.CompressedImage3D
See :ref:`CompressedImage2D` for more information.
.. py:class:: magnum.ImageView1D
See :ref:`ImageView2D` for more information.
.. py:class:: magnum.ImageView2D
:TODO: remove this line once m.css stops ignoring first caption on a page
`Memory ownership and reference counting`_
==========================================
Similarly to :ref:`corrade.containers.ArrayView` (and unlike in C++), the
view keeps a reference to the original memory owner object in the
:ref:`owner` field, meaning that calling :py:`del` on the original object
will *not* invalidate the view. Slicing a view creates a new view
referencing the same original object, without any dependency on the
previous view. That means a long chained slicing operation will not cause
increased memory usage.
The :ref:`owner` is :py:`None` if the view is empty.
`Pixel data access`_
====================
The class makes use of Python's dynamic nature and provides direct access
to pixel data in their concrete types via :ref:`pixels`. The returned views
point to the underlying image data, element access coverts to a type
corresponding to a particular :ref:`PixelFormat` and for
performance-oriented access the view implements a buffer protocol with a
corresponding type annotation.
Normalized formats (such as :ref:`PixelFormat.RGB8_UNORM` but also
:ref:`PixelFormat.RGBA8_SRGB`) are unpacked to a corresponding
floating-point representation in element access and packed from a
floating-point representation in mutable acess. The type annotation is
however still matching the original type (such as :py:`'3B'` / :py:`'4B'`
in these cases), so code consuming these via the buffer protocol needs to
handle the normalization explicitly if needed.
..
>>> from magnum import *
>>> import numpy as np
>>> import array
.. code:: pycon
>>> data = array.array('B', [0xf3, 0x2a, 0x80, 0x23, 0x00, 0xff, 0x00, 0xff])
>>> image = ImageView2D(PixelFormat.RGBA8_SRGB, (2, 1), data)
>>> image.pixels[0, 0] # sRGB -> float conversion
Vector(0.896269, 0.0231534, 0.215861, 0.137255)
>>> np.array(image.pixels, copy=False)[0]
array([[243, 42, 128, 35],
[ 0, 255, 0, 255]], dtype=uint8)
.. py:class:: magnum.ImageView3D
See :ref:`ImageView2D` for more information.
.. py:class:: magnum.MutableImageView1D
See :ref:`ImageView2D` for more information. The only difference to the
non-mutable variant is that it's possible to modify the image through
:ref:`data` and :ref:`pixels`.
.. py:class:: magnum.MutableImageView2D
See :ref:`ImageView2D` for more information. The only difference to the
non-mutable variant is that it's possible to modify the image through
:ref:`data` and :ref:`pixels`.
.. py:class:: magnum.MutableImageView3D
See :ref:`ImageView2D` for more information. The only difference to the
non-mutable variant is that it's possible to modify the image through
:ref:`data` and :ref:`pixels`.
.. py:function:: magnum.ImageView1D.__init__(self, arg0: magnum.ImageView1D)
:raise RuntimeError: If :ref:`trade.ImageData1D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData1D` in the :ref:`trade` module.
.. py:function:: magnum.ImageView2D.__init__(self, arg0: magnum.ImageView2D)
:raise RuntimeError: If :ref:`trade.ImageData2D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData2D` in the :ref:`trade` module.
.. py:function:: magnum.ImageView3D.__init__(self, arg0: magnum.ImageView3D)
:raise RuntimeError: If :ref:`trade.ImageData3D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData3D` in the :ref:`trade` module.
.. py:function:: magnum.MutableImageView1D.__init__(self, arg0: magnum.MutableImageView1D)
:raise RuntimeError: If :ref:`trade.ImageData1D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData1D` in the :ref:`trade` module.
.. py:function:: magnum.MutableImageView2D.__init__(self, arg0: magnum.MutableImageView2D)
:raise RuntimeError: If :ref:`trade.ImageData2D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData2D` in the :ref:`trade` module.
.. py:function:: magnum.MutableImageView3D.__init__(self, arg0: magnum.MutableImageView3D)
:raise RuntimeError: If :ref:`trade.ImageData3D.is_compressed` is :py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData3D` in the :ref:`trade` module.
.. py:class:: magnum.CompressedImageView1D
See :ref:`CompressedImageView2D` for more information.
.. py:class:: magnum.CompressedImageView2D
:TODO: remove this line once m.css stops ignoring first caption on a page
`Memory ownership and reference counting`_
==========================================
Similarly to :ref:`corrade.containers.ArrayView` (and unlike in C++), the
view keeps a reference to the original memory owner object in the
:ref:`owner` field, meaning that calling :py:`del` on the original object
will *not* invalidate the view. Slicing a view creates a new view
referencing the same original object, without any dependency on the
previous view. That means a long chained slicing operation will not cause
increased memory usage.
The :ref:`owner` is :py:`None` if the view is empty.
.. py:class:: magnum.CompressedImageView3D
See :ref:`CompressedImageView2D` for more information.
.. py:class:: magnum.MutableCompressedImageView1D
See :ref:`CompressedImageView2D` for more information. The only difference
to the non-mutable variant is that it's possible to modify the image
through :ref:`data`.
.. py:class:: magnum.MutableCompressedImageView2D
See :ref:`CompressedImageView2D` for more information. The only difference
to the non-mutable variant is that it's possible to modify the image
through :ref:`data`.
.. py:class:: magnum.MutableImageView3D
See :ref:`CompressedImageView2D` for more information. The only difference
to the non-mutable variant is that it's possible to modify the image
through :ref:`data`.
.. py:function:: magnum.CompressedImageView1D.__init__(self, arg0: magnum.CompressedImageView1D)
:raise RuntimeError: If :ref:`trade.ImageData1D.is_compressed` is
:py:`False`
This function is used to implement implicit conversion from
:ref:`trade.ImageData1D` in the :ref:`trade` module.
.. py:function:: magnum.CompressedImageView2D.__init__(self, arg0: magnum.CompressedImageView2D)
:raise RuntimeError: If :ref:`trade.ImageData2D.is_compressed` is
:py:`False`
This function is used to implement implicit conversion from
:ref:`trade.ImageData2D` in the :ref:`trade` module.
.. py:function:: magnum.CompressedImageView3D.__init__(self, arg0: magnum.CompressedImageView3D)
:raise RuntimeError: If :ref:`trade.ImageData3D.is_compressed` is
:py:`False`
This function is used to implement implicit conversion from
:ref:`trade.ImageData3D` in the :ref:`trade` module.
.. py:function:: magnum.MutableCompressedImageView1D.__init__(self, arg0: magnum.MutableCompressedImageView1D)
:raise RuntimeError: If :ref:`trade.ImageData1D.is_compressed` is
:py:`False`
This function is used to implement implicit conversion from
:ref:`trade.ImageData1D` in the :ref:`trade` module.
.. py:function:: magnum.MutableCompressedImageView2D.__init__(self, arg0: magnum.MutableCompressedImageView2D)
:raise RuntimeError: If :ref:`trade.ImageData2D.is_compressed` is
:py:`True`
This function is used to implement implicit conversion from
:ref:`trade.ImageData2D` in the :ref:`trade` module.
.. py:function:: magnum.MutableCompressedImageView3D.__init__(self, arg0: magnum.MutableCompressedImageView3D)
:raise RuntimeError: If :ref:`trade.ImageData3D.is_compressed` is
:py:`False`
This function is used to implement implicit conversion from
:ref:`trade.ImageData3D` in the :ref:`trade` module.
.. TODO: change this to py:ref or something when we are able to reference names
.. default-role:: py

3
doc/python/magnum.scenegraph.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a

75
doc/python/magnum.scenetools.rst

@ -1,75 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:function:: magnum.scenetools.filter_fields
:raise AssertionError: If size of :p:`fields_to_keep` is different than
:ref:`trade.SceneData.field_count`
.. py:function:: magnum.scenetools.filter_field_entries
:raise AssertionError: If any field in :p:`entries_to_keep` does not exist
in :p:`scene`
:raise AssertionError: If any field in :p:`entries_to_keep` is listed more
than once
:raise AssertionError: If size of any array in :p:`entries_to_keep` does
not match :ref:`trade.SceneData.field_size()` for given field
.. py:function:: magnum.scenetools.filter_objects
:raise AssertionError: If size of :p:`objects_to_keep` is different than
:ref:`trade.SceneData.mapping_bound`
.. py:function:: magnum.scenetools.parents_breadth_first
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`
.. py:function:: magnum.scenetools.children_depth_first
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`
.. py:function:: magnum.scenetools.absolute_field_transformations2d(scene: magnum.trade.SceneData, field: magnum.trade.SceneField, global_transformation: magnum.Matrix3)
:raise KeyError: If :p:`field` does not exist in :p:`scene`
:raise AssertionError: If :p:`scene` is not 2D
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`
.. py:function:: magnum.scenetools.absolute_field_transformations2d(scene: magnum.trade.SceneData, field_id: int, global_transformation: magnum.Matrix3)
:raise IndexError: If :p:`field_id` negative or not less than
:ref:`trade.SceneData.field_count`
:raise AssertionError: If :p:`scene` is not 2D
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`
.. py:function:: magnum.scenetools.absolute_field_transformations3d(scene: magnum.trade.SceneData, field: magnum.trade.SceneField, global_transformation: magnum.Matrix4)
:raise KeyError: If :p:`field` does not exist in :p:`scene`
:raise AssertionError: If :p:`scene` is not 2D
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`
.. py:function:: magnum.scenetools.absolute_field_transformations3d(scene: magnum.trade.SceneData, field_id: int, global_transformation: magnum.Matrix4)
:raise IndexError: If :p:`field_id` negative or not less than
:ref:`trade.SceneData.field_count`
:raise AssertionError: If :p:`scene` is not 2D
:raise AssertionError: If :p:`scene` does not have
:ref:`trade.SceneField.PARENT`

132
doc/python/magnum.shaders.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -24,125 +23,20 @@
DEALINGS IN THE SOFTWARE.
..
.. py:class:: magnum.shaders.DistanceFieldVectorGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:data:: magnum.shaders.VertexColor2D.POSITION
:summary: Two-component vertex position
.. py:class:: magnum.shaders.DistanceFieldVectorGL3D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:data:: magnum.shaders.VertexColor3D.POSITION
:summary: Three-component vertex position
.. py:property:: magnum.shaders.DistanceFieldVectorGL2D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.DistanceFieldVectorGL3D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:data:: magnum.shaders.VertexColor2D.COLOR3
:summary: Three-component vertex color
.. py:class:: magnum.shaders.FlatGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
:data COLOR3: Three-component vertex color
:data COLOR4: Four-component vertex color
:data TRANSFORMATION_MATRIX: (Instanced) transformation matrix
:data TEXTURE_OFFSET: (Instanced) texture offset
.. py:data:: magnum.shaders.VertexColor3D.COLOR3
:summary: Three-component vertex color
.. py:class:: magnum.shaders.FlatGL3D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
:data COLOR3: Three-component vertex color
:data COLOR4: Four-component vertex color
:data TRANSFORMATION_MATRIX: (Instanced) transformation matrix
:data TEXTURE_OFFSET: (Instanced) texture offset
.. py:data:: magnum.shaders.VertexColor2D.COLOR4
:summary: Four-component vertex color
.. py:property:: magnum.shaders.FlatGL2D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.FlatGL3D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.FlatGL2D.alpha_mask
:raise AttributeError: If the shader was not created with
:ref:`Flags.ALPHA_MASK`
.. py:property:: magnum.shaders.FlatGL3D.alpha_mask
:raise AttributeError: If the shader was not created with
:ref:`Flags.ALPHA_MASK`
.. py:function:: magnum.shaders.FlatGL2D.bind_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURED`
.. py:function:: magnum.shaders.FlatGL3D.bind_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURED`
.. py:class:: magnum.shaders.VertexColorGL2D
:data POSITION: Vertex position
:data COLOR3: Three-component vertex color
:data COLOR4: Four-component vertex color
.. py:class:: magnum.shaders.VertexColorGL3D
:data POSITION: Vertex position
:data COLOR3: Three-component vertex color
:data COLOR4: Four-component vertex color
.. py:class:: magnum.shaders.PhongGL
:data POSITION: Vertex position
:data NORMAL: Normal direction
:data TANGENT: Tangent direction
:data TANGENT4: Tangent direction with a bitangent sign
:data BITANGENT: Bitangent direction
:data TEXTURE_COORDINATES: 2D texture coordinates
:data COLOR3: Three-component vertex color
:data COLOR4: Four-component vertex color
:data TRANSFORMATION_MATRIX: (Instanced) transformation matrix
:data NORMAL_MATRIX: (Instanced) normal matrix
:data TEXTURE_OFFSET: (Instanced) texture offset
.. py:property:: magnum.shaders.PhongGL.normal_texture_scale
:raise AttributeError: If the shader was not created with
:ref:`Flags.NORMAL_TEXTURE`
.. py:property:: magnum.shaders.PhongGL.alpha_mask
:raise AttributeError: If the shader was not created with
:ref:`Flags.ALPHA_MASK`
.. py:property:: magnum.shaders.PhongGL.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.PhongGL.light_positions
:raise ValueError: If list length is different from :ref:`light_count`
.. py:property:: magnum.shaders.PhongGL.light_colors
:raise ValueError: If list length is different from :ref:`light_count`
.. py:property:: magnum.shaders.PhongGL.light_ranges
:raise ValueError: If list length is different from :ref:`light_count`
.. py:function:: magnum.shaders.PhongGL.bind_ambient_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.AMBIENT_TEXTURE`
.. py:function:: magnum.shaders.PhongGL.bind_diffuse_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.DIFFUSE_TEXTURE`
.. py:function:: magnum.shaders.PhongGL.bind_specular_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.SPECULAR_TEXTURE`
.. py:function:: magnum.shaders.PhongGL.bind_normal_texture
:raise AttributeError: If the shader was not created with
:ref:`Flags.NORMAL_TEXTURE`
.. py:function:: magnum.shaders.PhongGL.bind_textures
:raise AttributeError: If the shader was not created with any of
:ref:`Flags.AMBIENT_TEXTURE`, :ref:`Flags.DIFFUSE_TEXTURE`,
:ref:`Flags.SPECULAR_TEXTURE` or :ref:`Flags.NORMAL_TEXTURE`
.. py:class:: magnum.shaders.VectorGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:class:: magnum.shaders.VectorGL3D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:property:: magnum.shaders.VectorGL2D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.VectorGL3D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:data:: magnum.shaders.VertexColor3D.COLOR4
:summary: Four-component vertex color

169
doc/python/magnum.text.rst

@ -1,169 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. py:class:: magnum.text.FontManager
:summary: Manager for :ref:`AbstractFont` plugin instances
Each plugin returned by :ref:`instantiate()` or :ref:`load_and_instantiate()`
references its owning :ref:`FontManager` through
:ref:`AbstractFont.manager`, ensuring the manager is not deleted before the
plugin instances are.
.. TODO couldn't the plugin_interface etc. docs be parsed from pybind's docs?
repeating them for every plugin is annoying
.. py:class:: magnum.text.AbstractFont
:data plugin_interface: Plugin interface string
:data plugin_search_paths: Plugin search paths
:data plugin_suffix: Plugin suffix
:data plugin_metadata_suffix: Plugin metadata suffix
Similarly to C++, font plugins are loaded through :ref:`FontManager`:
..
>>> from magnum import text
.. code:: py
>>> manager = text.FontManager()
>>> font = manager.load_and_instantiate('StbTrueTypeFont')
Unlike C++, errors in both API usage and file parsing are reported by
raising an exception. See particular function documentation for detailed
behavior.
.. py:function:: magnum.text.AbstractFont.open_data
:raise RuntimeError: If file opening fails
.. py:function:: magnum.text.AbstractFont.open_file
:raise RuntimeError: If file opening fails
For compatibility with :ref:`os.path`, on Windows this function converts
all backslashes in :p:`filename` to forward slashes before passing it to
:dox:`Text::AbstractFont::openFile()`, which expects forward slashes as
directory separators on all platforms.
.. py:property:: magnum.text.AbstractFont.size
:raise AssertionError: If no file is opened
.. py:property:: magnum.text.AbstractFont.ascent
:raise AssertionError: If no file is opened
.. py:property:: magnum.text.AbstractFont.descent
:raise AssertionError: If no file is opened
.. py:property:: magnum.text.AbstractFont.line_height
:raise AssertionError: If no file is opened
.. py:property:: magnum.text.AbstractFont.glyph_count
:raise AssertionError: If no file is opened
.. py:function:: magnum.text.AbstractFont.glyph_id
:raise AssertionError: If no file is opened
.. py:function:: magnum.text.AbstractFont.glyph_size
:raise AssertionError: If no file is opened
:raise IndexError: If :p:`glyph` is negative or not less than
:ref:`glyph_count`
.. py:function:: magnum.text.AbstractFont.glyph_advance
:raise AssertionError: If no file is opened
:raise IndexError: If :p:`glyph` is negative or not less than
:ref:`glyph_count`
.. py:function:: magnum.text.AbstractFont.fill_glyph_cache
:raise AssertionError: If no file is opened
.. py:function:: magnum.text.AbstractFont.create_shaper
:raise AssertionError: If no file is opened
.. TODO remove the copies once the base class methods don't leak to subclasses
.. py:property:: magnum.text.RendererCore.cursor
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.Renderer.cursor
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererGL.cursor
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererCore.alignment
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.Renderer.alignment
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererGL.alignment
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererCore.line_advance
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.Renderer.line_advance
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererGL.line_advance
:raise AssertionError: If setting this property while rendering is in
progress
.. py:property:: magnum.text.RendererGL.index_type
:raise AssertionError: If setting this property while rendering is in
progress
.. py:function:: magnum.text.RendererCore.add
:raise AssertionError: If :p:`shaper` font isn't present in
:ref:`glyph_cache`
.. py:function:: magnum.text.Renderer.add
:raise AssertionError: If :p:`shaper` font isn't present in
:ref:`glyph_cache`
.. py:function:: magnum.text.RendererGL.add
:raise AssertionError: If :p:`shaper` font isn't present in
:ref:`glyph_cache`
.. py:function:: magnum.text.RendererGL.render(self, shaper: magnum.text.AbstractShaper, size: float, text: str, features: list[magnum.text.FeatureRange])
:raise AssertionError: If :p:`shaper` font isn't present in
:ref:`glyph_cache`
.. py:enum:: magnum.text.Feature
The equivalent to C++ :dox:`Text::feature()` is passing the four-character
code to the constructor:
..
>>> from magnum import text
.. code:: pycon
>>> feature = text.Feature('kern')
>>> feature.name
'KERNING'
.. py:enum:: magnum.text.Script
The equivalent to C++ :dox:`Text::script()` is passing the four-character
code to the constructor:
..
>>> from magnum import text
.. code:: pycon
>>> script = text.Script('Latn')
>>> script.name
'LATIN'

1479
doc/python/magnum.trade.rst

File diff suppressed because it is too large Load Diff

BIN
doc/python/numpy.inv

Binary file not shown.

128
doc/python/pages/api-conventions.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -27,11 +26,8 @@
Python API conventions
######################
:summary: Basic rules and good practices for both Python binding developers and
:summary: Basic rules and good practices for both Python binding develpoers and
users.
:ref-prefix:
corrade
magnum
`API naming`_
=============
@ -45,31 +41,16 @@ Python API conventions
- constants and enums ``UPPERCASE``, again underscores omitted if it doesn't
hurt readability
`Preprocessor definitions`_
---------------------------
Exposed to Python as plain boolean constants, and only those that actually are
useful in a Python setting.
.. class:: m-table
=================================== ==================================
C++ Python
=================================== ==================================
:dox:`CORRADE_BUILD_MULTITHREADED` :ref:`corrade.BUILD_MULTITHREADED`
:dox:`MAGNUM_TARGET_GLES` :ref:`magnum.TARGET_GLES`
=================================== ==================================
`Namespaces / modules`_
-----------------------
`Namespaces`_
-------------
.. class:: m-table
=================================== ============================
C++ Python
=================================== ============================
:dox:`Magnum::Math` :ref:`magnum.math`
:dox:`Magnum::SceneGraph` :ref:`magnum.scenegraph`
:dox:`Magnum::Math` `magnum.math`
:dox:`Magnum::SceneGraph` `magnum.scenegraph`
=================================== ============================
`Classes`_
@ -80,8 +61,8 @@ C++ Python
=================================== ============================
C++ Python
=================================== ============================
:dox:`Vector2i` :ref:`Vector2i`
:dox:`GL::Buffer` :ref:`gl.Buffer`
:dox:`Vector2i` `Vector2i`
:dox:`GL::Buffer` `gl.Buffer`
=================================== ============================
`Functions`_
@ -89,62 +70,41 @@ C++ Python
.. class:: m-table
=============================================================== ===========
C++ Python
=============================================================== ===========
:dox:`Math::angle()` :ref:`math.angle()`
:dox:`Vector2::xAxis() <Math::Vector2::xAxis()>` :ref:`Vector2.x_axis()`
:dox:`v.isZero() <Math::Vector::isZero()>` :ref:`v.is_zero() <Vector3.is_zero()>`
:dox:`m.transformVector(a) <Math::Matrix4::transformVector()>` :ref:`m.transform_vector(a) <Matrix4.transform_vector()>`
=============================================================== ===========
================================================ ==========================
C++ Python
================================================ ==========================
:dox:`Math::angle()` `math.angle()`
:dox:`Vector2::xAxis() <Math::Vector2::xAxis()>` `Vector2.x_axis()`
:cpp:`v.isZero()` :py:`v.is_zero()`
:cpp:`m.transformVector(a)` :py:`m.transform_vector(a)`
================================================ ==========================
`Enums`_
--------
Custom construction helpers for enums are converted to functions directly on
the Python enum class.
.. class:: m-table
============================================== ============================
C++ Python
============================================== ============================
:dox:`PixelFormat::RGB8Unorm` :ref:`PixelFormat.RGB8_UNORM`
:dox:`MeshPrimitive::TriangleStrip` :ref:`MeshPrimitive.TRIANGLE_STRIP`
:dox:`Trade::meshAttributeCustom()` :ref:`trade.MeshAttribute.CUSTOM() <trade.MeshAttribute>`
:dox:`Trade::isMeshAttributeCustom()` :ref:`trade.MeshAttribute.is_custom <trade.MeshAttribute>`
============================================== ============================
`Enum sets`_
------------
Compared to C++, there's just one enum type with a plural name, and it contains
both the values and binary operators. Additionally, there's an explicit
``NONE`` value for an empty set.
.. class:: m-table
============================================== ============================
C++ Python
============================================== ============================
:dox:`Trade::DataFlag::Mutable` :ref:`trade.DataFlags.MUTABLE`
:dox:`Trade::DataFlags{} <Trade::DataFlags>` :ref:`trade.DataFlags.NONE`
:dox:`PixelFormat::RGB8Unorm` `PixelFormat.RGB8UNORM`
:dox:`MeshPrimitive::TriangleStrip` :py:`MeshPrimitive.TRIANGLE_STRIP`
============================================== ============================
`Constants`_
------------
Apart from :dox:`Math::Constants`, which are exposed directly as members of the
:ref:`magnum.math` submodule to mimic Python's :ref:`math`, most of the
constants used throughout the C++ API are related to templates. Those are,
where applicable, converted to Python builtins such as :py:`len()`.
`math` submodule to mimic Python's :py:`math`, most of the constants used
throughout the C++ API are related to templates. Those are, where applicable,
converted to Python builtins such as :py:`len()`.
.. class:: m-table
============================================== ============================
C++ Python
============================================== ============================
:dox:`Constants::pi() <Math::Constants::pi()>` :ref:`math.pi <magnum.math.pi>`
:dox:`Constants::pi() <Math::Constants::pi()>` `math.pi`
:dox:`Math::Vector::Size` :py:`len(vec)`
============================================== ============================
@ -211,52 +171,10 @@ In particular, both the C++ and the Python API is designed in a way to prevent
too generic or confusing names in the root namespace / module and also keeping
it relatively clean and small, without too many symbols. On the other hand, the
subnamespaces *do* have generic names. The :dox:`GL::version()` /
:ref:`gl.version()` API is one example --- it's tucked in a subnamespace so the
`gl.version()` API is one example --- it's tucked in a subnamespace so the
generic name isn't a problem, but you wouldn't find anything of similar
genericity in the root namespace / module.
An exception to this rule is exposed preprocessor definitions --- these are
*not* pulled in when doing :py:`from magnum import *` as this would likely
cause conflicts (in particular, :ref:`BUILD_STATIC` is defined by Corrade as
well). Instead, you have to access them like this:
.. code:: py
import magnum
if magnum.TARGET_GLES2:
format = gl.TextureFormat.RGBA8
else:
format = gl.TextureFormat.R8
`Handling of alternate implementations`_
----------------------------------------
C++ APIs that have alternative implementations (such as
:dox:`Platform::Sdl2Application` vs. :dox:`Platform::GlfwApplication`, or
:dox:`SceneGraph::MatrixTransformation3D` vs.
:dox:`SceneGraph::TranslationRotationScalingTransformation3D`) either provide
:cpp:`typedef`\ s based on what header you include or require you to
:cpp:`typedef` them yourselves:
.. code:: c++
class MyApplication: Platform::Application {}; // depends on what you include
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
In Python, the alternate implementations are tucked in submodules (such as
:ref:`platform.sdl2` vs. :ref:`platform.glfw`, or :ref:`scenegraph.matrix` vs.
:ref:`scenegraph.trs`), each submodule providing the same names (such as
:ref:`Application <platform.sdl2.Application>` or
:ref:`Object3D <scenegraph.matrix.Object3D>`)
and the designed way to use them is via :py:`from ... import`:
.. code:: py
from magnum.platform.sdl2 import Application
from magnum.scenegraph.trs import Scene3D, Object3D
`Basic guarantees`_
===================

95
doc/python/pages/building.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -29,13 +28,8 @@ Downloading and building
.. role:: sh(code)
:language: sh
.. role:: bat(code)
:language: bat
:summary: Installation guide for the Python bindings.
:ref-prefix:
corrade
magnum
Building of Python bindings is a similar process to
:dox:`building Magnum itself <building>` with an additional step involving
@ -61,7 +55,7 @@ the source tree.
.. code:: sh
git clone https://github.com/mosra/magnum-bindings && cd magnum-bindings
git clone git://github.com/mosra/magnum-bindings && cd magnum-bindings
cd package/archlinux
makepkg -fp PKGBUILD
@ -73,22 +67,16 @@ Once built, install the package using ``pacman``:
.. code:: sh
sudo pacman -U magnum-bindings-*.pkg.tar.zst
sudo pacman -U magnum-bindings-*.pkg.tar.xz
`Homebrew formulas for macOS`_
------------------------------
macOS `Homebrew <https://brew.sh>`_ formulas building the latest Git revision
are in the ``package/homebrew`` directory. Either use the ``*.rb`` files
directly or use the tap at https://github.com/mosra/homebrew-magnum. This will
install the latest stable version of Magnum Bindings with all its dependencies:
.. code:: sh
brew install mosra/magnum/magnum-bindings
But often you may want to install the latest Git revision of all Magnum
projects instead:
are in the `package/homebrew` directory. Either use the `*.rb` files directly
or use the tap at https://github.com/mosra/homebrew-magnum. Right now, there's
no stable release of Python bindings yet, so you need to install the latest Git
revision of all Magnum projects instead:
.. code:: sh
@ -96,19 +84,14 @@ projects instead:
brew install --HEAD mosra/magnum/magnum
brew install --HEAD mosra/magnum/magnum-bindings
# If already installed, use the following to upgrade, in the same order
brew upgrade --fetch-HEAD mosra/magnum/corrade
brew upgrade --fetch-HEAD mosra/magnum/magnum
brew upgrade --fetch-HEAD mosra/magnum/magnum-bindings
When installing from the ``*.rb`` files you need to install the
When installing from the `*.rb` files you need to install the
:dox:`Corrade <building-corrade-packages-brew>` and
:dox:`Magnum <building-packages-brew>` Homebrew packages first. If you want to
pass additional flags to CMake or ``setup.py`` or enable / disable additional
features, edit the ``*.rb`` file.
There are also Homebrew packages for
:dox:`Magnum Plugins <building-plugins-packages-brew>`,
:dox:`Magnum Plugins <building-plugins-packages-brew>`
:dox:`Magnum Integration <building-integration-packages-brew>`,
:dox:`Magnum Extras <building-extras-packages-brew>` and
:dox:`Magnum Examples <building-examples-packages-brew>`.
@ -122,7 +105,7 @@ snapshot as a compressed archive or use the command line:
.. code:: sh
git clone https://github.com/mosra/magnum-bindings.git
git clone git://github.com/mosra/magnum-bindings.git
Assuming a Unix-based OS, the first step is to build the native libraries. The
bindings will be generated for all Corrade and Magnum libraries that are found,
@ -133,7 +116,7 @@ default location known to CMake, add their path to ``CMAKE_PREFIX_PATH``.
mkdir build && cd build
cmake .. \
-DMAGNUM_WITH_PYTHON=ON
-DWITH_PYTHON=ON
make
Note that pybind11 compilation is quite time- and memory-hungry, so you might
@ -155,39 +138,6 @@ In case Corrade or Magnum is built with :dox:`CORRADE_BUILD_STATIC` /
:dox:`MAGNUM_BUILD_STATIC`, the corresponding bindings are compiled into a
single dynamic module instead of one module per Corrade/Magnum library.
In this case, similarly to linking static plugins to Magnum's own command-line
utilities, you can use the ``MAGNUM_PYTHON_BINDINGS_STATIC_PLUGINS`` CMake
variable to link static plugins to the Python module, assuming Magnum, Magnum
Plugins and Magnum Bindings are all CMake subprojects. It's a
semicolon-separated list of existing CMake targets, for example
``Magnum::AnyImageImporter;MagnumPlugins::StbImageImporter``.
On Unix platforms, Python by default loads the modules in isolated namespaces.
That's a good thing to do from a security point of view, nevertheless with
static builds of Corrade and Magnum it will result in globals duplicated across
the Corrade and Magnum modules (and also any other Python modules that
use Magnum natively inside) unable to see each other in order to deduplicate
themselves, causing strange issues. To solve that, the
``MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL`` CMake option, which is enabled by
default on static builds on Unix platforms, overrides Python's module loading
code to not load them in isolated namespaces using :ref:`sys.setdlopenflags()`.
The override then happens inside :py:`import corrade` and is in effect for the
rest of the interpreter lifetime, to affect also any potential other modules
depending on Magnum loaded later. See also
:dox:`CORRADE_BUILD_STATIC_UNIQUE_GLOBALS` and
:dox:`MAGNUM_BUILD_STATIC_UNIQUE_GLOBALS` in Corrade and Magnum for more
information.
On Windows, Python since version 3.8 no longer loads dependency DLLs from
:bat:`%PATH%`. Instead, it requires relevant DLL directories to be explicitly
passed to :ref:`os.add_dll_directory()`. CMake by default adds the (absolute)
path to Corrade and Magnum DLLs there, you can edit the path or add additional
directories for other dependencies (such as SDL or GLFW) using the
``MAGNUM_PYTHON_BINDINGS_DLL_PATH`` CMake option. Non-absolute paths are
interpreted as relative to the package root --- for example, if the Corrade
module is in ``tools/python/corrade/``, specifying ``bin/`` as the DLL path
will resolve to ``tools/bin/``.
`Running unit tests`_
---------------------
@ -201,17 +151,16 @@ running them is then a matter of:
cd src/python/magnum
python -m unittest
.. block-default:: Disabling GL tests
.. block-warning:: Subject to change
If the tests detect that one of
:ref:`platform.WindowlessApplication <platform.egl.WindowlessApplication>`\ s
is present, GL tests (suffixed with ``_gl``) will be run as well. In order
to disable them (for example when running on a headless CI), set the
:sh:`$MAGNUM_SKIP_GL_TESTS` environment variable to ``ON``:
If the tests detect that one of `platform.WindowlessApplication`\ s is
present, GL tests (suffixed with ``_gl``) will be run as well. Currently
there's no way to blacklist them if windowless application implementations
are compiled, you can only whitelist-run the remaining tests:
.. code:: sh
MAGNUM_SKIP_GL_TESTS=ON python -m unittest
python -m unittest test.test_gl test.test_math # test.test_gl_gl is a GL test
For code coverage, `coverage.py <https://coverage.readthedocs.io/>`_ is used.
Get it via ``pip`` or as a system package.
@ -233,10 +182,8 @@ following commands, the resulting HTML overview is located in
`Continuous Integration`_
=========================
In ``package/ci/`` there is a ``circleci.yml`` file that compiles and tests the
bindings on Linux GCC 4.8 + CMake 3.5 and on macOS, online at
https://circleci.com/gh/mosra/magnum-bindings. For Windows there is an
``appveyor.yml`` testing on Windows with MSVC, online at
https://ci.appveyor.com/project/mosra/magnum-bindings. Code coverage for both
the C++ bindings code and Python side is reported to
In ``package/ci/`` there is a ``travis.yml`` file that compiles and tests the
bindings on Linux GCC 4.8 + CMake 3.1 and on macOS. Online at
https://travis-ci.org/mosra/magnum-bindings. Code coverage for both the C++
bindings code and Python side is reported to
https://codecov.io/gh/mosra/magnum-bindings.

238
doc/python/pages/changelog.rst

@ -1,238 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
Changelog
#########
:ref-prefix:
corrade
magnum
:some_directive: TODO: why can't the title below "just work" and I have to
add some bogus content before?
`Changes since 2020.06`_
========================
- Minimal supported CMake version is now 3.5, changed from 3.4, since CMake
3.27+ warns if a compatibility with CMake below 3.5 is requested. Older
versions are not supported anymore and all workarounds for them were
removed. This is a conservative change, as there are no known supported
distributions which would have anything older than 3.5.
- Exposed the :ref:`corrade.BUILD_DEPRECATED` and
:ref:`magnum.BUILD_DEPRECATED` constants, as some features may work
differently depending on these being enabled or not and it's useful to be
able to query this
- Exposed the new :ref:`containers.BitArray`, :ref:`containers.BitArrayView`,
:ref:`containers.StridedBitArrayView1D` containers, their mutable and
multi-dimensional counterparts as well as the
:ref:`containers.StridedArrayView*D.slice_bit() <containers.StridedArrayView1D.slice_bit()>`
utility
- Exposed missing :ref:`Vector4` constructor from a :ref:`Vector3` and a
W component and :ref:`Vector3` from :ref:`Vector2` and a Z component
- Renamed :py:`Matrix3.from()` / :py:`Matrix4.from()` to :ref:`Matrix3.from_()`
/ :ref:`Matrix4.from_()` because :py:`from` is a Python keyword and it
would be silly to have to write :py:`getattr(Matrix4, 'from')` just to use
these APIs
- Exposed newly added off-center variants of
:ref:`Matrix4.orthographic_projection()` and
:ref:`Matrix3.projection()`
- Exposed remaining vector/scalar, exponential and other functions in the
:ref:`math <magnum.math>` library
- Exposed the :ref:`CompressedPixelFormat` enum, various pixel-format-related
helper APIs are now properties on :ref:`PixelFormat` and
:ref:`CompressedPixelFormat`
- Exposed :ref:`CompressedImage2D`, :ref:`CompressedImageView2D`,
:ref:`MutableCompressedImageView2D` and their 1D and 3D counterparts
- Exposed :ref:`Color3.from_xyz()`, :ref:`Color3.from_linear_rgb_int()`,
:ref:`Color3.to_xyz()`, :ref:`Color3.to_linear_rgb_int()` and equivalent
APIs on :ref:`Color4`
- Exposed unsigned :ref:`Range1Dui`, :ref:`Range2Dui` and :ref:`Range3Dui`
types in addition to the signed variants
- Exposed new :ref:`Quaternion.rotation()`, :ref:`Quaternion.reflection()`,
:ref:`Quaternion.reflect_vector()`, :ref:`Quaternion.xyzw` and
:ref:`Quaternion.wxyz` APIs
- Exposed :ref:`gl.Context` and its platform-specific subclasses for EGL, WGL
and GLX
- Exposed :ref:`gl.Framebuffer.attach_texture()` and missing sRGB, depth
and stencil :ref:`gl.TextureFormat` values (see :gh:`mosra/magnum-bindings#14`)
- Exposed :ref:`gl.Renderer.set_blend_function()`,
:ref:`gl.Renderer.set_blend_equation()` and related enums (see :gh:`mosra/magnum-bindings#9`)
- Exposed :ref:`gl.Renderer.Feature.CLIP_DISTANCEn <gl.Renderer.Feature.CLIP_DISTANCE0>`
values that are new since 2020.06
- Exposed new instancing, texture transformation, normal-mapping-related and
lighting features in :ref:`shaders.PhongGL`
- Exposed new instancing and texture transformation features in
:ref:`shaders.FlatGL2D` and :ref:`shaders.FlatGL3D`
- Exposed :ref:`shaders.DistanceFieldVectorGL2D`,
:ref:`shaders.DistanceFieldVectorGL3D`, :ref:`shaders.VectorGL2D` and
:ref:`shaders.VectorGL3D` shaders
- Renamed all helper ``Python.h`` headers to ``PythonBindings.h`` to avoid
issues with shitty IDE indexers such as Eclipse, confusing these with
Python's ``<Python.h>``
- Minor performance fixes (see :gh:`mosra/magnum-bindings#10`,
:gh:`mosra/magnum-bindings#15`,
:gh:`mosra/magnum-bindings#16`,
:gh:`mosra/magnum-bindings#17`,
:gh:`mosra/magnum-bindings#19`,
:gh:`mosra/magnum-bindings#20`)
Travis banned everyone from using their CI and so all Linux and macOS
builds were migrated from Travis to Circle CI. See also
:gh:`mosra/magnum#350` and :gh:`mosra/magnum#523`.
- It's now possible to use ``<PackageName>_ROOT`` to point to install
locations of dependencies such as Corrade on CMake 3.12+, in addition to
putting them all together inside ``CMAKE_PREFIX_PATH``. See also
:gh:`mosra/magnum#614`.
- On CMake 3.16 and newer, ``FindMagnumBindings.cmake`` can provide
additional details if some component is not found
- The Homebrew package now uses ``std_cmake_args`` instead of hardcoded build
type and install prefix, which resolves certain build issues (see
:gh:`mosra/homebrew-magnum#6`)
- Added a caster for :dox:`Containers::Optional`, allowing it to be used
directly in function signatures and showing up on the Python side as either
:py:`None` or the actual value
- Various documentation fixes (see :gh:`mosra/magnum-bindings#11`)
- Fixed copypaste errors in bindings for :ref:`Range2D.center_x()` /
:ref:`Range2D.center_y()`, :ref:`Range3D.z()`, :ref:`Range3D.center_x()` /
:ref:`Range3D.center_y()` / :ref:`Range3D.center_z()`
- Fixed a copypaste error in
:ref:`platform.sdl2.Application.PointerMoveEvent.relative_position` and
:ref:`platform.glfw.Application.PointerMoveEvent.relative_position`
- Fixed :ref:`platform.sdl2.Application.Modifier` and
:ref:`platform.glfw.Application.Modifier` to behave properly
as flags and not just as an enum
- Exposed :ref:`meshtools.compress_indices()`, :ref:`meshtools.concatenate()`,
:ref:`meshtools.copy()`, :ref:`meshtools.duplicate()`,
:ref:`meshtools.filter_attributes()`,
:ref:`meshtools.filter_except_attributes()`,
:ref:`meshtools.filter_only_attributes()`,
:ref:`meshtools.generate_indices()`, :ref:`meshtools.interleave()`,
:ref:`meshtools.remove_duplicates()`,
:ref:`meshtools.remove_duplicates_fuzzy()`, :ref:`meshtools.transform2d()`,
:ref:`meshtools.transform2d_in_place()`, :ref:`meshtools.transform3d()`,
:ref:`meshtools.transform3d_in_place()`,
:ref:`meshtools.transform_texture_coordinates2d()` and
:ref:`meshtools.transform_texture_coordinates2d_in_place()`
- Exposed :ref:`platform.sdl2.Application.viewport_event` and
:ref:`platform.glfw.Application.viewport_event` and a possibility
to make the window resizable on startup
- Exposed :ref:`platform.sdl2.Application.exit_event` and
:ref:`platform.glfw.Application.exit_event`
- Exposed :ref:`platform.sdl2.Application.dpi_scaling` and
:ref:`platform.glfw.Application.dpi_scaling`
- Exposed :ref:`platform.glfw.Application.swap_interval` and
:ref:`platform.glfw.Application.main_loop_iteration`
- Exposed :ref:`platform.sdl2.Application.cursor` and
:ref:`platform.sdl2.Application.warp_cursor`, same for GLFW
- Exposed :ref:`platform.sdl2.Application.is_key_pressed()` and
:ref:`platform.glfw.Application.is_key_pressed()`
- Exposed all :ref:`platform.sdl2.Application.Configuration.WindowFlags` and
:ref:`platform.glfw.Application.Configuration.WindowFlags`
- Exposed the new :ref:`primitives.CubeFlags`
- Exposed the new :ref:`text.AbstractShaper`, :ref:`text.RendererCore`,
:ref:`text.Renderer`, :ref:`text.RendererGL` classes as well as the new
:ref:`text.Feature`, :ref:`text.Script` enums and the
:ref:`text.FeatureRange` helper, plus more :ref:`text.Alignment` options
- Exposed :ref:`trade.AbstractImporter.features` and
:ref:`trade.AbstractImporter.flags` and corresponding enums
- Exposed a basic interface of :ref:`trade.AbstractImageConverter` and
:ref:`trade.AbstractSceneConverter`
- Exposed the whole interface of :ref:`trade.MeshData` and
:ref:`trade.MeshAttributeData` including typed access to index and
attribute data, together with :ref:`VertexFormat`, :ref:`trade.DataFlags`,
:ref:`trade.AbstractImporter.mesh_attribute_name()` and
:ref:`trade.AbstractImporter.mesh_attribute_for_name()`
- Exposed the whole interface of :ref:`trade.MaterialData` including typed
access to attribute data, together with
:ref:`trade.AbstractImporter.material()` and related importer APIs
- Exposed the whole interface of :ref:`trade.SceneData` and
:ref:`trade.SceneFieldData` including typed access to mapping and field
data, together with :ref:`trade.AbstractImporter.scene()` and related
importer APIs
- Exposed :ref:`Color3.red()` and other convenience constructors (see
:gh:`mosra/magnum-bindings#12`)
- Exposed the :ref:`materialtools`, :ref:`scenetools` and :ref:`text`
libraries
- Exposed :ref:`utility.copy()` for convenient, fast and safe copying of
multi-dimensional strided arrays
- Exposed the minimal interface of :ref:`utility.ConfigurationGroup` and
:ref:`utility.Configuration`
- Exposed :ref:`pluginmanager.AbstractManager.set_preferred_plugins()`,
:ref:`pluginmanager.AbstractManager.register_external_manager()`, the base
:ref:`pluginmanager.AbstractPlugin` class and
:ref:`pluginmanager.PluginMetadata`
- Fixed issues with an in-source build (see :gh:`mosra/magnum-bindings#13`)
- All CMake build options are now prefixed with ``MAGNUM_``. For backwards
compatibility, unless ``MAGNUM_BUILD_DEPRECATED`` is disabled and unless a
prefixed option is already set during the initial run, the unprefixed
options are still recognized with a warning. See also :gh:`mosra/corrade#139`.
- Added a ``MAGNUM_PYTHON_BINDINGS_STATIC_PLUGINS`` CMake option for linking
static plugins to the Python bindings module. See the
:ref:`building documentation <std:doc:building>` for more information.
- Added a ``MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL`` CMake option to make
the Python bindings module loaded into the global namespace instead of
isolated in order to attempt to solve problems with duplicated globals when
static builds of Corrade and Magnum are linked into multiple dynamic
modules. See the :ref:`building documentation <std:doc:building>` for more
information.
`2020.06`_
==========
Released 2020-06-27, tagged as
:gh:`v2020.06 <mosra/magnum-bindings/releases/tag/v2020.06>`.
- Exposed :ref:`Matrix4.cofactor()`, :ref:`Matrix4.comatrix()`,
:ref:`Matrix4.adjugate()` (and equivalents in other matrix sizes), and
:ref:`Matrix4.normal_matrix()`
- Exposed :ref:`gl.AbstractFramebuffer.blit()` functions and related enums
- Exposed more keys in :ref:`platform.sdl2.Application` and
:ref:`platform.glfw.Application`
- Exposed :ref:`gl.AbstractTexture.unbind()`
- Exposed :ref:`trade.AbstractImporter.image2d_level_count()` and related
APIs for 1D and 3D
- Exposed :ref:`trade.MeshData` and related APIs, the previous
``trade.MeshData3D`` APIs are removed
- Exposed new APIs and tangent support in the :ref:`primitives` library
- :ref:`platform.sdl2.Application` and :ref:`platform.glfw.Application` now
provide a clear error instead of "pure virtual method call" in case
``draw_event()`` is not implemented
- Library version is now exposed through ``MAGNUMBINDINGS_VERSION_YEAR``,
``MAGNUMBINDINGS_VERSION_MONTH``, ``MAGNUMBINDINGS_VERSION_COMMIT``,
``MAGNUMBINDINGS_VERSION_HASH`` and ``MAGNUMBINDINGS_VERSION_STRING``
preprocessor defines in a new ``Magnum/versionBindings.h`` header. This
header is not included by any other header to avoid trigerring a full
rebuild when Git commit changes. If Git is not found, only the first two
defines are present.
`2019.10`_
==========
Released 2019-10-24, tagged as
:gh:`v2019.10 <mosra/magnum-bindings/releases/tag/v2019.10>`.
Initial version. See :gh:`mosra/magnum#228`, :gh:`mosra/magnum-bindings#1`,
:gh:`mosra/magnum-bindings#2` and :gh:`mosra/magnum-bindings#6` for more
information.

81
doc/python/pages/credits.rst

@ -1,81 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
Credits
#######
:ref-prefix:
corrade
magnum
:summary: Third-party dependencies and their corresponding license information;
people and organizations that contributed to Magnum Python Bindings.
`Third-party components`_
=========================
.. TODO: ffs doxygen SORT YOUR SHIT OUT, why can't I link to
credits-third-party?!
.. role:: doxygen-you-fool(link)
:class: m-doc-external
While Magnum Python Bindings themselves don't depend on much, a lot of
third-party components is used transitively from the Magnum C++ implementation.
Please see the :ref:`main page <std:doc:index#license>` for license of Magnum
Python Bindings themselves and the
:doxygen-you-fool:`Third-party components <https://doc.magnum.graphics/magnum/credits-third-party.html>`
page of C++ docs for a detailed overview of all used components. The list below
uses the same color-coding scheme for easier overview:
:ref:`Magnum Python Bindings <std:doc:index>`
Bindings generated with :gh:`pybind11 <pybind/pybind11>`, released under a
:label-success:`BSD-style license`
(`license text <https://github.com/pybind/pybind11/blob/master/LICENSE>`_,
`choosealicense.com <https://choosealicense.com/licenses/bsd-3-clause/>`_).
It requires attribution for public use.
`Contributors`_
===============
Listing only people with code contributions or other significant work, because
otherwise there's too many :) There's also a
:dox:`similar list for Corrade <corrade-credits-contributors>` and
:dox:`Magnum <credits-contributors>` themselves. Big thanks to everyone
involved!
.. class:: m-text-center m-text m-dim
Are the below lists missing your name or something's wrong?
`Let us know! <https://magnum.graphics/contact/>`_
- **Aaron Gokaslan** (:gh:`Skylion007`) --- minor performance and
documentation fixes, expanding :ref:`Color3` / :ref:`Color4` bindings
- **Cameron Egbert** (:gh:`cegbertOculus`) --- initial Windows port
- **James Murphy** (:gh:`mCodingLLC`) --- buildsystem fixes, expanding
:ref:`gl.Framebuffer` bindings
- **John Laxson** (:gh:`jlaxson`) --- Homebrew package improvements
- **Stanislaw Halik** (:gh:`sthalik`) --- build fixes
- **Vladimir Gamalyan** (:gh:`vladimirgamalyan`) --- expanding
:ref:`gl.Renderer` bindings

80
doc/python/pages/developers.rst

@ -1,80 +0,0 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
Developers Guide
################
:ref-prefix:
corrade
magnum
:summary: Checklists for developing new things in Magnum Python bindings
themselves.
.. role:: cmake(code)
:language: cmake
.. role:: cpp(code)
:language: c++
.. role:: py(code)
:language: py
`Checklist for adding / removing bindings for a library`_
=========================================================
1. Add a corresponding ``Foo`` Magnum dependency to the :cmake:`find_package()`
call in ``src/python/magnum/CMakeLists.txt``, create a ``magnum_foo_SRCS``
variable with its source file(s).
2. Add a :cmake:`if(Magnum_Foo_FOUND)` branch to the
:cmake:`if(NOT MAGNUM_BUILD_STATIC)` condition, adding a new ``magnum_foo``
module from ``magnum_foo_SRCS``, linking to ``Magnum::Foo`` and setting
``OUTPUT_NAME`` to ``foo``.
3. Add a :cmake:`if(Magnum_Foo_FOUND)` branch to the :cmake:`else()`
condition, ``APPEND``\ ing ``magnum_foo_SRCS`` to ``magnum_SRCS`` and
``Magnum::Foo`` to ``magnum_LIBS``.
4. Add :cpp:`void foo(py::module_& m);` forward declaration to
``magnum/bootstrap.h``, and :cpp:`#cmakdefeine Magnum_Foo_FOUND` to
``magnum/staticconfigure.h.cmake``.
5. Implement ``void foo(py::module_& m)`` in ``src/python/magnum/foo.cpp``,
add a :cpp:`PYBIND11_MODULE()` calling it.
6. Add :cpp:`m.def_submodule("foo");` and a call to :cpp:`magnum:foo()`
wrapped in :cpp:`#ifdef Magnum_Foo_FOUND` to the
:cpp:`#ifdef MAGNUM_BUILD_STATIC` section of :cpp:`PYBIND11_MODULE()` in
``magnum/magnum.cpp``.
7. Add the new module name to the list in ``magnum/__init__.py``.
8. Add a line with ``magnum_foo`` to the :cmake:`foreach()` in
``src/python/CMakeLists.txt``, and then a corresponding :py:`'magnum.foo'`
entry in ``src/python/setup.py.cmake``
9. Add a ``magnum/test/test_foo.py`` test file, and potentially also
``magnum/test/test_foo_gl.py`` where is
:py:`from . import GLTestCase, setUpModule` to skip the test if GL context
doesn't exist, and the test cases derive from :py:`GLTestCase` instead of
:py:`unittest.TestCase`.
10. Add the new module into the :py:`magnum.__all__` list in
``doc/python/conf.py``.
11. Add a ``doc/python/magnum.foo.rst`` documentation file for more detailed
docs, if needed, and reference it from ``INPUT_DOCS``.
12. Add a ``doc/python/pages/changelog.rst`` entry.
For Corrade bindings it's similar.

21
doc/python/pages/index.rst

@ -1,8 +1,7 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -43,11 +42,11 @@ the C++ docs --- highlighting important differences and describing general
conventions, but referring to documentation of underlying C++ APIs for all
details.
See the :ref:`building docs <std:doc:building>` for an installation guide,
:ref:`API convention documentation <std:doc:api-conventions>` and
:ref:`documentation of each module <std:special:modules>` for more information about
the actual usage. There are also :ref:`examples <std:doc:examples>` to give you
an idea about how the API feels.
See the :link-ref:`building docs <building.html>` for an installation guide,
:link-ref:`API convention documentation <api-conventions.html>` and
:link-ref:`documentation of each module <modules.html>` for more information
about the actual usage. There are also :link-ref:`examples <examples.html>` to
give you an idea about how the API feels.
`Contact & support`_
====================
@ -65,7 +64,8 @@ right away!
- E-mail --- info@magnum.graphics
- Google Groups mailing list --- magnum-engine@googlegroups.com
(`archive <https://groups.google.com/forum/#!forum/magnum-engine>`_)
- Bluesky --- https://bsky.app/profile/mosra.cz
- Twitter --- https://twitter.com/czmosra and the
`#MagnumEngine <https://twitter.com/hashtag/MagnumEngine>`_ hashtag
See also the `Contact & Support page <https://magnum.graphics/contact/>`_ on
the project website for further information.
@ -75,9 +75,8 @@ the project website for further information.
Magnum, including the Python bindings, is licensed under the MIT/Expat license:
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026 Vladimír Vondruš
<mosra@centrum.cz> and contributors
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz> and contributors
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

BIN
doc/python/python.inv

Binary file not shown.

16
modules/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -28,17 +27,4 @@ set(MagnumBindings_MODULES
FindMagnumBindings.cmake
MagnumBindingsConfig.cmake)
# IMPORTANT: When adding a new module here, be sure to update the
# find_path(_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR ...) list in
# FindMagnumBindings.cmake to avoid breakages when the directory contains only
# that new module.
set(MagnumBindings_DEPENDENCY_MODULES )
# No dependency Find modules so far
install(FILES ${MagnumBindings_MODULES} DESTINATION ${MAGNUMBINDINGS_CMAKE_MODULE_INSTALL_DIR})
if(MagnumBindings_DEPENDENCY_MODULES)
install(FILES ${MagnumBindings_DEPENDENCY_MODULES} DESTINATION ${MAGNUMBINDINGS_CMAKE_MODULE_INSTALL_DIR}/dependencies)
endif()
# Magnum Bindings dependency module dir for superprojects
set(_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")

520
modules/FindCorrade.cmake

@ -11,13 +11,14 @@
#
# Corrade_FOUND - Whether the base library was found
# CORRADE_LIB_SUFFIX_MODULE - Path to CorradeLibSuffix.cmake module
# CORRADE_INCLUDE_INSTALL_PREFIX - Prefix where to put platform-independent
# include and other files, defaults to ``.``. If a relative path is used,
# it's relative to :variable:`CMAKE_INSTALL_PREFIX`.
#
# This command will try to find only the base library, not the optional
# components, which are:
#
# Containers - Containers library
# Interconnect - Interconnect library
# Main - Main library
# PluginManager - PluginManager library
# TestSuite - TestSuite library
# Utility - Utility library
@ -64,25 +65,19 @@
#
# Features of found Corrade library are exposed in these variables:
#
# CORRADE_MSVC_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2019+ without the /permissive- flag set
# CORRADE_MSVC2019_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2019
# CORRADE_MSVC2017_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2017
# CORRADE_MSVC2015_COMPATIBILITY - Defined if compiled with compatibility
# mode for MSVC 2015
# CORRADE_BUILD_DEPRECATED - Defined if compiled with deprecated features
# CORRADE_BUILD_DEPRECATED - Defined if compiled with deprecated APIs
# included
# CORRADE_BUILD_STATIC - Defined if compiled as static libraries.
# Default are shared libraries.
# CORRADE_BUILD_STATIC_UNIQUE_GLOBALS - Defined if static libraries keep their
# globals unique even across different shared libraries. Enabled by default
# for static builds.
# CORRADE_BUILD_MULTITHREADED - Defined if compiled in a way that makes it
# possible to safely use certain Corrade features simultaneously in multiple
# possible to safely use certain Corrade features simultaenously in multiple
# threads
# CORRADE_BUILD_CPU_RUNTIME_DISPATCH - Defined if built with code paths
# optimized for multiple architectres with the best matching variant selected
# at runtime based on detected CPU features
# CORRADE_TARGET_UNIX - Defined if compiled for some Unix flavor
# (Linux, BSD, macOS)
# CORRADE_TARGET_APPLE - Defined if compiled for Apple platforms
@ -93,21 +88,9 @@
# CORRADE_TARGET_WINDOWS_RT - Defined if compiled for Windows RT
# CORRADE_TARGET_EMSCRIPTEN - Defined if compiled for Emscripten
# CORRADE_TARGET_ANDROID - Defined if compiled for Android
# CORRADE_TARGET_GCC - Defined if compiling with GCC or GCC-
# compatible Clang
# CORRADE_TARGET_CLANG - Defined if compiling with Clang or any of its
# variants
# CORRADE_TARGET_APPLE_CLANG - Defined if compiling with Apple's Clang
# CORRADE_TARGET_CLANG_CL - Defined if compiling with Clang-CL (Clang
# with a MSVC frontend)
# CORRADE_TARGET_MSVC - Defined if compiling with MSVC or Clang with
# a MSVC frontend
# CORRADE_TARGET_MINGW - Defined if compiling under MinGW
# CORRADE_CPU_USE_IFUNC - Defined if GNU IFUNC is allowed to be used
# for runtime dispatch in the Cpu library
# CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT - Defined if PluginManager
# doesn't support dynamic plugin loading due to platform limitations
# CORRADE_TESTSUITE_TARGET_XCTEST - Defined if TestSuite is targeting Xcode
# CORRADE_TESTSUITE_TARGET_XCTEST - Defined if TestSuite is targetting Xcode
# XCTest
# CORRADE_UTILITY_USE_ANSI_COLORS - Defined if ANSI escape sequences are used
# for colored output with Utility::Debug on Windows
@ -118,25 +101,24 @@
# CORRADE_*_LIBRARY_DEBUG - Debug version of given library, if found
# CORRADE_*_LIBRARY_RELEASE - Release version of given library, if found
# CORRADE_*_EXECUTABLE - Location of given executable, if found
# CORRADE_*_EXECUTABLE_EMULATOR - Emulator to run CORRADE_*_EXECUTABLE, if a
# non-native version was found when cross-compiling
# CORRADE_USE_MODULE - Path to UseCorrade.cmake module (included
# automatically)
# CORRADE_DEPENDENCY_MODULE_DIR - Path to Find modules for dependencies used
# internally by Corrade. Defined only if any such modules are expected to
# exist on given platform.
# CORRADE_TESTSUITE_XCTEST_RUNNER - Path to XCTestRunner.mm.in file
# CORRADE_TESTSUITE_ADB_RUNNER - Path to AdbRunner.sh file
# CORRADE_UTILITY_JS - Path to CorradeUtility.js file
# CORRADE_PEDANTIC_COMPILER_OPTIONS - List of pedantic compiler options used
# for targets with :prop_tgt:`CORRADE_USE_PEDANTIC_FLAGS` enabled
# CORRADE_PEDANTIC_COMPILER_DEFINITIONS - List of pedantic compiler
# definitions used for targets with :prop_tgt:`CORRADE_USE_PEDANTIC_FLAGS`
# enabled
# CORRADE_CXX{11,14,17,20}_STANDARD_FLAG - Compiler flag to use for targeting
# C++11, 14, 17 or 20 in cases where it's not possible to use
# :prop_tgt:`CORRADE_CXX_STANDARD`. Not defined if a standard switch is
# already present in :variable:`CMAKE_CXX_FLAGS`.
#
# Workflows without :prop_tgt:`IMPORTED` targets are deprecated and the
# following variables are included just for backwards compatibility and only if
# :variable:`CORRADE_BUILD_DEPRECATED` is enabled:
#
# CORRADE_CXX_FLAGS - Pedantic compile flags. Use
# :prop_tgt:`CORRADE_USE_PEDANTIC_FLAGS` property or
# :variable:`CORRADE_PEDANTIC_COMPILER_DEFINITIONS` /
# :variable:`CORRADE_PEDANTIC_COMPILER_OPTIONS` list variables instead.
#
# Corrade provides these macros and functions:
#
@ -201,19 +183,13 @@
# <metadata file>
# <sources>...)
#
# The macro adds a preprocessor directive ``CORRADE_DYNAMIC_PLUGIN`` when
# compiling ``<sources>``. Additional libraries can be linked in via
# :command:`target_link_libraries(plugin_name ...) <target_link_libraries>`.
# The macro adds preprocessor directive ``CORRADE_DYNAMIC_PLUGIN``. Additional
# libraries can be linked in via :command:`target_link_libraries(plugin_name ...) <target_link_libraries>`.
# On DLL platforms, the plugin DLLs and metadata files are put into
# ``<debug binary install dir>`` / ``<release binary install dir>`` and the
# ``*.lib`` files into ``<debug library install dir>`` /
# ``<release library install dir>``. On non-DLL platforms everything is put
# into ``<debug library install dir>`` / ``<release library install dir>``.
#
# If the plugin interface disables plugin metadata files, the
# ``<metadata file>`` can be set to ``""``, in which case no metadata file is
# copied anywhere. Otherwise the metadata file is copied and renamed to
# ``<plugin name>``, retaining its original extension.
# ``<debug binary install dir>``/``<release binary install dir>`` and the
# ``*.lib`` files into ``<debug library install dir>``/``<release library install dir>``.
# On non-DLL platforms everything is put into ``<debug library install dir>``/
# ``<release library install dir>``.
#
# corrade_add_plugin(<plugin name>
# <debug install dir>
@ -221,7 +197,7 @@
# <metadata file>
# <sources>...)
#
# Unlike the above version this puts everything into ``<debug install dir>`` on
# Unline the above version this puts everything into ``<debug install dir>`` on
# both DLL and non-DLL platforms. If ``<debug install dir>`` is set to
# :variable:`CMAKE_CURRENT_BINARY_DIR` (e.g. for testing purposes), the files
# are copied directly, without the need to perform install step. Note that the
@ -238,9 +214,8 @@
# <metadata file>
# <sources>...)
#
# The macro adds a preprocessor directive ``CORRADE_STATIC_PLUGIN`` when
# compiling ``<sources>``. Additional libraries can be linked in via
# :command:`target_link_libraries(plugin_name ...) <target_link_libraries>`.
# The macro adds preprocessor directive ``CORRADE_STATIC_PLUGIN``. Additional
# libraries can be linked in via :command:`target_link_libraries(plugin_name ...) <target_link_libraries>`.
# The ``<binary install dir>`` is ignored and included just for compatibility
# with the :command:`corrade_add_plugin` command, everything is installed into
# ``<library install dir>``. Note that plugins built in debug configuration
@ -248,11 +223,6 @@
# suffix to make it possible to have both debug and release plugins installed
# alongside each other.
#
# If the plugin interface disables plugin metadata files, the
# ``<metadata file>`` can be set to ``""``, in which case no metadata file is
# used. Otherwise the metadata file is bundled and renamed to
# ``<plugin name>``, retaining its original extension.
#
# corrade_add_static_plugin(<plugin name>
# <install dir>
# <metadata file>
@ -277,8 +247,7 @@
# This file is part of Corrade.
#
# Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
# 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
# 2017, 2018, 2019 Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@ -320,17 +289,16 @@ endif()
# Read flags from configuration
file(READ ${_CORRADE_CONFIGURE_FILE} _corradeConfigure)
string(REGEX REPLACE ";" "\\\\;" _corradeConfigure "${_corradeConfigure}")
string(REGEX REPLACE "\n" ";" _corradeConfigure "${_corradeConfigure}")
set(_corradeFlags
# WARNING: CAREFUL HERE, the string(FIND) succeeds even if a subset is
# found -- so e.g. looking for TARGET_GL will match TARGET_GLES2 as well.
# So far that's not a problem, but might become an issue for new flags.
MSVC2015_COMPATIBILITY
MSVC2017_COMPATIBILITY
MSVC_COMPATIBILITY
MSVC2019_COMPATIBILITY
BUILD_DEPRECATED
BUILD_STATIC
BUILD_STATIC_UNIQUE_GLOBALS
BUILD_MULTITHREADED
BUILD_CPU_RUNTIME_DISPATCH
TARGET_UNIX
TARGET_APPLE
TARGET_IOS
@ -339,17 +307,11 @@ set(_corradeFlags
TARGET_WINDOWS_RT
TARGET_EMSCRIPTEN
TARGET_ANDROID
# TARGET_X86 etc, TARGET_32BIT, TARGET_BIG_ENDIAN and TARGET_LIBCXX etc.
# are not exposed to CMake as the meaning is unclear on platforms with
# multi-arch binaries or when mixing different STL implementations.
# TARGET_GCC etc are figured out via UseCorrade.cmake, as the compiler can
# be different when compiling the lib & when using it.
CPU_USE_IFUNC
PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
TESTSUITE_TARGET_XCTEST
UTILITY_USE_ANSI_COLORS)
foreach(_corradeFlag ${_corradeFlags})
list(FIND _corradeConfigure "#define CORRADE_${_corradeFlag}" _corrade_${_corradeFlag})
string(FIND "${_corradeConfigure}" "#define CORRADE_${_corradeFlag}" _corrade_${_corradeFlag})
if(NOT _corrade_${_corradeFlag} EQUAL -1)
set(CORRADE_${_corradeFlag} 1)
endif()
@ -360,60 +322,44 @@ find_path(_CORRADE_MODULE_DIR
NAMES UseCorrade.cmake CorradeLibSuffix.cmake
PATH_SUFFIXES share/cmake/Corrade)
mark_as_advanced(_CORRADE_MODULE_DIR)
if(CORRADE_TARGET_EMSCRIPTEN)
find_path(CORRADE_DEPENDENCY_MODULE_DIR
NAMES FindNodeJs.cmake
PATH_SUFFIXES share/cmake/Corrade/dependencies)
mark_as_advanced(CORRADE_DEPENDENCY_MODULE_DIR)
endif()
set(CORRADE_USE_MODULE ${_CORRADE_MODULE_DIR}/UseCorrade.cmake)
set(CORRADE_LIB_SUFFIX_MODULE ${_CORRADE_MODULE_DIR}/CorradeLibSuffix.cmake)
# Component distinction (listing them explicitly to avoid mistakes with finding
# unknown components)
set(_CORRADE_LIBRARY_COMPONENTS
Containers Interconnect Main PluginManager TestSuite Utility)
# These libraries are excluded from DLL detection if Corrade is built as shared
set(_CORRADE_LIBRARY_COMPONENTS_ALWAYS_STATIC
Main)
set(_CORRADE_HEADER_ONLY_COMPONENTS Containers)
if(NOT CORRADE_TARGET_WINDOWS)
# CorradeMain is a real library only on windows, a dummy target elsewhere
list(APPEND _CORRADE_HEADER_ONLY_COMPONENTS Main)
endif()
set(_CORRADE_EXECUTABLE_COMPONENTS rc)
# Currently everything is enabled implicitly. Keep in sync with Corrade's root
# CMakeLists.txt.
set(_CORRADE_IMPLICITLY_ENABLED_COMPONENTS
Containers Interconnect Main PluginManager TestSuite Utility rc)
# Inter-component dependencies
set(_CORRADE_Containers_DEPENDENCIES Utility)
set(_CORRADE_Interconnect_DEPENDENCIES Containers Utility)
set(_CORRADE_PluginManager_DEPENDENCIES Containers Utility rc)
set(_CORRADE_TestSuite_DEPENDENCIES Containers Utility Main) # see below
set(_CORRADE_Utility_DEPENDENCIES Containers rc)
# Ensure that all inter-component dependencies are specified as well
foreach(_component ${Corrade_FIND_COMPONENTS})
string(TOUPPER ${_component} _COMPONENT)
if(_component STREQUAL Containers)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Utility)
elseif(_component STREQUAL Interconnect)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Utility)
elseif(_component STREQUAL PluginManager)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Containers Utility rc)
elseif(_component STREQUAL TestSuite)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Utility Main) # see below
elseif(_component STREQUAL Utility)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Containers rc)
endif()
# Mark the dependencies as required if the component is also required
if(Corrade_FIND_REQUIRED_${_component})
foreach(_dependency ${_CORRADE_${_component}_DEPENDENCIES})
foreach(_dependency ${_CORRADE_${_COMPONENT}_DEPENDENCIES})
set(Corrade_FIND_REQUIRED_${_dependency} TRUE)
endforeach()
endif()
list(APPEND _CORRADE_ADDITIONAL_COMPONENTS ${_CORRADE_${_component}_DEPENDENCIES})
endforeach()
list(APPEND _CORRADE_ADDITIONAL_COMPONENTS ${_CORRADE_${_COMPONENT}_DEPENDENCIES})
# Main is linked only in corrade_add_test(), not to everything that depends on
# TestSuite, so remove it from the list again once we filled the above
# variables
set(_CORRADE_TestSuite_DEPENDENCIES Containers Utility)
# Main is linked only in corrade_add_test(), not to everything that depends
# on TestSuite, so remove it from the list again once we filled the above
# variables
if(_component STREQUAL TestSuite)
set(_CORRADE_${_COMPONENT}_DEPENDENCIES Utility)
endif()
endforeach()
# Join the lists, remove duplicate components
set(_CORRADE_ORIGINAL_FIND_COMPONENTS ${Corrade_FIND_COMPONENTS})
if(_CORRADE_ADDITIONAL_COMPONENTS)
list(INSERT Corrade_FIND_COMPONENTS 0 ${_CORRADE_ADDITIONAL_COMPONENTS})
endif()
@ -421,10 +367,15 @@ if(Corrade_FIND_COMPONENTS)
list(REMOVE_DUPLICATES Corrade_FIND_COMPONENTS)
endif()
# Special cases of include paths. Libraries not listed here have a path suffix
# and include name derived from the library name in the loop below.
set(_CORRADE_MAIN_INCLUDE_PATH_SUFFIX Corrade)
set(_CORRADE_MAIN_INCLUDE_PATH_NAMES Corrade.h)
# Component distinction
set(_CORRADE_LIBRARY_COMPONENTS "^(Containers|Interconnect|Main|PluginManager|TestSuite|Utility)$")
if(CORRADE_TARGET_WINDOWS)
# CorradeMain is a real library only on windows, a dummy target elsewhere
set(_CORRADE_HEADER_ONLY_COMPONENTS "^(Containers)$")
else()
set(_CORRADE_HEADER_ONLY_COMPONENTS "^(Containers|Main)$")
endif()
set(_CORRADE_EXECUTABLE_COMPONENTS "^(rc)$")
# Find all components
foreach(_component ${Corrade_FIND_COMPONENTS})
@ -433,180 +384,57 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
# Create imported target in case the library is found. If the project is
# added as subproject to CMake, the target already exists and all the
# required setup is already done from the build tree.
if(TARGET "Corrade::${_component}") # Quotes to "fix" KDE's higlighter
if(TARGET Corrade::${_component})
set(Corrade_${_component}_FOUND TRUE)
else()
# Default include path names to look for for library / header-only
# components, unless set above already
if(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS)
if(NOT _CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX)
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX Corrade/${_component})
endif()
if(NOT _CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES)
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES ${_component}.h)
endif()
endif()
# The Main library consists of two libraries on MinGW to be able to
# handle both console and windows apps, special-case it before any
# other libraries. The CORRADE_MAIN{CONSOLE,WINDOWS}_LIBRARY_<CONFIG>
# variables then get subsequently used below.
if(MINGW AND _component STREQUAL Main)
foreach(_mainComponent Console Windows)
string(TOUPPER ${_mainComponent} _MAIN_COMPONENT)
find_library(CORRADE_MAIN${_MAIN_COMPONENT}_LIBRARY_DEBUG CorradeMain${_mainComponent}-d)
find_library(CORRADE_MAIN${_MAIN_COMPONENT}_LIBRARY_RELEASE CorradeMain${_mainComponent})
mark_as_advanced(CORRADE_MAIN${_MAIN_COMPONENT}_LIBRARY_DEBUG
CORRADE_MAIN${_MAIN_COMPONENT}_LIBRARY_RELEASE)
endforeach()
# Library (and not header-only) components
elseif(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS AND NOT _component IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS)
if(_component MATCHES ${_CORRADE_LIBRARY_COMPONENTS} AND NOT _component MATCHES ${_CORRADE_HEADER_ONLY_COMPONENTS})
add_library(Corrade::${_component} UNKNOWN IMPORTED)
# Try to find both debug and release version
find_library(CORRADE_${_COMPONENT}_LIBRARY_DEBUG Corrade${_component}-d)
find_library(CORRADE_${_COMPONENT}_LIBRARY_RELEASE Corrade${_component})
mark_as_advanced(CORRADE_${_COMPONENT}_LIBRARY_DEBUG
CORRADE_${_COMPONENT}_LIBRARY_RELEASE)
# On Windows, if we have a dynamic build of given library, find the
# DLLs as well. Abuse find_program() since the DLLs should be
# alongside usual executables. On MinGW they however have a lib
# prefix.
if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_BUILD_STATIC AND NOT _component IN_LIST _CORRADE_LIBRARY_COMPONENTS_ALWAYS_STATIC)
find_program(CORRADE_${_COMPONENT}_DLL_DEBUG ${CMAKE_SHARED_LIBRARY_PREFIX}Corrade${_component}-d.dll)
find_program(CORRADE_${_COMPONENT}_DLL_RELEASE ${CMAKE_SHARED_LIBRARY_PREFIX}Corrade${_component}.dll)
mark_as_advanced(CORRADE_${_COMPONENT}_DLL_DEBUG
CORRADE_${_COMPONENT}_DLL_RELEASE)
# If not on Windows or on a static build, unset the DLL variables
# to avoid leaks when switching shared and static builds
else()
unset(CORRADE_${_COMPONENT}_DLL_DEBUG CACHE)
unset(CORRADE_${_COMPONENT}_DLL_RELEASE CACHE)
if(CORRADE_${_COMPONENT}_LIBRARY_RELEASE)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_property(TARGET Corrade::${_component} PROPERTY
IMPORTED_LOCATION_RELEASE ${CORRADE_${_COMPONENT}_LIBRARY_RELEASE})
endif()
# Executable components
elseif(_component IN_LIST _CORRADE_EXECUTABLE_COMPONENTS)
find_program(CORRADE_${_COMPONENT}_EXECUTABLE corrade-${_component})
mark_as_advanced(CORRADE_${_COMPONENT}_EXECUTABLE)
# If the executable wasn't found, we're cross-compiling, an
# emulator is set and we're on CMake 3.6+ that actually uses
# CMAKE_CROSSCOMPILING_EMULATOR in add_custom_command((), try to
# find the cross-compiled version as a (slower) fallback. This
# assumes the toolchain sets CMAKE_FIND_ROOT_PATH_MODE_PROGRAM to
# NEVER, i.e. that the search is restricted to native executables
# by default.
if(NOT CORRADE_${_COMPONENT}_EXECUTABLE AND CMAKE_CROSSCOMPILING AND CMAKE_CROSSCOMPILING_EMULATOR AND NOT CMAKE_VERSION VERSION_LESS 3.6)
# Additionally, there are no CMAKE_FIND_PROGRAM_SUFFIXES akin
# to CMAKE_FIND_LIBRARY_SUFFIXES for libraries, so we have to
# try manually.
if(CORRADE_TARGET_EMSCRIPTEN)
set(_CORRADE_PROGRAM_EXTENSION .js)
endif()
find_program(CORRADE_${_COMPONENT}_EXECUTABLE
NAMES
corrade-${_component}
corrade-${_component}${_CORRADE_PROGRAM_EXTENSION}
ONLY_CMAKE_FIND_ROOT_PATH)
if(CORRADE_${_COMPONENT}_EXECUTABLE)
set(CORRADE_${_COMPONENT}_EXECUTABLE_EMULATOR ${CMAKE_CROSSCOMPILING_EMULATOR} CACHE PATH "Emulator for running a cross-compiled corrade-${_component} executable")
mark_as_advanced(CORRADE_${_COMPONENT}_EXECUTABLE_EMULATOR)
endif()
if(CORRADE_${_COMPONENT}_LIBRARY_DEBUG)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_property(TARGET Corrade::${_component} PROPERTY
IMPORTED_LOCATION_DEBUG ${CORRADE_${_COMPONENT}_LIBRARY_DEBUG})
endif()
# If not a header-only component it's something unknown, skip. FPHSA
# will take care of handling this below.
elseif(NOT _component IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS)
continue()
endif()
# Find library includes
if(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS)
find_path(_CORRADE_${_COMPONENT}_INCLUDE_DIR
NAMES ${_CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES}
HINTS ${CORRADE_INCLUDE_DIR}/${_CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX})
mark_as_advanced(_CORRADE_${_COMPONENT}_INCLUDE_DIR)
# Header-only library components
if(_component MATCHES ${_CORRADE_HEADER_ONLY_COMPONENTS})
add_library(Corrade::${_component} INTERFACE IMPORTED)
endif()
# Decide if the component was found. If not, skip the rest, which
# creates and populates the target and finds additional dependencies.
# If found, the _FOUND variable may still get reset by something below.
#
# The Main library consists of two libraries on MinGW to be able to
# handle both console and windows apps. See
# src/Corrade/CMakeLists.txt for a lengthy explanation. On non-MinGW
# it's handled as a regular library or a header-only library.
if(MINGW AND _component STREQUAL Main)
if((CORRADE_MAINCONSOLE_LIBRARY_DEBUG AND CORRADE_MAINWINDOWS_LIBRARY_DEBUG) OR (CORRADE_MAINCONSOLE_LIBRARY_RELEASE AND CORRADE_MAINWINDOWS_LIBRARY_RELEASE))
set(Corrade_Main_FOUND TRUE)
else()
set(Corrade_Main_FOUND FALSE)
continue()
endif()
elseif(
# If the component is a library, it should have the include dir
(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS AND _CORRADE_${_COMPONENT}_INCLUDE_DIR AND (
# And it should be either header-only
_component IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS OR
# Or have a debug library, and a DLL found if expected
(CORRADE_${_COMPONENT}_LIBRARY_DEBUG AND (
NOT DEFINED CORRADE_${_COMPONENT}_DLL_DEBUG OR
CORRADE_${_COMPONENT}_DLL_DEBUG)) OR
# Or have a release library, and a DLL found if expected
(CORRADE_${_COMPONENT}_LIBRARY_RELEASE AND (
NOT DEFINED CORRADE_${_COMPONENT}_DLL_RELEASE OR
CORRADE_${_COMPONENT}_DLL_RELEASE)))) OR
# If the component is an executable, it should have just the
# location
(_component IN_LIST _CORRADE_EXECUTABLE_COMPONENTS AND CORRADE_${_COMPONENT}_EXECUTABLE)
)
set(Corrade_${_component}_FOUND TRUE)
else()
set(Corrade_${_component}_FOUND FALSE)
continue()
# Default include path names to look for for library / header-only
# components
if(_component MATCHES ${_CORRADE_LIBRARY_COMPONENTS})
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX Corrade/${_component})
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES ${_component}.h)
endif()
# Target for header-only library components. The Main library consists
# of two libraries on MinGW to be able to handle both console and
# windows apps, so there the target is INTERFACE as well, and is filled
# with INTERFACE_LINK_LIBRARIES later below.
if(_component IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS OR (MINGW AND _component STREQUAL Main))
add_library(Corrade::${_component} INTERFACE IMPORTED)
# Target and location for (non-header-only) libraries
elseif(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS)
if(CORRADE_BUILD_STATIC OR _component IN_LIST _CORRADE_LIBRARY_COMPONENTS_ALWAYS_STATIC)
add_library(Corrade::${_component} STATIC IMPORTED)
else()
add_library(Corrade::${_component} SHARED IMPORTED)
endif()
foreach(_CONFIG DEBUG RELEASE)
if(NOT CORRADE_${_COMPONENT}_LIBRARY_${_CONFIG})
continue()
endif()
set_property(TARGET Corrade::${_component} APPEND PROPERTY
IMPORTED_CONFIGURATIONS ${_CONFIG})
# Unfortunately for a DLL the two properties are swapped out,
# *.lib goes to IMPLIB, so it's duplicated like this
if(DEFINED CORRADE_${_COMPONENT}_DLL_${_CONFIG})
# Quotes to "fix" KDE's higlighter
set_target_properties("Corrade::${_component}" PROPERTIES
IMPORTED_LOCATION_${_CONFIG} ${CORRADE_${_COMPONENT}_DLL_${_CONFIG}}
IMPORTED_IMPLIB_${_CONFIG} ${CORRADE_${_COMPONENT}_LIBRARY_${_CONFIG}})
else()
set_property(TARGET Corrade::${_component} PROPERTY
IMPORTED_LOCATION_${_CONFIG} ${CORRADE_${_COMPONENT}_LIBRARY_${_CONFIG}})
endif()
endforeach()
# Target and location for executable components
elseif(_component IN_LIST _CORRADE_EXECUTABLE_COMPONENTS)
# Executable components
if(_component MATCHES ${_CORRADE_EXECUTABLE_COMPONENTS})
add_executable(Corrade::${_component} IMPORTED)
set_property(TARGET Corrade::${_component} PROPERTY
IMPORTED_LOCATION ${CORRADE_${_COMPONENT}_EXECUTABLE})
find_program(CORRADE_${_COMPONENT}_EXECUTABLE corrade-${_component})
mark_as_advanced(CORRADE_${_COMPONENT}_EXECUTABLE)
if(CORRADE_${_COMPONENT}_EXECUTABLE)
set_property(TARGET Corrade::${_component} PROPERTY
IMPORTED_LOCATION ${CORRADE_${_COMPONENT}_EXECUTABLE})
endif()
endif()
# No special setup for Containers library
@ -614,9 +442,8 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
# Interconnect library
if(_component STREQUAL Interconnect)
# Disable /OPT:ICF on MSVC, which merges functions with identical
# contents and thus breaks signal comparison. Same case is for
# clang-cl which uses the MSVC linker by default.
if(CORRADE_TARGET_WINDOWS AND (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
# contents and thus breaks signal comparison
if(CORRADE_TARGET_WINDOWS AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(CMAKE_VERSION VERSION_LESS 3.13)
set_property(TARGET Corrade::${_component} PROPERTY
INTERFACE_LINK_LIBRARIES "-OPT:NOICF,REF")
@ -628,40 +455,11 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
# Main library
elseif(_component STREQUAL Main)
# On non-Windows platforms Main is a no-op interface target
if(CORRADE_TARGET_WINDOWS)
# On MinGW the library consists of two libraries, for which we
# need to add two extra targets to delegate to. See
# src/Corrade/CMakeLists.txt for a lengthy explanation.
if(MINGW)
foreach(_mainComponent Console Windows)
string(TOUPPER ${_mainComponent} _MAINCOMPONENT)
# Similarly as with _CORRADE_LIBRARY_COMPONENTS above,
# just specialized for the Main library (and without
# DLL handling, as the library is always static)
add_library(Corrade::Main${_mainComponent} STATIC IMPORTED)
foreach(_CONFIG DEBUG RELEASE)
if(NOT CORRADE_MAIN${_MAINCOMPONENT}_LIBRARY_${_CONFIG})
continue()
endif()
set_property(TARGET Corrade::Main${_mainComponent} APPEND PROPERTY
IMPORTED_CONFIGURATIONS ${_CONFIG})
set_property(TARGET Corrade::Main${_mainComponent} PROPERTY
IMPORTED_LOCATION_${_CONFIG} ${CORRADE_MAIN${_MAINCOMPONENT}_LIBRARY_${_CONFIG}})
endforeach()
endforeach()
# See src/Corrade/CMakeLists.txt for why -lmingw32 has to
# be linked this way
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES "-municode;$<$<NOT:$<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>>:Corrade::MainConsole>$<$<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>:-lmingw32;Corrade::MainWindows>")
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX Corrade)
set(_CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES Corrade.h)
# On MSVC and clang-cl it's simple, there's just a single
# library that was already added above. Add just the /ENTRY
# flag.
else()
if(CORRADE_TARGET_WINDOWS)
if(NOT MINGW)
# Abusing INTERFACE_LINK_LIBRARIES because
# INTERFACE_LINK_OPTIONS is only since 3.13. They treat
# things with `-` in front as linker flags and fortunately
@ -669,40 +467,39 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
# https://gitlab.kitware.com/cmake/cmake/issues/16543
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES "-ENTRY:$<$<NOT:$<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>>:wmainCRTStartup>$<$<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>:wWinMainCRTStartup>")
else()
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES "-municode")
endif()
endif()
# PluginManager library
elseif(_component STREQUAL PluginManager)
# -ldl is handled by Utility now
# At least static build needs this
if(CORRADE_TARGET_UNIX)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
endif()
# TestSuite library has some additional files. If those are not found,
# set the component _FOUND variable to false so it works properly both
# when the component is required and when it's optional.
# TestSuite library has some additional files
elseif(_component STREQUAL TestSuite)
# XCTest runner file
if(CORRADE_TESTSUITE_TARGET_XCTEST)
find_file(CORRADE_TESTSUITE_XCTEST_RUNNER XCTestRunner.mm.in
PATH_SUFFIXES share/corrade/TestSuite)
if(NOT CORRADE_TESTSUITE_XCTEST_RUNNER)
set(Corrade_${_component}_FOUND FALSE)
endif()
set(CORRADE_TESTSUITE_XCTEST_RUNNER_NEEDED CORRADE_TESTSUITE_XCTEST_RUNNER)
# ADB runner file
elseif(CORRADE_TARGET_ANDROID)
find_file(CORRADE_TESTSUITE_ADB_RUNNER AdbRunner.sh
PATH_SUFFIXES share/corrade/TestSuite)
if(NOT CORRADE_TESTSUITE_ADB_RUNNER)
set(Corrade_${_component}_FOUND FALSE)
endif()
set(CORRADE_TESTSUITE_ADB_RUNNER_NEEDED CORRADE_TESTSUITE_ADB_RUNNER)
# Emscripten runner file
elseif(CORRADE_TARGET_EMSCRIPTEN)
find_file(CORRADE_TESTSUITE_EMSCRIPTEN_RUNNER EmscriptenRunner.html.in
PATH_SUFFIXES share/corrade/TestSuite)
if(NOT CORRADE_TESTSUITE_EMSCRIPTEN_RUNNER)
set(Corrade_${_component}_FOUND FALSE)
endif()
set(CORRADE_TESTSUITE_EMSCRIPTEN_RUNNER_NEEDED CORRADE_TESTSUITE_EMSCRIPTEN_RUNNER)
endif()
# Utility library (contains all setup that is used by others)
@ -717,96 +514,55 @@ foreach(_component ${Corrade_FIND_COMPONENTS})
set_property(TARGET Corrade::${_component} APPEND PROPERTY
COMPATIBLE_INTERFACE_NUMBER_MAX CORRADE_CXX_STANDARD)
# -fno-strict-aliasing is set in UseCorrade.cmake for everyone who
# enables CORRADE_USE_PEDANTIC_FLAGS. Not all projects linking to
# Corrade enable it (or can't enable it), but this flag is
# essential to prevent insane bugs and random breakages, so force
# it for anyone linking to Corrade::Utility. Similar code is in
# Corrade/Utility/CMakeLists.txt.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?Clang" AND NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") OR CORRADE_TARGET_EMSCRIPTEN)
set_property(TARGET Corrade::${_component} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS -fno-strict-aliasing)
endif()
# Path::libraryLocation() needs this
if(CORRADE_TARGET_UNIX)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
endif()
# AndroidLogStreamBuffer class needs to be linked to log library
if(CORRADE_TARGET_ANDROID)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES "log")
endif()
# Emscripten has various stuff implemented in JS
if(CORRADE_TARGET_EMSCRIPTEN)
find_file(CORRADE_UTILITY_JS CorradeUtility.js
PATH_SUFFIXES lib)
set_property(TARGET Corrade::${_component} APPEND PROPERTY
# TODO switch to INTERFACE_LINK_OPTIONS and SHELL: once we
# require CMake 3.13 unconditionally
INTERFACE_LINK_LIBRARIES "--js-library ${CORRADE_UTILITY_JS}")
endif()
endif()
# Find library includes
if(_component MATCHES ${_CORRADE_LIBRARY_COMPONENTS})
find_path(_CORRADE_${_COMPONENT}_INCLUDE_DIR
NAMES ${_CORRADE_${_COMPONENT}_INCLUDE_PATH_NAMES}
HINTS ${CORRADE_INCLUDE_DIR}/${_CORRADE_${_COMPONENT}_INCLUDE_PATH_SUFFIX})
mark_as_advanced(_CORRADE_${_COMPONENT}_INCLUDE_DIR)
endif()
# Add inter-library dependencies
if(_component IN_LIST _CORRADE_LIBRARY_COMPONENTS OR _component IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS)
foreach(_dependency ${_CORRADE_${_component}_DEPENDENCIES})
if(_dependency IN_LIST _CORRADE_LIBRARY_COMPONENTS OR _dependency IN_LIST _CORRADE_HEADER_ONLY_COMPONENTS)
if(_component MATCHES ${_CORRADE_LIBRARY_COMPONENTS} OR _component MATCHES ${_CORRADE_HEADER_ONLY_COMPONENTS})
foreach(_dependency ${_CORRADE_${_COMPONENT}_DEPENDENCIES})
if(_dependency MATCHES ${_CORRADE_LIBRARY_COMPONENTS} OR _dependency MATCHES ${_CORRADE_HEADER_ONLY_COMPONENTS})
set_property(TARGET Corrade::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES Corrade::${_dependency})
endif()
endforeach()
endif()
endif()
endforeach()
# For CMake 3.16+ with REASON_FAILURE_MESSAGE, provide additional potentially
# useful info about the failed components.
if(NOT CMAKE_VERSION VERSION_LESS 3.16)
set(_CORRADE_REASON_FAILURE_MESSAGE )
# Go only through the originally specified find_package() components, not
# the dependencies added by us afterwards
foreach(_component ${_CORRADE_ORIGINAL_FIND_COMPONENTS})
if(Corrade_${_component}_FOUND)
continue()
endif()
# If it's not known at all, tell the user -- it might be a new library
# and an old Find module, or something platform-specific.
if(NOT _component IN_LIST _CORRADE_LIBRARY_COMPONENTS AND NOT _component IN_LIST _CORRADE_EXECUTABLE_COMPONENTS)
list(APPEND _CORRADE_REASON_FAILURE_MESSAGE "${_component} is not a known component on this platform.")
# Otherwise, if it's not among implicitly built components, hint that
# the user may need to enable it.
# TODO: currently, the _FOUND variable doesn't reflect if dependencies
# were found. When it will, this needs to be updated to avoid
# misleading messages.
elseif(NOT _component IN_LIST _CORRADE_IMPLICITLY_ENABLED_COMPONENTS)
string(TOUPPER ${_component} _COMPONENT)
list(APPEND _CORRADE_REASON_FAILURE_MESSAGE "${_component} is not built by default. Make sure you enabled CORRADE_WITH_${_COMPONENT} when building Corrade.")
# Otherwise we have no idea. Better be silent than to print something
# misleading.
# Decide if the component was found
if((_component MATCHES ${_CORRADE_LIBRARY_COMPONENTS} AND _CORRADE_${_COMPONENT}_INCLUDE_DIR AND (_component MATCHES ${_CORRADE_HEADER_ONLY_COMPONENTS} OR CORRADE_${_COMPONENT}_LIBRARY_RELEASE OR CORRADE_${_COMPONENT}_LIBRARY_DEBUG)) OR (_component MATCHES ${_CORRADE_EXECUTABLE_COMPONENTS} AND CORRADE_${_COMPONENT}_EXECUTABLE))
set(Corrade_${_component}_FOUND TRUE)
else()
set(Corrade_${_component}_FOUND FALSE)
endif()
endforeach()
string(REPLACE ";" " " _CORRADE_REASON_FAILURE_MESSAGE "${_CORRADE_REASON_FAILURE_MESSAGE}")
set(_CORRADE_REASON_FAILURE_MESSAGE REASON_FAILURE_MESSAGE "${_CORRADE_REASON_FAILURE_MESSAGE}")
endif()
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Corrade REQUIRED_VARS
CORRADE_INCLUDE_DIR
_CORRADE_MODULE_DIR
_CORRADE_CONFIGURE_FILE
HANDLE_COMPONENTS
${_CORRADE_REASON_FAILURE_MESSAGE})
${CORRADE_TESTSUITE_XCTEST_RUNNER_NEEDED}
${CORRADE_TESTSUITE_ADB_RUNNER_NEEDED}
${CORRADE_TESTSUITE_EMSCRIPTEN_RUNNER_NEEDED}
HANDLE_COMPONENTS)
# Finalize the finding process
include(${CORRADE_USE_MODULE})
set(CORRADE_INCLUDE_INSTALL_DIR include/Corrade)
# Installation dirs
set(CORRADE_INCLUDE_INSTALL_PREFIX "."
CACHE STRING "Prefix where to put platform-independent include and other files")
if(CORRADE_BUILD_DEPRECATED AND CORRADE_INCLUDE_INSTALL_PREFIX AND NOT CORRADE_INCLUDE_INSTALL_PREFIX STREQUAL ".")
message(DEPRECATION "CORRADE_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.")
set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/${CORRADE_INCLUDE_INSTALL_DIR})
endif()
set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/include/Corrade)

86
modules/FindEGL.cmake

@ -0,0 +1,86 @@
#.rst:
# Find EGL
# --------
#
# Finds the EGL library. This module defines:
#
# EGL_FOUND - True if EGL library is found
# EGL::EGL - EGL imported target
#
# Additionally these variables are defined for internal usage:
#
# EGL_LIBRARY - EGL library
# EGL_INCLUDE_DIR - Include dir
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# Under Emscripten, GL is linked implicitly. With MINIMAL_RUNTIME you need to
# specify -lGL. Simply set the library name to that.
if(CORRADE_TARGET_EMSCRIPTEN)
set(EGL_LIBRARY GL CACHE STRING "Path to a library." FORCE)
else()
find_library(EGL_LIBRARY NAMES
EGL
# ANGLE (CMake doesn't search for lib prefix on Windows)
libEGL
# On iOS a part of OpenGLES
OpenGLES)
endif()
# Include dir
find_path(EGL_INCLUDE_DIR NAMES
EGL/egl.h
# iOS
EAGL.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG
EGL_LIBRARY
EGL_INCLUDE_DIR)
if(NOT TARGET EGL::EGL)
# Work around BUGGY framework support on macOS. Do this also in case of
# Emscripten, since there we don't have a location either.
# http://public.kitware.com/pipermail/cmake/2016-April/063179.html
if((APPLE AND ${EGL_LIBRARY} MATCHES "\\.framework$") OR CORRADE_TARGET_EMSCRIPTEN)
add_library(EGL::EGL INTERFACE IMPORTED)
set_property(TARGET EGL::EGL APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${EGL_LIBRARY})
else()
add_library(EGL::EGL UNKNOWN IMPORTED)
set_property(TARGET EGL::EGL PROPERTY
IMPORTED_LOCATION ${EGL_LIBRARY})
endif()
set_target_properties(EGL::EGL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${EGL_INCLUDE_DIR})
endif()
mark_as_advanced(EGL_LIBRARY EGL_INCLUDE_DIR)

94
modules/FindGLFW.cmake

@ -0,0 +1,94 @@
#.rst:
# Find GLFW
# ---------
#
# Finds the GLFW library using its cmake config if that exists, otherwise
# falls back to finding it manually. This module defines:
#
# GLFW_FOUND - True if GLFW library is found
# GLFW::GLFW - GLFW imported target
#
# Additionally, in case the config was not found, these variables are defined
# for internal usage:
#
# GLFW_LIBRARY - GLFW library
# GLFW_INCLUDE_DIR - Root include dir
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
# Copyright © 2016 Jonathan Hale <squareys@googlemail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# GLFW installs cmake package config files to shared/ folder which handles
# dependencies in case GLFW is built statically. Try to find first, quietly, so
# it doesn't print loud messages when it's not found, since that's okay.
find_package(glfw3 CONFIG QUIET)
if(TARGET glfw)
if(NOT TARGET GLFW::GLFW)
# Aliases of (global) targets are only supported in CMake 3.11, so we
# work around it by this. This is easier than fetching all possible
# properties (which are impossible to track of) and then attempting to
# rebuild them into a new target.
add_library(GLFW::GLFW INTERFACE IMPORTED)
set_target_properties(GLFW::GLFW PROPERTIES INTERFACE_LINK_LIBRARIES glfw)
endif()
# Just to make FPHSA print some meaningful location, nothing else
get_target_property(_GLFW_INTERFACE_INCLUDE_DIRECTORIES glfw INTERFACE_INCLUDE_DIRECTORIES)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("GLFW" DEFAULT_MSG
_GLFW_INTERFACE_INCLUDE_DIRECTORIES)
return()
endif()
# In case no config file was found, try manually finding the library.
find_library(GLFW_LIBRARY NAMES glfw glfw3)
# Include dir
find_path(GLFW_INCLUDE_DIR
NAMES GLFW/glfw3.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("GLFW" DEFAULT_MSG
GLFW_LIBRARY
GLFW_INCLUDE_DIR)
if(NOT TARGET GLFW::GLFW)
add_library(GLFW::GLFW UNKNOWN IMPORTED)
# Work around BUGGY framework support on macOS
# https://cmake.org/Bug/view.php?id=14105
if(CORRADE_TARGET_APPLE AND ${GLFW_LIBRARY} MATCHES "\\.framework$")
set_property(TARGET GLFW::GLFW PROPERTY IMPORTED_LOCATION ${GLFW_LIBRARY}/GLFW)
else()
set_property(TARGET GLFW::GLFW PROPERTY IMPORTED_LOCATION ${GLFW_LIBRARY})
endif()
set_property(TARGET GLFW::GLFW PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${GLFW_INCLUDE_DIR})
endif()
mark_as_advanced(GLFW_LIBRARY GLFW_INCLUDE_DIR)

832
modules/FindMagnum.cmake

File diff suppressed because it is too large Load Diff

162
modules/FindMagnumBindings.cmake

@ -34,8 +34,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -59,77 +58,22 @@
find_package(Magnum REQUIRED)
# Global include dir that's unique to Magnum Bindings. Often they will be
# installed alongside Magnum, which is why the hint, but if not, it shouldn't
# just pick MAGNUM_INCLUDE_DIR because then _MAGNUMBINDINGS_*_INCLUDE_DIR will
# fail to be found. In case of CMake subprojects the versionBindings.h is
# generated inside the build dir so this won't find it, instead
# src/CMakeLists.txt forcibly sets MAGNUMBINDINGS_INCLUDE_DIR as an internal
# cache value to make that work.
find_path(MAGNUMBINDINGS_INCLUDE_DIR Magnum/versionBindings.h
HINTS ${MAGNUM_INCLUDE_DIR})
# Global bindings include dir
find_path(MAGNUMBINDINGS_INCLUDE_DIR Magnum
HINTS ${MAGNUMBINDINGS_INCLUDE_DIR})
mark_as_advanced(MAGNUMBINDINGS_INCLUDE_DIR)
# CMake module dir for dependencies. It might not be present at all if no
# feature that needs them is enabled, in which case it'll be left at NOTFOUND.
# But in that case it should also not be subsequently needed for any
# find_package(). If this is called from a superproject, the
# _MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR is already set by
# modules/CMakeLists.txt.
#
# There's no dependency Find modules so far. Once there are, uncomment this and
# list the modules in NAMES.
#find_path(_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR
# NAMES
# PATH_SUFFIXES share/cmake/MagnumBindings/dependencies)
#mark_as_advanced(_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR)
# If the module dir is found and is not present in CMAKE_MODULE_PATH already
# (such as when someone explicitly added it, or if it's the Magnum's modules/
# dir in case of a superproject), add it as the first before all other. Set a
# flag to remove it again at the end, so the modules don't clash with Find
# modules of the same name from other projects.
if(_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR AND NOT _MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR IN_LIST CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH ${_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR} ${CMAKE_MODULE_PATH})
set(_MAGNUMBINDINGS_REMOVE_DEPENDENCY_MODULE_DIR_FROM_CMAKE_PATH ON)
else()
unset(_MAGNUMBINDINGS_REMOVE_DEPENDENCY_MODULE_DIR_FROM_CMAKE_PATH)
endif()
# Component distinction (listing them explicitly to avoid mistakes with finding
# components from other repositories)
set(_MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS Python)
# Nothing is enabled by default right now
set(_MAGNUMBINDINGS_IMPLICITLY_ENABLED_COMPONENTS )
# No inter-component dependencies right now
# Ensure that all inter-component dependencies are specified as well
set(_MAGNUMBINDINGS_ADDITIONAL_COMPONENTS )
foreach(_component ${MagnumBindings_FIND_COMPONENTS})
# Mark the dependencies as required if the component is also required
if(MagnumBindings_FIND_REQUIRED_${_component})
foreach(_dependency ${_MAGNUMBINDINGS_${_component}_DEPENDENCIES})
set(MagnumBindings_FIND_REQUIRED_${_dependency} TRUE)
endforeach()
endif()
set(_MAGNUMBINDINGS_HEADER_ONLY_COMPONENT_LIST Python)
list(APPEND _MAGNUMBINDINGS_ADDITIONAL_COMPONENTS ${_MAGNUMBINDINGS_${_component}_DEPENDENCIES})
# Convert components lists to regular expressions so I can use if(MATCHES).
# TODO: Drop this once CMake 3.3 and if(IN_LIST) can be used
foreach(_WHAT HEADER_ONLY)
string(REPLACE ";" "|" _MAGNUMBINDINGS_${_WHAT}_COMPONENTS "${_MAGNUMBINDINGS_${_WHAT}_COMPONENT_LIST}")
set(_MAGNUMBINDINGS_${_WHAT}_COMPONENTS "^(${_MAGNUMBINDINGS_${_WHAT}_COMPONENTS})$")
endforeach()
# Join the lists, remove duplicate components
set(_MAGNUMBINDINGS_ORIGINAL_FIND_COMPONENTS ${MagnumBindings_FIND_COMPONENTS})
if(_MAGNUMBINDINGS_ADDITIONAL_COMPONENTS)
list(INSERT MagnumBindings_FIND_COMPONENTS 0 ${_MAGNUMBINDINGS_ADDITIONAL_COMPONENTS})
endif()
if(MagnumBindings_FIND_COMPONENTS)
list(REMOVE_DUPLICATES MagnumBindings_FIND_COMPONENTS)
endif()
# Special cases of include paths. Libraries not listed here have a path suffix
# and include name derived from the library name in the loop below. (So far no
# special cases.)
# Find all components
foreach(_component ${MagnumBindings_FIND_COMPONENTS})
string(TOUPPER ${_component} _COMPONENT)
@ -137,95 +81,45 @@ foreach(_component ${MagnumBindings_FIND_COMPONENTS})
# Create imported target in case the library is found. If the project is
# added as subproject to CMake, the target already exists and all the
# required setup is already done from the build tree.
if(TARGET "MagnumBindings::${_component}") # Quotes to fix KDE's higlighter
if(TARGET MagnumBindings::${_component})
set(MagnumBindings_${_component}_FOUND TRUE)
else()
# Header-only components
if(_component IN_LIST _MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS)
# Include path names to find, unless specified above
if(NOT _MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_PATH_NAMES)
set(_MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_PATH_NAMES ${_component}Bindings.h)
endif()
if(_component MATCHES ${_MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS})
add_library(MagnumBindings::${_component} INTERFACE IMPORTED)
endif()
# Find library includes
if(_component IN_LIST _MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS)
# Python bindings
if(_component STREQUAL Python)
set(_MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_PATH_NAMES Magnum/SceneGraph/Python.h)
endif()
if(_component MATCHES ${_MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS})
# Find includes
find_path(_MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_DIR
NAMES ${_MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_PATH_NAMES}
HINTS ${MAGNUMBINDINGS_INCLUDE_DIR})
mark_as_advanced(_MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_DIR)
endif()
# Decide if the component was found. If not, skip the rest, which
# populates the target properties and finds additional dependencies.
if(_component IN_LIST _MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS AND _MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_DIR)
set(MagnumBindings_${_component}_FOUND TRUE)
else()
set(MagnumBindings_${_component}_FOUND FALSE)
continue()
endif()
# Target for header-only library components
if(_component IN_LIST _MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS)
add_library(MagnumBindings::${_component} INTERFACE IMPORTED)
endif()
# No special setup for Python bindings
if(_component IN_LIST _MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS)
# Link to core Magnum library
set_property(TARGET MagnumBindings::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES Magnum::Magnum)
# Add bindings include dir
# Add bindings incldue dir
set_property(TARGET MagnumBindings::${_component} APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${MAGNUMBINDINGS_INCLUDE_DIR})
endif()
endif()
endforeach()
# For CMake 3.16+ with REASON_FAILURE_MESSAGE, provide additional potentially
# useful info about the failed components.
if(NOT CMAKE_VERSION VERSION_LESS 3.16)
set(_MAGNUMBINDINGS_REASON_FAILURE_MESSAGE)
# Go only through the originally specified find_package() components, not
# the dependencies added by us afterwards
foreach(_component ${_MAGNUMBINDINGS_ORIGINAL_FIND_COMPONENTS})
if(MagnumBindings_${_component}_FOUND)
continue()
endif()
# If it's not known at all, tell the user -- it might be a new library
# and an old Find module, or something platform-specific.
if(NOT _component IN_LIST _MAGNUMBINDINGS_LIBRARY_COMPONENTS AND NOT _component IN_LIST _MAGNUMBINDINGS_PLUGIN_COMPONENTS)
list(APPEND _MAGNUMBINDINGS_REASON_FAILURE_MESSAGE "${_component} is not a known component on this platform.")
# Otherwise, if it's not among implicitly built components, hint that
# the user may need to enable it
# TODO: currently, the _FOUND variable doesn't reflect if dependencies
# were found. When it will, this needs to be updated to avoid
# misleading messages.
elseif(NOT _component IN_LIST _MAGNUMBINDINGS_IMPLICITLY_ENABLED_COMPONENTS)
string(TOUPPER ${_component} _COMPONENT)
list(APPEND _MAGNUMBINDINGS_REASON_FAILURE_MESSAGE "${_component} is not built by default. Make sure you enabled MAGNUM_WITH_${_COMPONENT} when building Magnum Bindings")
# Otherwise we have no idea. Better be silent than to print something
# misleading.
# Decide if the component was found
if(_component MATCHES ${_MAGNUMBINDINGS_HEADER_ONLY_COMPONENTS} AND _MAGNUMBINDINGS_${_COMPONENT}_INCLUDE_DIR)
set(MagnumBindings_${_component}_FOUND TRUE)
else()
set(MagnumBindings_${_component}_FOUND FALSE)
endif()
endforeach()
string(REPLACE ";" " " _MAGNUMBINDINGS_REASON_FAILURE_MESSAGE "${_MAGNUMBINDINGS_REASON_FAILURE_MESSAGE}")
set(_MAGNUMBINDINGS_REASON_FAILURE_MESSAGE REASON_FAILURE_MESSAGE "${_MAGNUMBINDINGS_REASON_FAILURE_MESSAGE}")
endif()
# Remove Magnum Extras dependency module dir from CMAKE_MODULE_PATH again. Do
# it before the FPHSA call which may exit early in case of a failure.
if(_MAGNUMBINDINGS_REMOVE_DEPENDENCY_MODULE_DIR_FROM_CMAKE_PATH)
list(REMOVE_ITEM CMAKE_MODULE_PATH ${_MAGNUMBINDINGS_DEPENDENCY_MODULE_DIR})
unset(_MAGNUMBINDINGS_REMOVE_DEPENDENCY_MODULE_DIR_FROM_CMAKE_PATH)
endif()
endif()
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MagnumBindings
REQUIRED_VARS MAGNUMBINDINGS_INCLUDE_DIR
HANDLE_COMPONENTS
${_MAGNUMBINDINGS_REASON_FAILURE_MESSAGE})
HANDLE_COMPONENTS)

78
modules/FindOpenGLES2.cmake

@ -0,0 +1,78 @@
#.rst:
# Find OpenGL ES 2
# ----------------
#
# Finds the OpenGL ES 2 library. This module defines:
#
# OpenGLES2_FOUND - True if OpenGL ES 2 library is found
# OpenGLES2::OpenGLES2 - OpenGL ES 2 imported target
#
# Additionally these variables are defined for internal usage:
#
# OPENGLES2_LIBRARY - OpenGL ES 2 library
#
# Please note this find module is tailored especially for the needs of Magnum.
# In particular, it depends on its platform definitions and doesn't look for
# OpenGL ES includes as Magnum has its own, generated using flextGL.
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# Under Emscripten, GL is linked implicitly. With MINIMAL_RUNTIME you need to
# specify -lGL. Simply set the library name to that.
if(CORRADE_TARGET_EMSCRIPTEN)
set(OPENGLES2_LIBRARY GL CACHE STRING "Path to a library." FORCE)
else()
find_library(OPENGLES2_LIBRARY NAMES
GLESv2
# ANGLE (CMake doesn't search for lib prefix on Windows)
libGLESv2
# iOS
OpenGLES)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenGLES2 DEFAULT_MSG
OPENGLES2_LIBRARY)
if(NOT TARGET OpenGLES2::OpenGLES2)
# Work around BUGGY framework support on macOS. Do this also in case of
# Emscripten, since there we don't have a location either.
# http://public.kitware.com/pipermail/cmake/2016-April/063179.html
if((CORRADE_TARGET_APPLE AND ${OPENGLES2_LIBRARY} MATCHES "\\.framework$") OR CORRADE_TARGET_EMSCRIPTEN)
add_library(OpenGLES2::OpenGLES2 INTERFACE IMPORTED)
set_property(TARGET OpenGLES2::OpenGLES2 APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${OPENGLES2_LIBRARY})
else()
add_library(OpenGLES2::OpenGLES2 UNKNOWN IMPORTED)
set_property(TARGET OpenGLES2::OpenGLES2 PROPERTY
IMPORTED_LOCATION ${OPENGLES2_LIBRARY})
endif()
endif()
mark_as_advanced(OPENGLES2_LIBRARY)

92
modules/FindOpenGLES3.cmake

@ -0,0 +1,92 @@
#.rst:
# Find OpenGL ES 3
# ----------------
#
# Finds the OpenGL ES 3 library. This module defines:
#
# OpenGLES3_FOUND - True if OpenGL ES 3 library is found
# OpenGLES3::OpenGLES3 - OpenGL ES 3 imported target
#
# Additionally these variables are defined for internal usage:
#
# OPENGLES3_LIBRARY - OpenGL ES 3 library
#
# Please note this find module is tailored especially for the needs of Magnum.
# In particular, it depends on its platform definitions and doesn't look for
# OpenGL ES includes as Magnum has its own, generated using flextGL.
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# Under Emscripten, GL is linked implicitly. With MINIMAL_RUNTIME you need to
# specify -lGL. Simply set the library name to that.
if(CORRADE_TARGET_EMSCRIPTEN)
set(OPENGLES3_LIBRARY GL CACHE STRING "Path to a library." FORCE)
else()
find_library(OPENGLES3_LIBRARY NAMES
GLESv3
# On some platforms (e.g. desktop emulation with Mesa or NVidia) ES3
# support is provided in ES2 lib
GLESv2
# ANGLE (CMake doesn't search for lib prefix on Windows)
libGLESv2
# iOS
OpenGLES)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("OpenGLES3" DEFAULT_MSG
OPENGLES3_LIBRARY)
if(NOT TARGET OpenGLES3::OpenGLES3)
# Work around BUGGY framework support on macOS. Do this also in case of
# Emscripten, since there we don't have a location either.
# http://public.kitware.com/pipermail/cmake/2016-April/063179.html
if((CORRADE_TARGET_APPLE AND ${OPENGLES3_LIBRARY} MATCHES "\\.framework$") OR CORRADE_TARGET_EMSCRIPTEN)
add_library(OpenGLES3::OpenGLES3 INTERFACE IMPORTED)
set_property(TARGET OpenGLES3::OpenGLES3 APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${OPENGLES3_LIBRARY})
else()
add_library(OpenGLES3::OpenGLES3 UNKNOWN IMPORTED)
set_property(TARGET OpenGLES3::OpenGLES3 PROPERTY
IMPORTED_LOCATION ${OPENGLES3_LIBRARY})
endif()
# Emscripten needs a special flag to use WebGL 2. CMake 3.13 allows to set
# this via INTERFACE_LINK_OPTIONS, for older versions we modify the global
# CMAKE_EXE_LINKER_FLAGS inside FindMagnum.cmake.
if(CORRADE_TARGET_EMSCRIPTEN AND NOT CMAKE_VERSION VERSION_LESS 3.13)
# I could probably use target_link_options() here, but let's be
# consistent with the rest
set_property(TARGET OpenGLES3::OpenGLES3 APPEND PROPERTY
INTERFACE_LINK_OPTIONS "SHELL:-s USE_WEBGL2=1")
endif()
endif()
mark_as_advanced(OPENGLES3_LIBRARY)

173
modules/FindSDL2.cmake

@ -0,0 +1,173 @@
#.rst:
# Find SDL2
# ---------
#
# Finds the SDL2 library. This module defines:
#
# SDL2_FOUND - True if SDL2 library is found
# SDL2::SDL2 - SDL2 imported target
#
# Additionally these variables are defined for internal usage:
#
# SDL2_LIBRARY_DEBUG - SDL2 debug library, if found
# SDL2_LIBRARY_RELEASE - SDL2 release library, if found
# SDL2_INCLUDE_DIR - Root include dir
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
# Copyright © 2018 Jonathan Hale <squareys@googlemail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# In Emscripten SDL is linked automatically, thus no need to find the library.
# Also the includes are in SDL subdirectory, not SDL2.
if(CORRADE_TARGET_EMSCRIPTEN)
set(_SDL2_PATH_SUFFIXES SDL)
else()
set(_SDL2_PATH_SUFFIXES SDL2)
if(WIN32)
# Precompiled libraries for MSVC are in x86/x64 subdirectories
if(MSVC)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_SDL2_LIBRARY_PATH_SUFFIX lib/x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(_SDL2_LIBRARY_PATH_SUFFIX lib/x86)
endif()
# Both includes and libraries for MinGW are in some directory deep
# inside. There's also a CMake config file but it has HARDCODED path
# to /opt/local/i686-w64-mingw32, which doesn't make ANY SENSE,
# especially on Windows.
elseif(MINGW)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_SDL2_LIBRARY_PATH_SUFFIX x86_64-w64-mingw32/lib)
list(APPEND _SDL2_PATH_SUFFIXES x86_64-w64-mingw32/include/SDL2)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(_SDL2_LIBRARY_PATH_SUFFIX i686-w64-mingw32/lib)
list(APPEND _SDL2_PATH_SUFFIXES i686-w64-mingw32/include/SDL2)
endif()
endif()
endif()
find_library(SDL2_LIBRARY_RELEASE
# Compiling SDL2 from scratch on macOS creates dead libSDL2.so symlink
# which CMake somehow prefers before the SDL2-2.0.dylib file. Making
# the dylib first so it is preferred. Not sure how this maps to debug
# config though :/
NAMES SDL2-2.0 SDL2
PATH_SUFFIXES ${_SDL2_LIBRARY_PATH_SUFFIX})
find_library(SDL2_LIBRARY_DEBUG
NAMES SDL2d
PATH_SUFFIXES ${_SDL2_LIBRARY_PATH_SUFFIX})
# FPHSA needs one of the _DEBUG/_RELEASE variables to check that the
# library was found -- using SDL_LIBRARY, which will get populated by
# select_library_configurations() below.
set(SDL2_LIBRARY_NEEDED SDL2_LIBRARY)
endif()
include(SelectLibraryConfigurations)
select_library_configurations(SDL2)
# Include dir
find_path(SDL2_INCLUDE_DIR
# We must search file which is present only in SDL2 and not in SDL1.
# Apparently when both SDL.h and SDL_scancode.h are specified, CMake is
# happy enough that it found SDL.h and doesn't bother about the other.
#
# On macOS, where the includes are not in SDL2/SDL.h form (which would
# solve this issue), but rather SDL2.framework/Headers/SDL.h, CMake might
# find SDL.framework/Headers/SDL.h if SDL1 is installed, which is wrong.
NAMES SDL_scancode.h
PATH_SUFFIXES ${_SDL2_PATH_SUFFIXES})
# iOS dependencies
if(CORRADE_TARGET_IOS)
set(_SDL2_FRAMEWORKS
AudioToolbox
AVFoundation
CoreGraphics
CoreMotion
Foundation
GameController
QuartzCore
UIKit)
set(_SDL2_FRAMEWORK_LIBRARIES )
foreach(framework ${_SDL2_FRAMEWORKS})
find_library(_SDL2_${framework}_LIBRARY ${framework})
mark_as_advanced(_SDL2_${framework}_LIBRARY)
list(APPEND _SDL2_FRAMEWORK_LIBRARIES ${_SDL2_${framework}_LIBRARY})
list(APPEND _SDL2_FRAMEWORK_LIBRARY_NAMES _SDL2_${framework}_LIBRARY)
endforeach()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("SDL2" DEFAULT_MSG
${SDL2_LIBRARY_NEEDED}
${_SDL2_FRAMEWORK_LIBRARY_NAMES}
SDL2_INCLUDE_DIR)
if(NOT TARGET SDL2::SDL2)
if(SDL2_LIBRARY_NEEDED)
add_library(SDL2::SDL2 UNKNOWN IMPORTED)
# Work around BUGGY framework support on macOS
# https://cmake.org/Bug/view.php?id=14105
if(CORRADE_TARGET_APPLE AND SDL2_LIBRARY_RELEASE MATCHES "\\.framework$")
set_property(TARGET SDL2::SDL2 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_property(TARGET SDL2::SDL2 PROPERTY IMPORTED_LOCATION_RELEASE ${SDL2_LIBRARY_RELEASE}/SDL2)
else()
if(SDL2_LIBRARY_RELEASE)
set_property(TARGET SDL2::SDL2 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_property(TARGET SDL2::SDL2 PROPERTY IMPORTED_LOCATION_RELEASE ${SDL2_LIBRARY_RELEASE})
endif()
if(SDL2_LIBRARY_DEBUG)
set_property(TARGET SDL2::SDL2 APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_property(TARGET SDL2::SDL2 PROPERTY IMPORTED_LOCATION_DEBUG ${SDL2_LIBRARY_DEBUG})
endif()
endif()
# Link additional `dl` and `pthread` libraries required by a static
# build of SDL on Unixy platforms (except Apple, where it is most
# probably some frameworks instead)
if(CORRADE_TARGET_UNIX AND NOT CORRADE_TARGET_APPLE AND SDL2_LIBRARY MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
find_package(Threads)
set_property(TARGET SDL2::SDL2 APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
endif()
# Link frameworks on iOS
if(CORRADE_TARGET_IOS)
set_property(TARGET SDL2::SDL2 APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${_SDL2_FRAMEWORK_LIBRARIES})
endif()
else()
add_library(SDL2::SDL2 INTERFACE IMPORTED)
endif()
set_property(TARGET SDL2::SDL2 PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR})
endif()
mark_as_advanced(SDL2_INCLUDE_DIR)

3
modules/MagnumBindingsConfig.cmake

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a

2
package/archlinux/.gitignore vendored

@ -1,3 +1,3 @@
pkg/
src/
*pkg.tar.zst
*pkg.tar.xz

1
package/archlinux/.kateconfig

@ -1 +0,0 @@
kate-wildcard(PKGBUILD*): hl bash;

37
package/archlinux/PKGBUILD

@ -8,42 +8,27 @@ url="https://magnum.graphics"
license=('MIT')
depends=('corrade' 'magnum' 'python')
makedepends=('cmake' 'ninja' 'pybind11')
options=(!buildflags)
provides=('magnum-bindings-git')
_rootdir=$startdir/../../
_buildtype=Release
# _buildtype=Debug
build() {
mkdir -p "$_rootdir/build"
cd "$_rootdir/build"
# Only one of these is built.
#
# Colored output is enabled implicitly. If Ninja detects it's outputting to
# a pipe, it strips it away from the output, alternatively you can set the
# GCC_COLORS= (empty) env variable to temporarily disable colors. The
# inverse, i.e. preserving colors when Ninja outputs to a pipe can be done
# with CLICOLOR_FORCE=1: https://github.com/ninja-build/ninja/issues/2196
# Disable optimization (saves A LOT of compilation time)
newcxxflags=$(echo $CXXFLAGS | sed s/-O.//g | sed s/-D_FORTIFY_SOURCE=.//g)
export CXXFLAGS="$newcxxflags"
cmake .. \
-DCMAKE_CONFIGURATION_TYPES="Release;Debug;RelWithDebInfo" \
-DCMAKE_CROSS_CONFIGS=all \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -g -DNDEBUG -fno-omit-frame-pointer" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_COLOR_DIAGNOSTICS=ON \
-DPYTHON_EXECUTABLE=$(which python) \
-DMAGNUM_WITH_PYTHON=ON \
-DMAGNUM_BUILD_TESTS=ON \
-G "Ninja Multi-Config"
ninja all:$_buildtype
-DWITH_PYTHON=ON \
-G Ninja
ninja
}
check() {
cd "$_rootdir/build"
CORRADE_TEST_COLOR=ON ctest --output-on-failure -C $_buildtype
cd "$_rootdir/src/python/corrade"
python -m unittest -v
@ -51,15 +36,15 @@ check() {
python -m unittest -v
cd "$_rootdir/doc/python"
PYTHONPATH="$_rootdir/build/src/python/$_buildtype" python -m doctest -v *.rst
PYTHONPATH="$_rootdir/build/src/python" python -m doctest -v *.rst
}
package() {
# Helper headers
cd "$_rootdir/build"
DESTDIR="$pkgdir/" ninja install:$_buildtype
DESTDIR="$pkgdir/" ninja install
# Native and python packages
cd "$_rootdir/build/src/python/$_buildtype"
cd "$_rootdir/build/src/python"
python setup.py install --root="$pkgdir" --prefix=/usr
}

23
package/archlinux/PKGBUILD-coverage

@ -7,7 +7,7 @@ arch=('i686' 'x86_64')
url="https://magnum.graphics"
license=('MIT')
depends=('corrade' 'magnum' 'python')
makedepends=('cmake' 'ninja' 'pybind11' 'lcov' 'python-coverage')
makedepends=('cmake' 'ninja' 'pybind11' 'lcov')
provides=('magnum-bindings-git')
_rootdir=$startdir/../../
@ -20,19 +20,11 @@ build() {
newcxxflags=$(echo $CXXFLAGS | sed s/-O.//g | sed s/-D_FORTIFY_SOURCE=.//g)
export CXXFLAGS="$newcxxflags"
# Colored output is enabled implicitly. If Ninja detects it's outputting to
# a pipe, it strips it away from the output, alternatively you can set the
# GCC_COLORS= (empty) env variable to temporarily disable colors. The
# inverse, i.e. preserving colors when Ninja outputs to a pipe can be done
# with CLICOLOR_FORCE=1: https://github.com/ninja-build/ninja/issues/2196
cmake .. \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_COLOR_DIAGNOSTICS=ON \
-DPYTHON_EXECUTABLE=$(which python) \
-DMAGNUM_WITH_PYTHON=ON \
-DMAGNUM_BUILD_TESTS=ON \
-DWITH_PYTHON=ON \
-G Ninja
ninja
}
@ -56,13 +48,14 @@ check() {
rm -rf coverage
mkdir coverage
# Keep in sync with package/ci/circleci.yml, please
# TODO figure out a way to avoid adding --ignore-errors mismatch etc
lcov --ignore-errors mismatch,inconsistent --directory . --capture --output-file coverage.info
lcov --ignore-errors inconsistent --extract coverage.info "*/src/python/*" "*/src/Corrade/*" "*/src/Magnum/*" --output-file coverage.info
genhtml --no-function-coverage --missed --output-directory ./coverage coverage.info
# Keep in sync with package/ci/travis.yml, please
lcov --directory . --capture --output-file coverage.info
lcov --extract coverage.info "*/src/python/*" "*/src/Corrade/*" "*/src/Magnum/*" --output-file coverage.info
genhtml --output-directory ./coverage coverage.info
}
package() {
echo -e "Open \n file://${_rootdir}build-coverage/coverage/index.html\n file://${_rootdir}src/python/htmlcov/index.html\nto see the results." && false
}
# kate: hl bash

41
package/archlinux/magnum-bindings-git/PKGBUILD

@ -1,41 +0,0 @@
# Author: mosra <mosra@centrum.cz>
pkgname=magnum-bindings-git
pkgver=2020.06.r116.g62a07c3
pkgrel=1
pkgdesc="Bindings for the Magnum C++11/C++14 graphics engine (Git version)"
arch=('i686' 'x86_64')
url="https://magnum.graphics"
license=('MIT')
depends=('magnum-git' 'python')
makedepends=('cmake' 'git' 'ninja' 'pybind11')
provides=('magnum-bindings')
conflicts=('magnum-bindings')
source=("git+https://github.com/mosra/magnum-bindings.git")
sha1sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
git describe --long | sed -r 's/([^-]*-g)/r\1/;s/-/./g;s/v//g'
}
build() {
mkdir -p "$srcdir/build"
cd "$srcdir/build"
cmake "$srcdir/${pkgname%-git}" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DMAGNUM_WITH_PYTHON=ON \
-G Ninja
ninja
}
package() {
# Helper headers
cd "$srcdir/build"
DESTDIR="$pkgdir/" ninja install
# Native and python packages
cd "$srcdir/build/src/python"
python setup.py install --root="$pkgdir" --prefix=/usr
}

141
package/ci/appveyor-desktop-gles.bat

@ -1,139 +1,90 @@
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2022" call "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
set PATH=%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
rem Build pybind11. Downloaded in the appveyor.yml script. Forcing
rem -DCMAKE_POLICY_VERSION_MINIMUM=3.5 because it's bumped from 3.4 to 3.5 only
rem in version 2.11, which got released in 2023, years after the MSVC versions
rem we test for.
cd pybind11-%PYBIND% || exit /b
rem Build pybind11. Downloaded in the appveyor.yml script.
cd pybind11-2.3.0 || exit /b
mkdir -p build && cd build || exit /b
cmake .. ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
-DPYBIND11_PYTHON_VERSION=3.%PYTHON% ^
-DPYBIND11_PYTHON_VERSION=3.6 ^
-DPYBIND11_TEST=OFF ^
-G Ninja || exit /b
ninja install || exit /b
cd .. && cd ..
rem Build Corrade
git clone --depth 1 https://github.com/mosra/corrade.git || exit /b
git clone --depth 1 git://github.com/mosra/corrade.git || exit /b
cd corrade || exit /b
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCORRADE_BUILD_STATIC=%BUILD_STATIC% ^
-DCORRADE_WITH_INTERCONNECT=OFF ^
-DCORRADE_WITH_PLUGINMANAGER=ON ^
-DCORRADE_WITH_TESTSUITE=ON ^
-DCORRADE_UTILITY_USE_ANSI_COLORS=ON ^
-DBUILD_DEPRECATED=OFF ^
-DBUILD_STATIC=%BUILD_STATIC% ^
-DWITH_INTERCONNECT=OFF ^
-DWITH_PLUGINMANAGER=ON ^
-DWITH_TESTSUITE=OFF ^
-DUTILITY_USE_ANSI_COLORS=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build Magnum
git clone --depth 1 https://github.com/mosra/magnum.git || exit /b
git clone --depth 1 git://github.com/mosra/magnum.git || exit /b
cd magnum || exit /b
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DMAGNUM_BUILD_STATIC=%BUILD_STATIC% ^
-DMAGNUM_TARGET_GLES=ON ^
-DMAGNUM_TARGET_GLES2=%TARGET_GLES2% ^
-DMAGNUM_TARGET_EGL=OFF ^
-DMAGNUM_WITH_AUDIO=OFF ^
-DMAGNUM_WITH_DEBUGTOOLS=OFF ^
-DMAGNUM_WITH_MATERIALTOOLS=ON ^
-DMAGNUM_WITH_GL=ON ^
-DMAGNUM_WITH_MESHTOOLS=ON ^
-DMAGNUM_WITH_PRIMITIVES=ON ^
-DMAGNUM_WITH_SCENEGRAPH=ON ^
-DMAGNUM_WITH_SCENETOOLS=ON ^
-DMAGNUM_WITH_SHADERS=ON ^
-DMAGNUM_WITH_SHADERTOOLS=OFF ^
-DMAGNUM_WITH_TEXT=ON ^
-DMAGNUM_WITH_TEXTURETOOLS=ON ^
-DMAGNUM_WITH_TRADE=ON ^
-DMAGNUM_WITH_VK=OFF ^
-DMAGNUM_WITH_SDL2APPLICATION=OFF ^
-DMAGNUM_WITH_GLFWAPPLICATION=OFF ^
-DMAGNUM_WITH_WINDOWLESSWGLAPPLICATION=ON ^
-DMAGNUM_WITH_ANYIMAGEIMPORTER=ON ^
-DMAGNUM_WITH_ANYSCENECONVERTER=ON ^
-DMAGNUM_WITH_ANYSCENEIMPORTER=ON ^
-DMAGNUM_WITH_TGAIMPORTER=ON ^
-DBUILD_DEPRECATED=OFF ^
-DBUILD_STATIC=%BUILD_STATIC% ^
-DTARGET_GLES=ON ^
-DTARGET_GLES2=%TARGET_GLES2% ^
-DTARGET_DESKTOP_GLES=ON ^
-DWITH_AUDIO=OFF ^
-DWITH_DEBUGTOOLS=OFF ^
-DWITH_GL=ON ^
-DWITH_MESHTOOLS=ON ^
-DWITH_PRIMITIVES=ON ^
-DWITH_SCENEGRAPH=ON ^
-DWITH_SHADERS=ON ^
-DWITH_TEXT=OFF ^
-DWITH_TEXTURETOOLS=ON ^
-DWITH_TRADE=ON ^
-DWITH_VK=OFF ^
-DWITH_SDL2APPLICATION=OFF ^
-DWITH_GLFWAPPLICATION=OFF ^
-DWITH_WINDOWLESSWGLAPPLICATION=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build Magnum Plugins
git clone --depth 1 https://github.com/mosra/magnum-plugins.git || exit /b
cd magnum-plugins || exit /b
rem Build. BUILD_GL_TESTS is enabled just to be sure, it should not be needed
rem by any plugin.
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DMAGNUM_BUILD_STATIC=%BUILD_STATIC% ^
-DMAGNUM_WITH_BCDECIMAGECONVERTER=ON ^
-DMAGNUM_WITH_DDSIMPORTER=ON ^
-DMAGNUM_WITH_ETCDECIMAGECONVERTER=ON ^
-DMAGNUM_WITH_GLTFIMPORTER=ON ^
-DMAGNUM_WITH_GLTFSCENECONVERTER=ON ^
-DMAGNUM_WITH_KTXIMAGECONVERTER=ON ^
-DMAGNUM_WITH_MESHOPTIMIZERSCENECONVERTER=ON ^
-DMAGNUM_WITH_PRIMITIVEIMPORTER=ON ^
-DMAGNUM_WITH_STANFORDSCENECONVERTER=ON ^
-DMAGNUM_WITH_STBIMAGECONVERTER=ON ^
-DMAGNUM_WITH_STBIMAGEIMPORTER=ON ^
-DMAGNUM_WITH_STBRESIZEIMAGECONVERTER=ON ^
-DMAGNUM_WITH_STBTRUETYPEFONT=ON ^
-DPYBIND11_PYTHON_VERSION=3.6 ^
-DWITH_PYTHON=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build. Again forcing -DCMAKE_POLICY_VERSION_MINIMUM=3.5 because the
rem pybind11 CMake config files also require just 3.4 now.
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
-DPYBIND11_PYTHON_VERSION=3.%PYTHON% ^
-DMAGNUM_WITH_PYTHON=ON ^
-DMAGNUM_BUILD_TESTS=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
rem Test
set CORRADE_TEST_COLOR=ON
rem On Windows, if an assertion or other issue happens, A DIALOG WINDOWS POPS
rem UP FROM THE CONSOLE. And then, for fucks sake, IT WAITS ENDLESSLY FOR YOU
rem TO CLOSE IT!! Such behavior is utterly stupid in a non-interactive setting
rem such as on this very CI, so I'm setting a timeout to 60 seconds to avoid
rem the CI job being stuck for an hour if an assertion happens. CTest's default rem timeouts is somehow 10M seconds, which is as useful as nothing at all.
ctest -V -E GLTest --timeout 60 || exit /b
rem Verify the setuptools install
cd src/python || exit /b
python setup.py install --root="%APPVEYOR_BUILD_FOLDER%/install" || exit /b
rem Run python tests & gather coverage
rem Run tests & gather coverage
cd ../../../src/python/corrade || exit /b
coverage run -m unittest -v || exit /b
cp .coverage ../.coverage.corrade || exit /b
coverage run -m unittest -v && cp .coverage ../.coverage.corrade || exit /b
cd ../magnum || exit /b
set MAGNUM_SKIP_GL_TESTS=ON
coverage run -m unittest -v || exit /b
cp .coverage ../.coverage.magnum || exit /b
coverage run -m unittest -v && cp .coverage ../.coverage.magnum || exit /b
rem Test docstring validity
cd ../../../doc/python || exit /b
@ -145,6 +96,18 @@ rem python -m doctest -v *.rst || exit /b
rem Upload coverage
cd ../../src/python || exit /b
coverage combine || exit /b
rem TODO: Currently disabled because I can't seem to convince it to relocate
rem the paths via codecov.yml: https://github.com/mosra/magnum-bindings/pull/3
rem codecov -X gcov || exit /b
rem I am unable to convince codecov to relocate paths using codecov.yml so
rem let's do that manually. But that doesn't work either.
powershell -Command "(gc .coverage) -replace 'C:\\\\projects\\\\magnum-bindings\\\\build\\\\src\\\\python\\\\', 'C:\\projects\\magnum-bindings\\src\\python\\' | Out-File -encoding ASCII .coverage" || exit /b
type .coverage
del ..\..\build\src\python\corrade\__init__.py || exit /b
del ..\..\build\src\python\magnum\__init__.py || exit /b
del ..\..\build\src\python\magnum\platform\__init__.py || exit /b
cd ..\..
codecov -X gcov || exit /b
type coverage.xml

151
package/ci/appveyor-desktop.bat

@ -1,150 +1,91 @@
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2022" call "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
rem SDL2 has the DLL in lib/x64, and in the static build it's imported so the
rem DLL has to be found.
set PATH=%APPVEYOR_BUILD_FOLDER%\deps\bin;%APPVEYOR_BUILD_FOLDER%\SDL\lib\x64;%PATH%
rem need to explicitly specify a 64-bit target, otherwise CMake+Ninja can't
rem figure that out -- https://gitlab.kitware.com/cmake/cmake/issues/16259
rem for TestSuite we need to enable exceptions explicitly with /EH as these are
rem currently disabled -- https://github.com/catchorg/Catch2/issues/1113
if "%COMPILER%" == "msvc-clang" if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2022" set COMPILER_EXTRA=-DCMAKE_CXX_COMPILER="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/bin/clang-cl.exe" -DCMAKE_LINKER="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/Llvm/bin/lld-link.exe" -DCMAKE_CXX_FLAGS="-m64 /EHsc"
if "%COMPILER%" == "msvc-clang" if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" set COMPILER_EXTRA=-DCMAKE_CXX_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/clang-cl.exe" -DCMAKE_LINKER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/Llvm/bin/lld-link.exe" -DCMAKE_CXX_FLAGS="-m64 /EHsc"
set EXCEPT_MSVC2017=ON
IF "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" set EXCEPT_MSVC2017=OFF
rem Build pybind11. Downloaded in the appveyor.yml script. Forcing
rem -DCMAKE_POLICY_VERSION_MINIMUM=3.5 because it's bumped from 3.4 to 3.5 only
rem in version 2.11, which got released in 2023, years after the MSVC versions
rem we test for.
cd pybind11-%PYBIND% || exit /b
rem Build pybind11. Downloaded in the appveyor.yml script.
cd pybind11-2.3.0 || exit /b
mkdir -p build && cd build || exit /b
cmake .. ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
-DPYBIND11_PYTHON_VERSION=3.%PYTHON% ^
-DPYBIND11_PYTHON_VERSION=3.6 ^
-DPYBIND11_TEST=OFF ^
-G Ninja || exit /b
ninja install || exit /b
cd .. && cd ..
rem Build Corrade
git clone --depth 1 https://github.com/mosra/corrade.git || exit /b
git clone --depth 1 git://github.com/mosra/corrade.git || exit /b
cd corrade || exit /b
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCORRADE_BUILD_STATIC=%BUILD_STATIC% ^
-DCORRADE_WITH_INTERCONNECT=OFF ^
-DCORRADE_WITH_PLUGINMANAGER=ON ^
-DCORRADE_WITH_TESTSUITE=ON ^
-DCORRADE_UTILITY_USE_ANSI_COLORS=ON ^
%COMPILER_EXTRA% -G Ninja || exit /b
-DBUILD_DEPRECATED=OFF ^
-DBUILD_STATIC=%BUILD_STATIC% ^
-DWITH_INTERCONNECT=OFF ^
-DWITH_PLUGINMANAGER=ON ^
-DWITH_TESTSUITE=OFF ^
-DUTILITY_USE_ANSI_COLORS=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build Magnum
git clone --depth 1 https://github.com/mosra/magnum.git || exit /b
git clone --depth 1 git://github.com/mosra/magnum.git || exit /b
cd magnum || exit /b
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%/SDL ^
-DMAGNUM_BUILD_STATIC=%BUILD_STATIC% %STATIC_PLUGIN_PATH% ^
-DMAGNUM_WITH_AUDIO=OFF ^
-DMAGNUM_WITH_DEBUGTOOLS=OFF ^
-DMAGNUM_WITH_GL=ON ^
-DMAGNUM_WITH_MATERIALTOOLS=ON ^
-DMAGNUM_WITH_MESHTOOLS=ON ^
-DMAGNUM_WITH_PRIMITIVES=ON ^
-DMAGNUM_WITH_SCENEGRAPH=ON ^
-DMAGNUM_WITH_SCENETOOLS=ON ^
-DMAGNUM_WITH_SHADERS=ON ^
-DMAGNUM_WITH_SHADERTOOLS=OFF ^
-DMAGNUM_WITH_TEXT=ON ^
-DMAGNUM_WITH_TEXTURETOOLS=ON ^
-DMAGNUM_WITH_TRADE=ON ^
-DMAGNUM_WITH_VK=OFF ^
-DMAGNUM_WITH_SDL2APPLICATION=ON ^
-DMAGNUM_WITH_GLFWAPPLICATION=ON ^
-DMAGNUM_WITH_WINDOWLESSWGLAPPLICATION=ON ^
-DMAGNUM_WITH_ANYIMAGEIMPORTER=ON ^
-DMAGNUM_WITH_ANYSCENECONVERTER=ON ^
-DMAGNUM_WITH_ANYSCENEIMPORTER=ON ^
-DMAGNUM_WITH_TGAIMPORTER=ON ^
%COMPILER_EXTRA% -G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build Magnum Plugins
git clone --depth 1 https://github.com/mosra/magnum-plugins.git || exit /b
cd magnum-plugins || exit /b
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DMAGNUM_BUILD_STATIC=%BUILD_STATIC% ^
-DMAGNUM_WITH_BCDECIMAGECONVERTER=ON ^
-DMAGNUM_WITH_DDSIMPORTER=ON ^
-DMAGNUM_WITH_ETCDECIMAGECONVERTER=ON ^
-DMAGNUM_WITH_GLTFIMPORTER=ON ^
-DMAGNUM_WITH_GLTFSCENECONVERTER=ON ^
-DMAGNUM_WITH_KTXIMAGECONVERTER=ON ^
-DMAGNUM_WITH_MESHOPTIMIZERSCENECONVERTER=%EXCEPT_MSVC2017% ^
-DMAGNUM_WITH_PRIMITIVEIMPORTER=ON ^
-DMAGNUM_WITH_STANFORDSCENECONVERTER=ON ^
-DMAGNUM_WITH_STBIMAGECONVERTER=ON ^
-DMAGNUM_WITH_STBIMAGEIMPORTER=ON ^
-DMAGNUM_WITH_STBRESIZEIMAGECONVERTER=ON ^
-DMAGNUM_WITH_STBTRUETYPEFONT=ON ^
%COMPILER_EXTRA% -G Ninja || exit /b
-DBUILD_DEPRECATED=OFF ^
-DBUILD_STATIC=%BUILD_STATIC% ^
-DWITH_AUDIO=OFF ^
-DWITH_DEBUGTOOLS=OFF ^
-DWITH_GL=ON ^
-DWITH_MESHTOOLS=ON ^
-DWITH_PRIMITIVES=ON ^
-DWITH_SCENEGRAPH=ON ^
-DWITH_SHADERS=ON ^
-DWITH_TEXT=OFF ^
-DWITH_TEXTURETOOLS=ON ^
-DWITH_TRADE=ON ^
-DWITH_VK=OFF ^
-DWITH_SDL2APPLICATION=ON ^
-DWITH_GLFWAPPLICATION=ON ^
-DWITH_WINDOWLESSWGLAPPLICATION=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
cd .. && cd ..
rem Build. Again forcing -DCMAKE_POLICY_VERSION_MINIMUM=3.5 because the
rem pybind11 CMake config files also require just 3.4 now.
rem Build. BUILD_GL_TESTS is enabled just to be sure, it should not be needed
rem by any plugin.
mkdir build && cd build || exit /b
cmake .. ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=%APPVEYOR_BUILD_FOLDER%/deps ^
-DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%/SDL ^
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
-DPYBIND11_PYTHON_VERSION=3.%PYTHON% ^
-DMAGNUM_WITH_PYTHON=ON ^
-DMAGNUM_BUILD_TESTS=ON ^
%COMPILER_EXTRA% %BINDINGS_EXTRA% -G Ninja || exit /b
-DPYBIND11_PYTHON_VERSION=3.6 ^
-DWITH_PYTHON=ON ^
-G Ninja || exit /b
cmake --build . || exit /b
cmake --build . --target install || exit /b
rem Test
set CORRADE_TEST_COLOR=ON
rem On Windows, if an assertion or other issue happens, A DIALOG WINDOWS POPS
rem UP FROM THE CONSOLE. And then, for fucks sake, IT WAITS ENDLESSLY FOR YOU
rem TO CLOSE IT!! Such behavior is utterly stupid in a non-interactive setting
rem such as on this very CI, so I'm setting a timeout to 60 seconds to avoid
rem the CI job being stuck for an hour if an assertion happens. CTest's default rem timeouts is somehow 10M seconds, which is as useful as nothing at all.
ctest -V -E GLTest --timeout 60 || exit /b
rem Verify the setuptools install
cd src/python || exit /b
python setup.py install --root="%APPVEYOR_BUILD_FOLDER%/install" || exit /b
rem Run python tests & gather coverage
rem Run tests & gather coverage
cd ../../../src/python/corrade || exit /b
coverage run -m unittest -v || exit /b
cp .coverage ../.coverage.corrade || exit /b
coverage run -m unittest -v && cp .coverage ../.coverage.corrade || exit /b
cd ../magnum || exit /b
set MAGNUM_SKIP_GL_TESTS=ON
coverage run -m unittest -v || exit /b
cp .coverage ../.coverage.magnum || exit /b
coverage run -m unittest -v && cp .coverage ../.coverage.magnum || exit /b
rem Test docstring validity
cd ../../../doc/python || exit /b
@ -156,6 +97,18 @@ rem python -m doctest -v *.rst || exit /b
rem Upload coverage
cd ../../src/python || exit /b
coverage combine || exit /b
rem TODO: Currently disabled because I can't seem to convince it to relocate
rem the paths via codecov.yml: https://github.com/mosra/magnum-bindings/pull/3
rem codecov -X gcov || exit /b
rem I am unable to convince codecov to relocate paths using codecov.yml so
rem let's do that manually. But that doesn't work either.
powershell -Command "(gc .coverage) -replace 'C:\\\\projects\\\\magnum-bindings\\\\build\\\\src\\\\python\\\\', 'C:\\projects\\magnum-bindings\\src\\python\\' | Out-File -encoding ASCII .coverage" || exit /b
type .coverage
del ..\..\build\src\python\corrade\__init__.py || exit /b
del ..\..\build\src\python\magnum\__init__.py || exit /b
del ..\..\build\src\python\magnum\platform\__init__.py || exit /b
cd ..\..
codecov -X gcov || exit /b
type coverage.xml

143
package/ci/appveyor.yml

@ -5,149 +5,70 @@ environment:
- TARGET: desktop
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_JOB_NAME: windows-msvc2017
PYTHON: 6
PYBIND: 2.3.0
APPVEYOR_JOB_NAME: windows-gl-msvc2017
PYTHON: 36
- TARGET: desktop
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
APPVEYOR_JOB_NAME: windows-msvc2019
# Python 3.7 was removed from 2019 and 2022 images sometimes in 2025
PYTHON: 8
PYBIND: 2.3.0
- TARGET: desktop
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
APPVEYOR_JOB_NAME: windows-msvc2022
PYTHON: 8
PYBIND: 2.9.0 # first supporting MSVC 2022
APPVEYOR_JOB_NAME: windows-gl-msvc2019
PYTHON: 36
- TARGET: desktop
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
APPVEYOR_JOB_NAME: windows-static-msvc2019
BUILD_STATIC: ON
PYTHON: 8
PYBIND: 2.3.0
# The static build puts everything including Sdl2Application together so it
# needs the SDL DLL directory as well. Here also making one relative to
# verify it gets correctly turned into absolute -- the built modules are in
# C:/projects/magnum-bindings/build/src/python, and the DLLs in
# C:/projects/magnum-bindings/SDL/lib/x64
BINDINGS_EXTRA: "-DMAGNUM_PYTHON_BINDINGS_DLL_PATH=C:/projects/magnum-bindings/deps/bin;../../../SDL/lib/x64"
- TARGET: desktop
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
APPVEYOR_JOB_NAME: windows-static-msvc2022
BUILD_STATIC: ON
PYTHON: 8
PYBIND: 2.9.0 # first supporting MSVC 2022
# The static build puts everything including Sdl2Application together so it
# needs the SDL DLL directory as well. Here making the other one relative
# to verify both get correctly turned into absolute -- the built modules
# are in C:/projects/magnum-bindings/build/src/python, and the DLLs in
# C:/projects/magnum-bindings/deps/bin
BINDINGS_EXTRA: "-DMAGNUM_PYTHON_BINDINGS_DLL_PATH=../../../deps/bin;C:/projects/magnum-bindings/SDL/lib/x64"
# clang-cl crashes with pybind11, "Illegal instruction" and
# lld-link: warning: ignoring unknown argument '-flto'
# LLVM ERROR: Associative COMDAT symbol '??0type_error@pybind11@@QEAA@PEBD@Z' does not exist.
# TODO: retry once their changelog says something about clang-cl being fixed
#- TARGET: desktop
#COMPILER: msvc-clang
#APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
#APPVEYOR_JOB_NAME: windows-msvc2019-clang
#PYTHON: 8
#PYBIND: 2.7.0
#- TARGET: desktop
#COMPILER: msvc-clang
#APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
#APPVEYOR_JOB_NAME: windows-msvc2022-clang
#PYTHON: 8
#PYBIND: 2.9.0 # first supporting MSVC 2022
- TARGET: desktop
COMPILER: msvc
# Same reasoning as in Corrade for /EHsc
COMPILER_EXTRA: -DCMAKE_CXX_FLAGS="/permissive- /EHsc" -DCORRADE_MSVC_COMPATIBILITY=OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
APPVEYOR_JOB_NAME: windows-conforming-msvc2019
PYTHON: 8
PYBIND: 2.3.0
- TARGET: desktop
COMPILER: msvc
# Not playing with fire and using /EHsc on 2022 as well
COMPILER_EXTRA: -DCMAKE_CXX_FLAGS="/permissive- /EHsc" -DCORRADE_MSVC_COMPATIBILITY=OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
APPVEYOR_JOB_NAME: windows-conforming-msvc2022
PYTHON: 8
PYBIND: 2.9.0 # first supporting MSVC 2022
PYTHON: 36
- TARGET: desktop-gles
TARGET_GLES2: ON
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_JOB_NAME: windows-gles2-msvc2017
PYTHON: 36
- TARGET: desktop-gles
TARGET_GLES2: ON
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
APPVEYOR_JOB_NAME: windows-gles2-msvc2019
PYTHON: 8
PYBIND: 2.3.0
PYTHON: 36
- TARGET: desktop-gles
TARGET_GLES2: ON
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
APPVEYOR_JOB_NAME: windows-gles2-msvc2022
PYTHON: 8
PYBIND: 2.9.0 # first supporting MSVC 2022
TARGET_GLES2: OFF
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
APPVEYOR_JOB_NAME: windows-gles3-msvc2017
PYTHON: 36
- TARGET: desktop-gles
TARGET_GLES2: OFF
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
APPVEYOR_JOB_NAME: windows-gles3-msvc2019
PYTHON: 8
PYBIND: 2.3.0
- TARGET: desktop-gles
TARGET_GLES2: OFF
COMPILER: msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
APPVEYOR_JOB_NAME: windows-gles3-msvc2022
PYTHON: 8
PYBIND: 2.9.0 # first supporting MSVC 2022
install:
# Ninja. `cinst ninja` started 503ing in late November 2019 and wasn't really
# reliable before either. So install by hand, as that's reliable always.
- IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\ninja-win.zip appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-win.zip
- 7z x ninja-win.zip -oC:/tools
- set PATH=C:/tools;%PATH%
PYTHON: 36
# Codecov uploader
- appveyor DownloadFile https://uploader.codecov.io/latest/windows/codecov.exe -FileName C:/tools/codecov.exe
notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/415ae90928ba0dbd3df4
on_build_success: false
on_build_failure: true
on_build_status_changed: true
install:
- cinst ninja
# pip is in Scripts
- set PATH=C:/tools/ninja;C:/Python3%PYTHON%-x64;C:/Python3%PYTHON%-x64/Scripts;%PATH%
- pip3 install coverage
- set PATH=C:/tools/ninja;C:/Python%PYTHON%-x64;C:/Python%PYTHON%-x64/Scripts;%PATH%
- pip3 install coverage codecov
- IF NOT "%BUILD_STATIC%" == "ON" set BUILD_STATIC=OFF
# The fugly \=/ magic is to replace backward slashes with forward so CMake
# doesn't treat those as escape characters
- IF "%BUILD_STATIC%" == "ON" set "STATIC_PLUGIN_PATH=-DMAGNUM_PLUGINS_DIR=%APPVEYOR_BUILD_FOLDER:\=/%/deps/bin/magnum"
# pybind11. Built in the CI script.
- IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\v%PYBIND%.zip appveyor DownloadFile https://github.com/pybind/pybind11/archive/v%PYBIND%.zip
- 7z x v%PYBIND%.zip
- IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\v2.3.0.zip appveyor DownloadFile https://github.com/pybind/pybind11/archive/v2.3.0.zip
- 7z x v2.3.0.zip
# SDL2
- IF "%TARGET%" == "desktop" IF "%COMPILER:~0,4%" == "msvc" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\SDL2-devel-2.0.9-VC.zip appveyor DownloadFile https://www.libsdl.org/release/SDL2-devel-2.0.9-VC.zip
- IF "%TARGET%" == "desktop" IF "%COMPILER:~0,4%" == "msvc" 7z x SDL2-devel-2.0.9-VC.zip && ren SDL2-2.0.9 SDL
- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\SDL2-devel-2.0.9-VC.zip appveyor DownloadFile http://www.libsdl.org/release/SDL2-devel-2.0.9-VC.zip
- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" 7z x SDL2-devel-2.0.9-VC.zip && ren SDL2-2.0.9 SDL
# GLFW
- IF "%TARGET%" == "desktop" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\glfw-3.2.1.bin.WIN64.zip appveyor DownloadFile https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.bin.WIN64.zip
- IF "%TARGET%" == "desktop" 7z x glfw-3.2.1.bin.WIN64.zip && ren glfw-3.2.1.bin.WIN64 glfw && mkdir deps && mkdir deps\lib && mkdir deps\bin && mkdir deps\include && xcopy /e glfw\include\* deps\include\
- IF "%TARGET%" == "desktop" IF "%COMPILER:~0,4%" == "msvc" copy glfw\lib-vc2015\glfw3.dll deps\bin\ && copy glfw\lib-vc2015\glfw3dll.lib deps\lib\glfw3.lib
# meshoptimizer for MSVC 2022, 2019 and clang-cl; MinGW. MSVC 2017 doesn't work
# with the 2019 build unfortunately, and can't build it because of
# https://github.com/actions/runner-images/issues/3294
- IF "%COMPILER:~0,4%" == "msvc" appveyor DownloadFile https://ci.magnum.graphics/meshoptimizer-0.21-windows-2019-debug.zip && 7z x meshoptimizer-0.21-windows-2019-debug.zip -o%APPVEYOR_BUILD_FOLDER%\deps
- IF "%COMPILER%" == "mingw" appveyor DownloadFile https://ci.magnum.graphics/meshoptimizer-0.21-windows-mingw.zip && 7z x meshoptimizer-0.21-windows-mingw.zip -o%APPVEYOR_BUILD_FOLDER%\deps
- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" copy glfw\lib-vc2015\glfw3.dll deps\bin\ && copy glfw\lib-vc2015\glfw3dll.lib deps\lib\glfw3.lib
build_script:
- IF "%TARGET%" == "desktop" IF "%COMPILER:~0,4%" == "msvc" call package\ci\appveyor-desktop.bat
- IF "%TARGET%" == "desktop" IF "%COMPILER%" == "msvc" call package\ci\appveyor-desktop.bat
- IF "%TARGET%" == "desktop-gles" call package\ci\appveyor-desktop-gles.bat
cache:

499
package/ci/circleci.yml

@ -1,499 +0,0 @@
version: 2.1
orbs:
# Version 3.2.4 is the "new" uploader, but it's a 50 MB Node.js *binary* and
# doesn't work on ARM64 Linux (or ARM Macs, or FreeBSD for that matter) and
# nobody seems to care. Issues opened since Septembe 2021:
# https://github.com/codecov/uploader/issues/347
# https://github.com/codecov/uploader/issues/523
# https://github.com/codecov/uploader/issues/849
# The old 1.1.1 still seems to work even though codecov got removed from pip
# on 2023-04-14.
codecov: codecov/codecov@1.1.1
executors:
ubuntu-18_04:
docker:
- image: ubuntu:bionic-20220427
# As of November 7, 2025, M4 is the default, and the oldest version there is
# 14.3.1.
xcode-14_3:
macos:
xcode: 14.3.1
arm64:
machine:
image: ubuntu-2004:2023.07.1
resource_class: arm.medium
commands:
install-base-linux:
parameters:
extra:
type: string
default: ""
sudo:
type: string
default: ""
steps:
- run:
name: Update apt and install base packages
# Git is needed always for cloning Corrade etc
command: |
<< parameters.sudo >> apt update
if [[ "$CMAKE_CXX_FLAGS" == *"--coverage"* ]]; then export LCOV_PACKAGES="lcov curl"; fi
<< parameters.sudo >> apt install -y git ninja-build $LCOV_PACKAGES << parameters.extra >>
install-base-macos:
parameters:
extra:
type: string
default: ""
steps:
- run:
name: Install base packages
# As usual, homebrew takes five minutes to update and then explodes in
# a spectacular way. How is this acceptable?!
command: |
if [[ "$CMAKE_CXX_FLAGS" == *"--coverage"* ]]; then export LCOV_PACKAGES="lcov"; fi
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake ninja $LCOV_PACKAGES << parameters.extra >>
- run:
name: Uninstall the pyenv crap and install plain python instead
# Otherwise the numpy installed by homebrew is unreachable by actual
# user-side python. THIS ALL USED TO WORK BUT NOT ANYMORE. They
# subsequently added `brew pyenv-sync` in an attempt to fix this trash
# fire, but that damn thing doesn't work at all either. Fuck it, then.
# https://github.com/orgs/Homebrew/discussions/4664
# https://github.com/Homebrew/brew/issues/17563
command: |
HOMEBREW_NO_AUTO_UPDATE=1 brew remove pyenv
HOMEBREW_NO_AUTO_UPDATE=1 brew install python
rm -r ~/.pyenv
install-gcc-4_8:
steps:
- run:
name: Install GCC 4.8
# For some reason, CMake needs a working C compiler, so provice CC as
# well for the case when default gcc isn't installed.
command: |
apt install -y g++-4.8
echo 'export CC=gcc-4.8' >> $BASH_ENV
echo 'export CXX=g++-4.8' >> $BASH_ENV
install-cmake:
parameters:
version:
type: string
sudo:
type: string
default: ""
steps:
- run:
name: Install CMake << parameters.version >>
command: |
version_short=<< parameters.version >>
version_short="${version_short%.*}"
<< parameters.sudo >> apt install -y wget
mkdir -p $HOME/cmake && cd $HOME/cmake
wget -nc --no-check-certificate https://cmake.org/files/v$version_short/cmake-<< parameters.version >>-Linux-x86_64.tar.gz
tar --strip-components=1 -xzf cmake-<< parameters.version >>-Linux-x86_64.tar.gz
echo 'export PATH=$HOME/cmake/bin:$PATH' >> $BASH_ENV
source $BASH_ENV
cmake --version | grep << parameters.version >>
ctest --version | grep << parameters.version >>
install-python-3_6:
# Can't use the python3.6 docker image because there I can't install GCC
# 4.8. Loosely based on https://gist.github.com/monkut/c4c07059444fd06f3f8661e13ccac619
# The deadsnakes PPA no longer supports 16.04, so this repo builds against
# 18.04.
steps:
- run:
name: Install Python 3.6 and numpy
# The software-properties-common need to be installed in order to have
# apt-add-repository. Sigh, adding a repository should be a core
# feature ffs!
#
# Also, "Press ENTER to continue." Are we still in the DOS days?!
#
# Setting up 3.6 as the default is OF COURSE one command more than
# would be acceptable, but am I surprised on this distro?!
command: |
apt install -y software-properties-common
echo -e "\n" | add-apt-repository ppa:deadsnakes/ppa
apt update
apt install -y python3.6 python3.6-dev python3-pip
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 10
python3 --version | grep 3.6
python3 -m pip install pip --upgrade
python3 -m pip install wheel
pip3 install numpy
install-pybind11:
parameters:
version:
type: string
default: "2.3.0"
steps:
- run:
name: Install Pybind11 << parameters.version >>
command: |
cd $HOME
wget --no-clobber https://github.com/pybind/pybind11/archive/v<< parameters.version >>.tar.gz
tar -xzf v<< parameters.version >>.tar.gz
cd pybind11-<< parameters.version >>
mkdir -p build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/pybind11 \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DPYBIND11_TEST=OFF \
-G Ninja
ninja install
install-swiftshader-gles:
parameters:
build:
type: string
steps:
- run:
name: Install SwiftShader GLES
# Zip from https://github.com/mosra/magnum-ci/tree/swiftshader and
# self-hosted because GH Actions would make it too simple for people if
# you could just download the artifacts directly, right? RIGHT?
command: |
mkdir -p $HOME/swiftshader && cd $HOME/swiftshader
wget https://ci.magnum.graphics/swiftshader-gles-r5904.14dcbed947-<< parameters.build >>.zip
unzip swiftshader-gles-r5904.14dcbed947-<< parameters.build >>.zip
install-meshoptimizer:
steps:
- run:
name: Install meshoptimizer
# few commits after 0.14 with a fix for old Apple Clang
command: |
export MESHOPTIMIZER_VERSION=97c52415c6d29f297a76482ddde22f739292446d
mkdir -p $HOME/meshoptimizer && cd $HOME/meshoptimizer
wget -nc --no-check-certificate https://github.com/zeux/meshoptimizer/archive/$MESHOPTIMIZER_VERSION.tar.gz
tar --strip-components=1 -xzf $MESHOPTIMIZER_VERSION.tar.gz
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-G Ninja
ninja install
build:
parameters:
script:
type: string
steps:
- run:
name: Install coverage
command: pip3 install coverage
- checkout
- run:
name: Build & test
command: |
if [ "$BUILD_STATIC" != "ON" ]; then export BUILD_STATIC=OFF; fi
if [ "$BUILD_DEPRECATED" != "OFF" ]; then export BUILD_DEPRECATED=ON; fi
./package/ci/<< parameters.script >>
# Official docs say "token not needed for public repos", in reality not using
# the token is "extremely flakey". What's best is that if the upload fails,
# the damn thing exits with a success error code, and nobody cares:
# https://github.com/codecov/codecov-circleci-orb/issues/139
upload-codecov:
parameters:
file:
type: string
steps:
# Second best thing is that the codecov/upload helper takes a `token`
# parameter. But the token parameter is an ENVIRONMENT VARIABLE NAME!! So
# one just *can't* pass the token there. It got changed arbitrarily in
# https://github.com/codecov/codecov-circleci-orb/pull/93 "because
# CircleCI docs suggested so", yet all codecov docs suggest just
# commiting that token directly to the YML files because "it's fine". So
# if it's fine, why do I have to suffer like this?!
- run:
name: Set codecov upload token because everything is a dumpster fire
# An icing on the cake is that CircleCI commands don't allow setting
# `environment` for `commands`, only for `jobs`, so I have to do that
# via bash, and because the environment isn't passsed from a run to
# run, use the BASH_ENV hack. Mmm. Technology.
command: |
echo 'export CODECOV_TOKEN=ade9e2f1-d6d7-45cb-a292-c5bb1ad45be9' >> "$BASH_ENV"
- codecov/upload:
file: << parameters.file >>
lcov:
parameters:
extra:
type: string
default: ""
steps:
- run:
name: Collect code coverage
# Keep in sync with PKBUILD-coverage, please
command: |
lcov << parameters.extra >> --directory . --capture --output-file coverage.info > /dev/null
lcov << parameters.extra >> --extract coverage.info "*/src/python/*" "*/src/Corrade/*" "*/src/Magnum/*" --output-file coverage.info > /dev/null
cd src/python && coverage combine
- upload-codecov:
file: coverage.info
jobs:
linux-gl:
executor: ubuntu-18_04
environment:
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: GLX
# It crashes (OOM, probably) with the default setting
NINJA_JOBS: -j2
steps:
# libidn11 needed by CMake
- install-base-linux:
extra: libidn11 libgl1-mesa-dev libsdl2-dev libglfw3-dev
- install-gcc-4_8
- install-cmake:
version: "3.5.2"
- install-python-3_6
- install-pybind11
- install-meshoptimizer
- build:
script: unix-desktop.sh
- lcov:
extra: --gcov-tool /usr/bin/gcov-4.8
linux-arm64:
executor: arm64
environment:
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: GLX
steps:
# Not installing the old GCC 4.8 and CMake 3.5 to speed up. These are
# tested more than enough on other jobs. Machine executors need sudo.
- install-base-linux:
extra: gcc cmake libgl1-mesa-dev libsdl2-dev libglfw3-dev libpython3-dev
sudo: sudo
# 2.3.0 doesn't work with Python 3.11, this one should
- install-pybind11:
version: "2.11.1"
- run:
name: Install numpy
command: pip3 install numpy
- install-meshoptimizer
- build:
script: unix-desktop.sh
- lcov
linux-gles2:
executor: ubuntu-18_04
environment:
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: EGL
# STUPID yml interprets unquoted ON as a boolean
TARGET_GLES2: "ON"
# It crashes (OOM, probably) with the default setting
NINJA_JOBS: -j2
steps:
# libidn11 needed by CMake
- install-base-linux:
extra: libidn11 libsdl2-dev libglfw3-dev wget unzip
- install-gcc-4_8
- install-cmake:
version: "3.5.2"
- install-python-3_6
- install-pybind11
- install-meshoptimizer
- install-swiftshader-gles:
build: ubuntu-18.04
- build:
script: unix-desktop-gles.sh
- lcov:
extra: --gcov-tool /usr/bin/gcov-4.8
linux-gles3:
executor: ubuntu-18_04
environment:
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: EGL
# STUPID yml interprets unquoted OFF as a boolean
TARGET_GLES2: "OFF"
# It crashes (OOM, probably) with the default setting
NINJA_JOBS: -j2
steps:
# libidn11 needed by CMake
- install-base-linux:
extra: libidn11 libsdl2-dev libglfw3-dev wget unzip
- install-gcc-4_8
- install-cmake:
version: "3.5.2"
- install-python-3_6
- install-pybind11
- install-meshoptimizer
- install-swiftshader-gles:
build: ubuntu-18.04
- build:
script: unix-desktop-gles.sh
- lcov:
extra: --gcov-tool /usr/bin/gcov-4.8
linux-static:
executor: ubuntu-18_04
environment:
# STUPID yml interprets unquoted ON as a boolean
# https://stackoverflow.com/questions/53648244/specifying-the-string-value-yes-in-a-yaml-property
BUILD_STATIC: "ON"
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: GLX
# It crashes (OOM, probably) with the default setting
NINJA_JOBS: -j2
steps:
# libidn11 needed by CMake
- install-base-linux:
extra: libidn11 libsdl2-dev libglfw3-dev
- install-gcc-4_8
- install-cmake:
version: "3.5.2"
- install-python-3_6
- install-pybind11
- install-meshoptimizer
- build:
script: unix-desktop.sh
- lcov:
extra: --gcov-tool /usr/bin/gcov-4.8
linux-nondeprecated:
executor: ubuntu-18_04
environment:
# STUPID yml interprets unquoted OFF as a boolean
BUILD_DEPRECATED: "OFF"
CMAKE_CXX_FLAGS: --coverage
PLATFORM_GL_API: GLX
# It crashes (OOM, probably) with the default setting
NINJA_JOBS: -j2
steps:
# libidn11 needed by CMake
- install-base-linux:
extra: libidn11 libgl1-mesa-dev libsdl2-dev libglfw3-dev
- install-gcc-4_8
- install-cmake:
version: "3.5.2"
- install-python-3_6
- install-pybind11
- install-meshoptimizer
- build:
script: unix-desktop.sh
- lcov:
extra: --gcov-tool /usr/bin/gcov-4.8
macos-gl:
executor: xcode-14_3
environment:
# Make libc++ remove transitive includes, both for faster build times and
# to detect if we're missing a transitive include. Works with libc++ 16+,
# which is used by Xcode 15 (i.e., will get used on the next CircleCI
# executor update).
CMAKE_CXX_FLAGS: --coverage -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES
PLATFORM_GL_API: CGL
steps:
- install-base-macos:
extra: sdl2 glfw wget numpy pybind11
- install-meshoptimizer
- build:
script: unix-desktop.sh
# The 14.3 image seems to have the new lcov, which is very picky and throws
# errors about a ton of little things, 14.0.1 and older didn't
- lcov:
extra: --ignore-errors inconsistent
macos-gles3:
executor: xcode-14_3
environment:
# Make libc++ remove transitive includes, both for faster build times and
# to detect if we're missing a transitive include. Works with libc++ 16+,
# which is used by Xcode 15 (i.e., will get used on the next CircleCI
# executor update).
CMAKE_CXX_FLAGS: --coverage -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES
PLATFORM_GL_API: EGL
# STUPID yml interprets unquoted OFF as a boolean
TARGET_GLES2: "OFF"
steps:
- install-base-macos:
extra: sdl2 glfw wget numpy pybind11
- install-swiftshader-gles:
build: macos12-arm64
- install-meshoptimizer
- build:
script: unix-desktop-gles.sh
# The 14.3 image seems to have the new lcov, which is very picky and throws
# errors about a ton of little things, 14.0.1 and older didn't
- lcov:
extra: --ignore-errors inconsistent
macos-static:
executor: xcode-14_3
environment:
# STUPID yml interprets unquoted ON as a boolean
BUILD_STATIC: "ON"
# Make libc++ remove transitive includes, both for faster build times and
# to detect if we're missing a transitive include. Works with libc++ 16+,
# which is used by Xcode 15 (i.e., will get used on the next CircleCI
# executor update).
CMAKE_CXX_FLAGS: --coverage -D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES
PLATFORM_GL_API: CGL
steps:
- install-base-macos:
extra: sdl2 glfw wget numpy pybind11
- install-meshoptimizer
- build:
script: unix-desktop.sh
# The 14.3 image seems to have the new lcov, which is very picky and throws
# errors about a ton of little things, 14.0.1 and older didn't
- lcov:
extra: --ignore-errors inconsistent
workflows:
version: 2
build:
# While there's no actual execution or data dependency between the jobs,
# this is done in order to reduce unnecessary credit usage. The GL and
# non-deprecated Linux builds are taken as the main sanity checks. Only if
# they pass, the rest of the jobs gets gradually executed, with further
# dependencies especially for the macOS jobs that take the most credits.
jobs:
- linux-gl
- linux-nondeprecated
- linux-arm64:
requires:
- linux-gl
- linux-nondeprecated
- linux-gles2:
requires:
- linux-gl
- linux-nondeprecated
- linux-gles3:
requires:
- linux-gl
- linux-nondeprecated
- linux-static:
requires:
- linux-gl
- linux-nondeprecated
- macos-gl:
requires:
- linux-arm64
- linux-gl
- linux-nondeprecated
- macos-gles3:
requires:
- linux-gles3
- macos-gl
- macos-static:
requires:
- linux-static
- macos-gl

8
package/ci/codecov.yml

@ -1,9 +1,9 @@
fixes:
# The src/python/magnum/__init__.py is copied to cmake's build dir together
# with setup.py next to the C++ binaries and the test is done from here.
# with # setup.py next to the C++ binaries and the test is done from here.
# Python's coverage.py reports an absolute path to it, which means a simple
# "build/src/python/::src/python/" won't suffice. This is hardcoded to CircleCI
# "build/src/python/::src/python/" won't suffice. This is hardcoded to Travis
# Linux / macOS and AppVeyor build paths so let's hope these won't change.
- "/root/project/build/src/python/::src/python/"
- "/Users/distiller/project/build/src/python/::src/python/"
- "/home/travis/build/mosra/magnum-bindings/build/src/python/::src/python/"
- "/Users/travis/build/mosra/magnum-bindings/build/src/python/::src/python/"
- "C:/projects/magnum-bindings/build/src/python/::src/python/"

13
package/ci/setup-pybind11.sh

@ -0,0 +1,13 @@
set -e
wget --no-clobber https://github.com/pybind/pybind11/archive/v2.3.0.tar.gz && tar -xzf v2.3.0.tar.gz
cd pybind11-2.3.0
mkdir -p build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/pybind11 \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DPYBIND11_TEST=OFF \
-G Ninja
ninja install

80
package/ci/travis-desktop-gles.sh

@ -0,0 +1,80 @@
#!/bin/bash
set -ev
# Corrade
git clone --depth 1 git://github.com/mosra/corrade.git
cd corrade
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_DEPRECATED=$BUILD_DEPRECATED \
-DWITH_INTERCONNECT=OFF \
-DWITH_PLUGINMANAGER=ON \
-DWITH_TESTSUITE=OFF \
-G Ninja
ninja install
cd ../..
# Magnum
git clone --depth 1 git://github.com/mosra/magnum.git
cd magnum
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DEGL_LIBRARY=$HOME/swiftshader/libEGL.so \
-DOPENGLES2_LIBRARY=$HOME/swiftshader/libGLESv2.so \
-DOPENGLES3_LIBRARY=$HOME/swiftshader/libGLESv2.so \
-DCMAKE_INSTALL_RPATH=$HOME/swiftshader \
-DTARGET_GLES=ON \
-DTARGET_GLES2=$TARGET_GLES2 \
-DWITH_AUDIO=OFF \
-DWITH_DEBUGTOOLS=OFF \
-DWITH_GL=ON \
-DWITH_MESHTOOLS=ON \
-DWITH_PRIMITIVES=ON \
-DWITH_SCENEGRAPH=ON \
-DWITH_SHADERS=ON \
-DWITH_TEXT=OFF \
-DWITH_TEXTURETOOLS=OFF \
-DWITH_TRADE=ON \
-DWITH_VK=OFF \
-DWITH_WINDOWLESSEGLAPPLICATION=ON \
-DBUILD_DEPRECATED=OFF \
-G Ninja
ninja install
cd ../..
# Build the thing
mkdir build && cd build
cmake .. \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_PREFIX_PATH=$HOME/pybind11 \
-DEGL_LIBRARY=$HOME/swiftshader/libEGL.so \
-DOPENGLES2_LIBRARY=$HOME/swiftshader/libGLESv2.so \
-DOPENGLES3_LIBRARY=$HOME/swiftshader/libGLESv2.so \
-DCMAKE_INSTALL_RPATH=$HOME/swiftshader \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DWITH_PYTHON=ON \
-G Ninja
ninja
# Verify the setuptools install
cd src/python
python3 setup.py install --root="$TRAVIS_BUILD_DIR/install" --prefix=/usr
# Run tests & gather coverage
cd ../../../src/python/corrade
coverage run -m unittest -v && cp .coverage ../.coverage.corrade
cd ../magnum
coverage run -m unittest -v && cp .coverage ../.coverage.magnum
# Test docstring validity
cd ../../../doc/python
PYTHONPATH="$TRAVIS_BUILD_DIR/build/src/python" python3 -m doctest -v *.rst

74
package/ci/travis-desktop.sh

@ -0,0 +1,74 @@
#!/bin/bash
set -ev
# Corrade
git clone --depth 1 git://github.com/mosra/corrade.git
cd corrade
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_DEPRECATED=OFF \
-DBUILD_STATIC=$BUILD_STATIC \
-DWITH_INTERCONNECT=OFF \
-DWITH_PLUGINMANAGER=ON \
-DWITH_TESTSUITE=OFF \
-G Ninja
ninja install
cd ../..
# Magnum
git clone --depth 1 git://github.com/mosra/magnum.git
cd magnum
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_DEPRECATED=OFF \
-DBUILD_STATIC=$BUILD_STATIC \
-DWITH_AUDIO=OFF \
-DWITH_DEBUGTOOLS=OFF \
-DWITH_GL=ON \
-DWITH_MESHTOOLS=ON \
-DWITH_PRIMITIVES=ON \
-DWITH_SCENEGRAPH=ON \
-DWITH_SHADERS=ON \
-DWITH_TEXT=OFF \
-DWITH_TEXTURETOOLS=OFF \
-DWITH_TRADE=ON \
-DWITH_VK=OFF \
-DWITH_GLFWAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_WINDOWLESS${PLATFORM_GL_API}APPLICATION=ON \
-G Ninja
ninja install
cd ../..
# Build the thing
mkdir build && cd build
cmake .. \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_PREFIX_PATH=$HOME/pybind11 \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DWITH_PYTHON=ON \
-G Ninja
ninja
# Verify the setuptools install
cd src/python
python3 setup.py install --root="$TRAVIS_BUILD_DIR/install" --prefix=/usr
# Run tests & gather coverage
cd ../../../src/python/corrade
coverage run -m unittest -v && cp .coverage ../.coverage.corrade
cd ../magnum
MAGNUM_SKIP_GL_TESTS=ON coverage run -m unittest -v && cp .coverage ../.coverage.magnum
# Test docstring validity
cd ../../../doc/python
PYTHONPATH="$TRAVIS_BUILD_DIR/build/src/python" python3 -m doctest -v *.rst

146
package/ci/travis.yml

@ -0,0 +1,146 @@
addons:
apt:
packages:
- g++-4.8
- libgl1-mesa-dev
- ninja-build
- lcov
- libsdl2-dev
- libglfw3-dev
matrix:
include:
- language: python
python: 3.6
os: linux
dist: xenial
compiler: gcc
env:
- JOBID=linux-gl
- TARGET=desktop
- LCOV_EXTRA_OPTS="--gcov-tool /usr/bin/gcov-4.8"
- language: python
python: 3.6
os: linux
dist: xenial
compiler: gcc
env:
- JOBID=linux-gles2
- TARGET=desktop-gles
- TARGET_GLES2=ON
- CMAKE_CXX_FLAGS="--coverage"
- LCOV_EXTRA_OPTS="--gcov-tool /usr/bin/gcov-4.8"
addons:
apt:
packages:
- g++-4.8
- ninja-build
- lcov
- libsdl2-dev
- libglfw3-dev
- language: python
python: 3.6
os: linux
dist: xenial
compiler: gcc
env:
- JOBID=linux-gles3
- TARGET=desktop-gles
- TARGET_GLES2=OFF
- CMAKE_CXX_FLAGS="--coverage"
- LCOV_EXTRA_OPTS="--gcov-tool /usr/bin/gcov-4.8"
addons:
apt:
packages:
- g++-4.8
- ninja-build
- lcov
- libsdl2-dev
- libglfw3-dev
- language: python
python: 3.6
os: linux
dist: xenial
compiler: gcc
env:
- JOBID=linux-static
- TARGET=desktop
- BUILD_STATIC=ON
- LCOV_EXTRA_OPTS="--gcov-tool /usr/bin/gcov-4.8"
- language: cpp
os: osx
compiler: clang
env:
- JOBID=macos-gl
- TARGET=desktop
- language: cpp
os: osx
compiler: clang
env:
- JOBID=macos-static
- TARGET=desktop
- BUILD_STATIC=ON
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/00ec7a9066bb0fec98f3
on_success: change
on_failure: always
on_start: never
cache:
directories:
- $HOME/swiftshader
- $HOME/cmake
- $HOME/pybind11
install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export CXX=g++-4.8; fi
- if [ "$BUILD_STATIC" != "ON" ]; then export BUILD_STATIC=OFF; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ] && ( [ "$TARGET" == "desktop" ] || [ "$TARGET" == "desktop-sanitizers" ] ); then export PLATFORM_GL_API=GLX; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop-gles" ]; then export PLATFORM_GL_API=EGL; fi
# Download CMake 3.1.3 to ensure we're still compatible with it (Travis has
# 3.9 since December 2017). Also, the PATH setting can't be cached, so it's
# separate (bit me two times already). Android needs CMake 3.7, but
# https://gitlab.kitware.com/cmake/cmake/issues/17253 is fixed in 3.9.2, so
# grab that. FindVulkan is since 3.7, in that case just use the system package.
- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ ! -e "$HOME/cmake/bin" ]; then cd $HOME ; wget -nc --no-check-certificate https://cmake.org/files/v3.1/cmake-3.1.3-Linux-x86_64.tar.gz && mkdir -p cmake && cd cmake && tar --strip-components=1 -xzf ../cmake-3.1.3-Linux-x86_64.tar.gz && cd $TRAVIS_BUILD_DIR ; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PATH=$HOME/cmake/bin:$PATH && cmake --version; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja; fi
# Code coverage of python bindings
- if [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ]; then pip3 install coverage codecov; fi
# pybind11 (cached). On macOS the version 2.3.0 needs a brew update, the stale
# Travis image has just 2.2.4.
- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ ! -e "$HOME/pybind11/bin" ]; then $TRAVIS_BUILD_DIR/package/ci/setup-pybind11.sh; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install pybind11; fi
# SDL and GLFW on macOS
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install sdl2 glfw; fi
# numpy on macOS -- probably because we updated Homebrew to install new pybind
# (and thus python as well, apparently), the preinstalled numpy is no longer
# visible.
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew upgrade numpy; fi
# SwiftShader on Linux (cached). Taken from Chromium snapshot 587878
# (swiftshader-bin Arch package).
- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$TARGET" == "desktop-gles" ] && [ ! -e "$HOME/swiftshader/libEGL.so" ]; then cd $HOME ; wget https://ci.magnum.graphics/swiftshader-chromium-587878.tar.gz && mkdir -p swiftshader && cd swiftshader && tar -xzf ../swiftshader-chromium-587878.tar.gz && cd $TRAVIS_BUILD_DIR ; fi
# lcov on macOS
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install lcov; fi
script:
- if [ "$TARGET" == "desktop" ] && ( [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ] ); then ./package/ci/travis-desktop.sh; fi
- if [ "$TARGET" == "desktop-gles" ] && ( [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ] ); then ./package/ci/travis-desktop-gles.sh; fi
# Travis somehow is not able to gather all output, try to force it using this
- sync
after_success:
# Keep in sync with package/archlinux/PKGBUILD-coverage, please
- if [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ]; then lcov $LCOV_EXTRA_OPTS --directory . --capture --output-file coverage.info > /dev/null; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ]; then lcov $LCOV_EXTRA_OPTS --extract coverage.info "*/src/python/*" "*/src/Corrade/*" "*/src/Magnum/*" --output-file coverage.info; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ] || [ "$TRAVIS_OS_NAME" == "osx" ]; then cd src/python && coverage combine && codecov -X gcov; fi

117
package/ci/unix-desktop-gles.sh

@ -1,117 +0,0 @@
#!/bin/bash
set -ev
# Corrade
git clone --depth 1 https://github.com/mosra/corrade.git
cd corrade
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DCORRADE_WITH_INTERCONNECT=OFF \
-DCORRADE_WITH_PLUGINMANAGER=ON \
-DCORRADE_WITH_TESTSUITE=ON \
-G Ninja
ninja install
cd ../..
# Magnum
git clone --depth 1 https://github.com/mosra/magnum.git
cd magnum
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="$HOME/swiftshader;$HOME/pybind11" \
-DCMAKE_INSTALL_RPATH="$HOME/deps/lib;$HOME/swiftshader/lib" \
-DMAGNUM_TARGET_GLES=ON \
-DMAGNUM_TARGET_GLES2=$TARGET_GLES2 \
-DMAGNUM_WITH_AUDIO=OFF \
-DMAGNUM_WITH_DEBUGTOOLS=OFF \
-DMAGNUM_WITH_GL=ON \
-DMAGNUM_WITH_MATERIALTOOLS=ON \
-DMAGNUM_WITH_MESHTOOLS=ON \
-DMAGNUM_WITH_PRIMITIVES=ON \
-DMAGNUM_WITH_SCENEGRAPH=ON \
-DMAGNUM_WITH_SCENETOOLS=ON \
-DMAGNUM_WITH_SHADERS=ON \
-DMAGNUM_WITH_SHADERTOOLS=OFF \
-DMAGNUM_WITH_TEXT=ON \
-DMAGNUM_WITH_TEXTURETOOLS=OFF \
-DMAGNUM_WITH_TRADE=ON \
-DMAGNUM_WITH_VK=OFF \
-DMAGNUM_WITH_WINDOWLESSEGLAPPLICATION=ON \
-DMAGNUM_WITH_ANYIMAGEIMPORTER=ON \
-DMAGNUM_WITH_ANYSCENECONVERTER=ON \
-DMAGNUM_WITH_ANYSCENEIMPORTER=ON \
-DMAGNUM_WITH_TGAIMPORTER=ON \
-G Ninja
ninja install
cd ../..
# Magnum Plugins
git clone --depth 1 https://github.com/mosra/magnum-plugins.git
cd magnum-plugins
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Release \
`# StanfordSceneConverter uses MeshTools which rely on GL which looks` \
`# for OpenGLES. And the RPATH entry needs to be there as well,` \
`# otherwise it won't load.` \
-DCMAKE_PREFIX_PATH=$HOME/swiftshader \
-DCMAKE_INSTALL_RPATH="$HOME/deps/lib;$HOME/swiftshader/lib" \
-DMAGNUM_BUILD_STATIC=$BUILD_STATIC \
-DMAGNUM_WITH_BCDECIMAGECONVERTER=ON \
-DMAGNUM_WITH_DDSIMPORTER=ON \
-DMAGNUM_WITH_ETCDECIMAGECONVERTER=ON \
-DMAGNUM_WITH_GLTFIMPORTER=ON \
-DMAGNUM_WITH_GLTFSCENECONVERTER=ON \
-DMAGNUM_WITH_KTXIMAGECONVERTER=ON \
-DMAGNUM_WITH_MESHOPTIMIZERSCENECONVERTER=ON \
-DMAGNUM_WITH_PRIMITIVEIMPORTER=ON \
-DMAGNUM_WITH_STANFORDSCENECONVERTER=ON \
-DMAGNUM_WITH_STBIMAGECONVERTER=ON \
-DMAGNUM_WITH_STBIMAGEIMPORTER=ON \
-DMAGNUM_WITH_STBRESIZEIMAGECONVERTER=ON \
-DMAGNUM_WITH_STBTRUETYPEFONT=ON \
-G Ninja
ninja install
cd ../..
# Build the thing
mkdir build && cd build
cmake .. \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_PREFIX_PATH="$HOME/swiftshader;$HOME/pybind11" \
-DCMAKE_INSTALL_RPATH="$HOME/deps/lib;$HOME/swiftshader/lib" \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DMAGNUM_WITH_PYTHON=ON \
-DMAGNUM_BUILD_TESTS=ON \
-G Ninja
ninja $NINJA_JOBS
CORRADE_TEST_COLOR=ON ctest -V
# Verify the setuptools install. Not using $CIRCLE_WORKING_DIRECTORY because
# it's ~ and that's not correctly expanded always.
cd src/python
python3 setup.py install --root="$(pwd)/../../install" --prefix=/usr
# Run tests & gather coverage
cd ../../../src/python/corrade
coverage run -m unittest -v
cp .coverage ../.coverage.corrade
cd ../magnum
coverage run -m unittest -v
cp .coverage ../.coverage.magnum
# Test docstring validity
cd ../../../doc/python
# I would use $CIRCLE_WORKING_DIRECTORY, but that's ~ and that's not expanded
# here for some reason
PYTHONPATH="$(pwd)/../../build/src/python" python3 -m doctest -v *.rst

122
package/ci/unix-desktop.sh

@ -1,122 +0,0 @@
#!/bin/bash
set -ev
# Corrade
git clone --depth 1 https://github.com/mosra/corrade.git
cd corrade
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DMAGNUM_BUILD_DEPRECATED=$BUILD_DEPRECATED \
-DCORRADE_BUILD_STATIC=$BUILD_STATIC \
-DCORRADE_WITH_INTERCONNECT=OFF \
-DCORRADE_WITH_PLUGINMANAGER=ON \
-DCORRADE_WITH_TESTSUITE=ON \
-G Ninja
ninja install
cd ../..
# Magnum
git clone --depth 1 https://github.com/mosra/magnum.git
cd magnum
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DMAGNUM_BUILD_DEPRECATED=$BUILD_DEPRECATED \
-DMAGNUM_BUILD_STATIC=$BUILD_STATIC \
-DMAGNUM_WITH_AUDIO=OFF \
-DMAGNUM_WITH_DEBUGTOOLS=OFF \
-DMAGNUM_WITH_GL=ON \
-DMAGNUM_WITH_MATERIALTOOLS=ON \
-DMAGNUM_WITH_MESHTOOLS=ON \
-DMAGNUM_WITH_PRIMITIVES=ON \
-DMAGNUM_WITH_SCENEGRAPH=ON \
-DMAGNUM_WITH_SCENETOOLS=ON \
-DMAGNUM_WITH_SHADERS=ON \
-DMAGNUM_WITH_SHADERTOOLS=OFF \
-DMAGNUM_WITH_TEXT=ON \
-DMAGNUM_WITH_TEXTURETOOLS=OFF \
-DMAGNUM_WITH_TRADE=ON \
-DMAGNUM_WITH_VK=OFF \
-DMAGNUM_WITH_GLFWAPPLICATION=ON \
-DMAGNUM_WITH_SDL2APPLICATION=ON \
-DMAGNUM_WITH_WINDOWLESS${PLATFORM_GL_API}APPLICATION=ON \
-DMAGNUM_WITH_ANYIMAGEIMPORTER=ON \
-DMAGNUM_WITH_ANYSCENECONVERTER=ON \
-DMAGNUM_WITH_ANYSCENEIMPORTER=ON \
-DMAGNUM_WITH_TGAIMPORTER=ON \
-G Ninja
# In case of a static build there's no way for the test to know the plugin
# install directory so we have to hardcode it
if [ "$BUILD_STATIC" == "ON" ]; then
cmake . -DMAGNUM_PLUGINS_DIR=$HOME/deps/lib/magnum
fi
ninja install
cd ../..
# Magnum Plugins
git clone --depth 1 https://github.com/mosra/magnum-plugins.git
cd magnum-plugins
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_INSTALL_RPATH=$HOME/deps/lib \
-DCMAKE_BUILD_TYPE=Release \
-DMAGNUM_BUILD_STATIC=$BUILD_STATIC \
-DMAGNUM_WITH_BCDECIMAGECONVERTER=ON \
-DMAGNUM_WITH_DDSIMPORTER=ON \
-DMAGNUM_WITH_ETCDECIMAGECONVERTER=ON \
-DMAGNUM_WITH_GLTFIMPORTER=ON \
-DMAGNUM_WITH_GLTFSCENECONVERTER=ON \
-DMAGNUM_WITH_KTXIMAGECONVERTER=ON \
-DMAGNUM_WITH_MESHOPTIMIZERSCENECONVERTER=ON \
-DMAGNUM_WITH_PRIMITIVEIMPORTER=ON \
-DMAGNUM_WITH_STANFORDSCENECONVERTER=ON \
-DMAGNUM_WITH_STBIMAGECONVERTER=ON \
-DMAGNUM_WITH_STBIMAGEIMPORTER=ON \
-DMAGNUM_WITH_STBRESIZEIMAGECONVERTER=ON \
-DMAGNUM_WITH_STBTRUETYPEFONT=ON \
-G Ninja
ninja install
cd ../..
# Build the thing
mkdir build && cd build
cmake .. \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_INSTALL_PREFIX=$HOME/deps \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_PREFIX_PATH=$HOME/pybind11 \
-DPYBIND11_PYTHON_VERSION=3.6 \
-DMAGNUM_WITH_PYTHON=ON \
-DMAGNUM_BUILD_TESTS=ON \
-G Ninja
ninja $NINJA_JOBS
CORRADE_TEST_COLOR=ON ctest -V
# Verify the setuptools install. Not using $CIRCLE_WORKING_DIRECTORY because
# it's ~ and that's not correctly expanded always.
cd src/python
python3 setup.py install --root="$(pwd)/../../install" --prefix=/usr
# Run tests & gather coverage
cd ../../../src/python/corrade
coverage run -m unittest -v
cp .coverage ../.coverage.corrade
cd ../magnum
MAGNUM_SKIP_GL_TESTS=ON coverage run -m unittest -v
cp .coverage ../.coverage.magnum
# Test docstring validity
cd ../../../doc/python
# I would use $CIRCLE_WORKING_DIRECTORY, but that's ~ and that's not expanded
# here for some reason
PYTHONPATH="$(pwd)/../../build/src/python" python3 -m doctest -v *.rst

12
package/git/README.md

@ -1,12 +0,0 @@
This dir is used by `src/*/CMakeLists.txt` to run `git describe --match "v*"`.
Because, if it would be run in that directory, on Windows the `--match "v*"`
would get expanded to the `version.h.cmake` file there, causing Git to
obviously not find any such tag. The reason is probably that on Windows the
wildcard expansion is done on the application side and not by the shell, thus
being performed even though CMake docs say `execute_process()` doesn't involve
a shell. This directory is thus dedicated for that operation, *guaranteed* to
never contain any file starting with `v` (or `V` for that matter because,
again, HELLO WINDOWS).
No matter what you do, DON'T put any files starting with `v` or `V` here, or
hell breaks loose again.

24
package/homebrew/magnum-bindings.rb

@ -1,30 +1,20 @@
class MagnumBindings < Formula
desc "`Bindings for the Magnum C++11 graphics engine"
desc "`Bindings for the Magnum C++11/C++14 graphics engine"
homepage "https://magnum.graphics"
# git describe origin/master, except the `v` prefix
version "2020.06-444-gca5328a"
# Clone instead of getting an archive to have tags for version.h generation
url "https://github.com/mosra/magnum-bindings.git", revision: version.to_str().rpartition('g')[2]
head "https://github.com/mosra/magnum-bindings.git"
# url "https://github.com/mosra/magnum-plugins/archive/v2019.01.tar.gz"
# wget https://github.com/mosra/magnum-plugins/archive/v2019.01.tar.gz -O - | sha256sum
# sha256 "d3adadc5b6d4f2e5061608d67f0c7fa07f0dd078bab4672dc5604ddbcd11ca80"
head "git://github.com/mosra/magnum-bindings.git"
depends_on "cmake" => :build
depends_on "cmake"
depends_on "python"
depends_on "python-setuptools" => :build
depends_on "magnum"
depends_on "pybind11" => :build
def install
system "mkdir build"
cd "build" do
system "cmake",
*std_cmake_args,
# Without this, ARM builds will try to look for dependencies in
# /usr/local/lib and /usr/lib (which are the default locations) instead
# of /opt/homebrew/lib which is dedicated for ARM binaries. Please
# complain to Homebrew about this insane non-obvious filesystem layout.
"-DCMAKE_INSTALL_NAME_DIR:STRING=#{lib}",
"-DMAGNUM_WITH_PYTHON=ON",
".."
system "cmake", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_INSTALL_PREFIX=#{prefix}", "-DWITH_PYTHON=ON", ".."
system "cmake", "--build", "."
system "cmake", "--build", ".", "--target", "install"
cd "src/python" do

7
package/sync-modules.sh

@ -1,7 +0,0 @@
#!/bin/bash
set -e
dir=$(dirname "$0")
cp $dir/../../corrade/modules/FindCorrade.cmake $dir/../modules/
cp $dir/../../magnum/modules/FindMagnum.cmake $dir/../modules/

8
src/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,8 +23,7 @@
# DEALINGS IN THE SOFTWARE.
#
# On MSVC remove /W3, as we are replacing it with /W4. Could be removed as of
# 3.15 with this: https://cmake.org/cmake/help/latest/policy/CMP0092.html
# On MSVC remove /W3, as we are replacing it with /W4
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
@ -43,7 +41,7 @@ set_directory_properties(PROPERTIES
add_subdirectory(Corrade)
add_subdirectory(Magnum)
if(MAGNUM_WITH_PYTHON)
if(WITH_PYTHON)
add_subdirectory(python)
endif()

20
src/Corrade/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,17 +23,8 @@
# DEALINGS IN THE SOFTWARE.
#
# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER
# property that would have to be set on each target separately.
set(CMAKE_FOLDER "Corrade/Python")
if(MAGNUM_WITH_PYTHON)
add_custom_target(CorradePython SOURCES PythonBindings.h)
install(FILES PythonBindings.h DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR})
endif()
add_subdirectory(Containers)
if(Corrade_PluginManager_FOUND)
add_subdirectory(PluginManager)
if(WITH_PYTHON)
add_custom_target(CorradePython SOURCES Python.h)
set_target_properties(CorradePython PROPERTIES FOLDER "Corrade/Python")
install(FILES Python.h DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR})
endif()

15
src/Corrade/Containers/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,12 +23,8 @@
# DEALINGS IN THE SOFTWARE.
#
if(MAGNUM_WITH_PYTHON)
set(CorradeContainersPython_HEADERS
OptionalPythonBindings.h
PythonBindings.h
StridedArrayViewPythonBindings.h)
add_custom_target(CorradeContainersPython SOURCES ${CorradeContainersPython_HEADERS})
install(FILES ${CorradeContainersPython_HEADERS} DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR}/Containers)
if(WITH_PYTHON)
add_custom_target(CorradeContainersPython SOURCES Python.h)
set_target_properties(CorradeContainersPython PROPERTIES FOLDER "Corrade/Python")
install(FILES Python.h DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR}/Containers)
endif()

63
src/Corrade/Containers/OptionalPythonBindings.h

@ -1,63 +0,0 @@
#ifndef Corrade_Containers_OptionalPythonBindings_h
#define Corrade_Containers_OptionalPythonBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <pybind11/pybind11.h>
#include <Corrade/Containers/Optional.h>
namespace pybind11 { namespace detail {
/* pybind11/stl.h has optional_caster for this, but that relies on a value_type
typedef that Optional doesn't have, so adapting a copy of it, also without
std::is_lvalue_reference<T>::value, which is not a thing here */
template<class T> struct type_caster<Corrade::Containers::Optional<T>> {
using value_conv = make_caster<T>;
template<class T_> static handle cast(T_&& src, const return_value_policy policy, const handle parent) {
if(!src) return none{}.release();
return value_conv::cast(*std::forward<T_>(src), return_value_policy_override<T>::policy(policy), parent);
}
bool load(const handle src, bool convert) {
if(!src) return false;
/* default-constructed value is already empty */
if(src.is_none()) return true;
value_conv inner_caster;
if(!inner_caster.load(src, convert)) return false;
value.emplace(cast_op<T&&>(std::move(inner_caster)));
return true;
}
PYBIND11_TYPE_CASTER(Corrade::Containers::Optional<T>, _("Optional[") + value_conv::name + _("]"));
};
}}
#endif

10
src/Corrade/Containers/PythonBindings.h → src/Corrade/Containers/Python.h

@ -1,10 +1,9 @@
#ifndef Corrade_Containers_PythonBindings_h
#define Corrade_Containers_PythonBindings_h
#ifndef Corrade_Containers_Python_h
#define Corrade_Containers_Python_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -46,7 +45,7 @@ template<class T> struct PyArrayViewHolder: std::unique_ptr<T> {
};
template<class T> PyArrayViewHolder<T> pyArrayViewHolder(const T& view, pybind11::object owner) {
return PyArrayViewHolder<T>{new T{view}, std::move(owner)};
return PyArrayViewHolder<T>{new T{view}, owner};
}
}}
@ -54,3 +53,4 @@ template<class T> PyArrayViewHolder<T> pyArrayViewHolder(const T& view, pybind11
PYBIND11_DECLARE_HOLDER_TYPE(T, Corrade::Containers::PyArrayViewHolder<T>)
#endif

203
src/Corrade/Containers/StridedArrayViewPythonBindings.h

@ -1,203 +0,0 @@
#ifndef Corrade_Containers_StridedArrayViewPythonBindings_h
#define Corrade_Containers_StridedArrayViewPythonBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <pybind11/pybind11.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/String.h>
namespace Corrade { namespace Containers {
namespace Implementation {
/* For maintainability please keep in the same order as
https://docs.python.org/3/library/struct.html#format-characters. Each of
these has also a corresponding entry in accessorsForFormat() in
containers.cpp in the same order. */
template<class T> constexpr const char* pythonFormatString() {
static_assert(sizeof(T) == 0, "format string unknown for this type, supply it explicitly");
return {};
}
/* Treating bytes as unsigned 8-bit integers and not as chars for consistency
with bytes/bytearray, where you have to use ord(a[0]) to get a character
value. Same done for PyStridedArrayViewItem and PyStridedArrayViewSetItem
below. To further emphasize that this is "general data", a null format
string is returned, which should be treated the same as B:
https://docs.python.org/3/c-api/buffer.html#c.Py_buffer.format */
template<> constexpr const char* pythonFormatString<char>() { return nullptr; }
template<> constexpr const char* pythonFormatString<std::int8_t>() { return "b"; }
template<> constexpr const char* pythonFormatString<std::uint8_t>() { return "B"; }
template<> constexpr const char* pythonFormatString<std::int16_t>() { return "h"; }
template<> constexpr const char* pythonFormatString<std::uint16_t>() { return "H"; }
template<> constexpr const char* pythonFormatString<std::int32_t>() { return "i"; }
template<> constexpr const char* pythonFormatString<std::uint32_t>() { return "I"; }
/* *not* l / L, that's 4 bytes in Python */
template<> constexpr const char* pythonFormatString<std::int64_t>() { return "q"; }
template<> constexpr const char* pythonFormatString<std::uint64_t>() { return "Q"; }
/** @todo how to represent std::size_t? conflicts with uint32_t/uint64_t above */
template<> constexpr const char* pythonFormatString<float>() { return "f"; }
template<> constexpr const char* pythonFormatString<double>() { return "d"; }
template<class U> struct PyStridedArrayViewItem {
static pybind11::object get(const char* item) {
return pybind11::cast(*reinterpret_cast<const U*>(item));
}
};
/* Treating bytes as unsigned 8-bit integers and not as chars for consistency
with bytes/bytearray, where you have to use ord(a[0]) to get a character
value. Same done for pythonFormatString<char>() above and
PyStridedArrayViewSetItem below. */
template<> struct PyStridedArrayViewItem<const char> {
static pybind11::object get(const char* item) {
return pybind11::cast(*reinterpret_cast<const std::uint8_t*>(item));
}
};
template<class T, class U> struct PyStridedArrayViewSetItem;
template<class U> struct PyStridedArrayViewSetItem<const char, U> {
/* __setitem__ is not even exposed for immutable views so this is fine */
constexpr static std::nullptr_t set = nullptr;
};
template<class U> struct PyStridedArrayViewSetItem<char, U> {
static void set(char* item, pybind11::handle object) {
*reinterpret_cast<U*>(item) = pybind11::cast<U>(object);
}
};
/* Treating bytes as unsigned 8-bit integers and not as chars for consistency
with bytes/bytearray, where you have to use a[0] = ord('A') to set a
character value. Same done for pythonFormatString<char>() and
PyStridedArrayViewItem above. */
template<> struct PyStridedArrayViewSetItem<char, char> {
static void set(char* item, pybind11::handle object) {
*reinterpret_cast<std::uint8_t*>(item) = pybind11::cast<std::uint8_t>(object);
}
};
template<unsigned, class> struct PyStridedElement;
}
template<unsigned dimensions, class T> class PyStridedArrayView: public StridedArrayView<dimensions, T> {
/* the type is dynamic; ArrayView has the same check */
static_assert(std::is_same<const T, const char>::value, "only the (const) char StridedArrayView is meant to be exposed");
public:
/* Null function pointers should be okay as it shouldn't ever get to
them -- IndexError gets fired first. The format string can be null
as well (which nicely implies "general data"), in which case B
should be assumed:
https://docs.python.org/3/c-api/buffer.html#c.Py_buffer.format */
/*implicit*/ PyStridedArrayView(): format{}, getitem{}, setitem{} {}
template<class U> explicit PyStridedArrayView(const StridedArrayView<dimensions, U>& view): PyStridedArrayView{view, Implementation::pythonFormatString<typename std::decay<U>::type>(), sizeof(U)} {}
template<class U> explicit PyStridedArrayView(const StridedArrayView<dimensions, U>& view, Containers::StringView format, std::size_t itemsize): PyStridedArrayView<dimensions, T>{
arrayCast<T>(view),
format,
itemsize,
Implementation::PyStridedArrayViewItem<const U>::get,
Implementation::PyStridedArrayViewSetItem<T, U>::set
} {}
explicit PyStridedArrayView(const StridedArrayView<dimensions, T>& view, Containers::StringView format, std::size_t itemsize, pybind11::object(*getitem)(const char*), void(*setitem)(char*, pybind11::handle)): StridedArrayView<dimensions, T>{view}, format{format}, itemsize{itemsize}, getitem{getitem}, setitem{setitem} {}
/* All APIs that are exposed by bindings and return a StridedArrayView
have to return the wrapper now */
typedef typename std::conditional<dimensions == 1, T&, PyStridedArrayView<dimensions - 1, T>>::type ElementType;
ElementType operator[](std::size_t i) const {
return Implementation::PyStridedElement<dimensions, T>::wrap(StridedArrayView<dimensions, T>::operator[](i), format, itemsize, getitem, setitem);
}
T& operator[](const Containers::Size<dimensions>& i) const {
return StridedArrayView<dimensions, T>::operator[](i);
}
PyStridedArrayView<dimensions, T> slice(std::size_t begin, std::size_t end) const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::slice(begin, end), format, itemsize, getitem, setitem};
}
PyStridedArrayView<dimensions, T> slice(const Containers::Size<dimensions>& begin, const Containers::Size<dimensions>& end) const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::slice(begin, end), format, itemsize, getitem, setitem};
}
/* slice() with templated dimensions not used */
/* slice(&T::member) not used */
/* prefix(), suffix(), except() not used */
PyStridedArrayView<dimensions, T> every(std::size_t skip) const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::every(skip), format, itemsize, getitem, setitem};
}
PyStridedArrayView<dimensions, T> every(const Containers::Stride<dimensions>& skip) const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::every(skip), format, itemsize, getitem, setitem};
}
template<unsigned dimensionA, unsigned dimensionB> PyStridedArrayView<dimensions, T> transposed() const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::template transposed<dimensionA, dimensionB>(), format, itemsize, getitem, setitem};
}
template<unsigned dimension> PyStridedArrayView<dimensions, T> flipped() const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::template flipped<dimension>(), format, itemsize, getitem, setitem};
}
template<unsigned dimension> PyStridedArrayView<dimensions, T> broadcasted(std::size_t size) const {
return PyStridedArrayView<dimensions, T>{StridedArrayView<dimensions, T>::template broadcasted<dimension>(size), format, itemsize, getitem, setitem};
}
template<unsigned dimension, unsigned count> PyStridedArrayView<dimensions + count - 1, T> expanded(const Containers::Size<count>& size) const {
return PyStridedArrayView<dimensions + count - 1, T>{StridedArrayView<dimensions, T>::template expanded<dimension>(size), format, itemsize, getitem, setitem};
}
/* has to be public as it's accessed by the bindings directly */
/* The assumption is that >99% of format strings should be just a few
characters, stored with a SSO. I.e., not even bothering with
String::nullTerminatedGlobalView() anywhere. */
Containers::String format;
std::size_t itemsize;
pybind11::object(*getitem)(const char*);
void(*setitem)(char*, pybind11::handle);
};
namespace Implementation {
template<unsigned dimensions, class T> struct PyStridedElement {
static PyStridedArrayView<dimensions - 1, T> wrap(const StridedArrayView<dimensions - 1, T>& element, Containers::StringView format, std::size_t itemsize, pybind11::object(*getitem)(const char*), void(*setitem)(char*, pybind11::handle)) {
return PyStridedArrayView<dimensions - 1, T>{element, format, itemsize, getitem, setitem};
}
};
template<class T> struct PyStridedElement<1, T> {
static T& wrap(T& element, Containers::StringView, std::size_t, pybind11::object(*)(const char*), void(*)(char*, pybind11::handle)) {
return element;
}
};
}
}}
#endif

72
src/Corrade/PluginManager/PythonBindings.h

@ -1,72 +0,0 @@
#ifndef Corrade_PluginManager_PythonBindings_h
#define Corrade_PluginManager_PythonBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <memory> /* :( */
#include <pybind11/pybind11.h>
#include <Corrade/Containers/Pointer.h>
#include <Corrade/Utility/Assert.h>
namespace Corrade { namespace PluginManager {
/* Stores additional stuff needed for proper refcounting of plugin instances.
Due to obvious reasons we can't subclass plugins so this is the only
possible way. */
template<class T> struct PyPluginHolder: std::unique_ptr<T> {
explicit PyPluginHolder(T* object) noexcept: std::unique_ptr<T>{object} {
/* Plugin instance without an owner can only be without a manager and
thus without any metadata */
CORRADE_INTERNAL_ASSERT(!object->metadata());
}
explicit PyPluginHolder(T* object, pybind11::object manager) noexcept: std::unique_ptr<T>{object}, manager{std::move(manager)} {}
PyPluginHolder(PyPluginHolder<T>&&) noexcept = default;
PyPluginHolder(const PyPluginHolder<T>&) = delete;
PyPluginHolder<T>& operator=(PyPluginHolder<T>&&) noexcept = default;
PyPluginHolder<T>& operator=(const PyPluginHolder<T>&) = delete;
~PyPluginHolder() {
/* On destruction, first `manager` and then the plugin would be
destroyed, which would mean it asserts due to the manager being
destructed while plugins are still around. To flip the order, we
need to reset the pointer first */
std::unique_ptr<T>::reset();
}
pybind11::object manager;
};
template<class T> PyPluginHolder<T> pyPluginHolder(Containers::Pointer<T>&& plugin, pybind11::object owner) {
return PyPluginHolder<T>{plugin.release(), std::move(owner)};
}
}}
PYBIND11_DECLARE_HOLDER_TYPE(T, Corrade::PluginManager::PyPluginHolder<T>)
#endif

34
src/Corrade/PythonBindings.h → src/Corrade/Python.h

@ -1,10 +1,9 @@
#ifndef Corrade_PythonBindings_h
#define Corrade_PythonBindings_h
#ifndef Corrade_Python_h
#define Corrade_Python_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -31,22 +30,14 @@
namespace Corrade {
inline pybind11::handle pyHandleFromInstance(const void* obj, const std::type_info& type) {
/** @todo don't tell me there's no API for this either, ugh */
return pybind11::detail::get_object_handle(obj, pybind11::detail::get_type_info(type));
}
template<class T> inline pybind11::handle pyHandleFromInstance(T& obj) {
return pyHandleFromInstance(&obj, typeid(T));
}
inline pybind11::object pyObjectFromInstance(const void* obj, const std::type_info& type) {
/* reinterpret_borrow?! seriously?! */
return pybind11::reinterpret_borrow<pybind11::object>(pyHandleFromInstance(obj, type));
/** @todo don't tell me there's no API for this either, ugh */
return pybind11::detail::get_object_handle(&obj, pybind11::detail::get_type_info(typeid(T)));
}
template<class T> inline pybind11::object pyObjectFromInstance(T& obj) {
return pyObjectFromInstance(&obj, typeid(T));
/* reinterpret_borrow?! seriously?! */
return pybind11::reinterpret_borrow<pybind11::object>(pyHandleFromInstance(obj));
}
template<class T> inline T& pyInstanceFromHandle(pybind11::handle handle) {
@ -97,17 +88,6 @@ template<template<class> class T, class U> T<U>& pyObjectHolderFor(U& obj) {
return pyObjectHolderFor<T<U>>(pybind11::detail::get_object_handle(&obj, typeinfo), typeinfo);
}
/* This is a variant of https://github.com/pybind/pybind11/issues/1178,
implemented on the client side instead of patching pybind itself */
template<class, bool> struct PyNonDestructibleBaseDeleter;
template<class T> struct PyNonDestructibleBaseDeleter<T, false> {
void operator()(T*) { CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ }
};
template<class T> struct PyNonDestructibleBaseDeleter<T, true> {
void operator()(T* ptr) { delete ptr; }
};
template<class T, class... Args> using PyNonDestructibleClass = pybind11::class_<T, Args..., std::unique_ptr<T, PyNonDestructibleBaseDeleter<T, std::is_destructible<T>::value>>>;
}
#endif

67
src/Magnum/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,58 +23,10 @@
# DEALINGS IN THE SOFTWARE.
#
# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER
# property that would have to be set on each target separately.
set(CMAKE_FOLDER "Magnum/Python")
# Generate version header. If Git is found and this is a Git working copy,
# extract values from there, otherwise use just MAGNUMBINDINGS_VERSION_YEAR /
# MONTH that are set in project root CMakeLists.
find_package(Git)
if(Git_FOUND)
# Match only tags starting with `v`, always use the long format so we have
# a commit hash also on a tagged version
execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v*" --long
OUTPUT_VARIABLE MAGNUMBINDINGS_VERSION_STRING
RESULT_VARIABLE _MAGNUMBINDINGS_VERSION_RESULT
ERROR_VARIABLE _MAGNUMBINDINGS_VERSION_ERROR
# Otherwise this gets executed in the build dir, which might be inside
# a totally different Git working copy. But that's not enough, if it
# would be run in ${CMAKE_CURRENT_SOURCE_DIR}, on Windows the
# `--match "v*"` would get expanded to the `versionBindings.h.cmake`
# file, causing Git to obviously not find any such tag. The reason is
# probably that on Windows the wildcard expansion is done on the
# application side and not by the shell, thus being performed even
# though CMake docs say `execute_process()` doesn't involve a shell.
# The package/git directory is thus dedicated for that operation,
# *guaranteed* to never contain any file starting with `v` (or `V` for
# that matter because, again, HELLO WINDOWS).
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/package/git
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(MAGNUMBINDINGS_VERSION_STRING MATCHES "^v([0-9][0-9][0-9][0-9])\\.0?([0-9][0-9]?)-([0-9]+)-g([a-f0-9]+)$")
set(MAGNUMBINDINGS_VERSION_YEAR ${CMAKE_MATCH_1})
set(MAGNUMBINDINGS_VERSION_MONTH ${CMAKE_MATCH_2})
set(MAGNUMBINDINGS_VERSION_COMMIT ${CMAKE_MATCH_3})
# Otherwise if commit is 0, it would #undef the variable
set(MAGNUMBINDINGS_VERSION_COMMIT " ${MAGNUMBINDINGS_VERSION_COMMIT}")
set(MAGNUMBINDINGS_VERSION_HASH ${CMAKE_MATCH_4})
elseif(_MAGNUMBINDINGS_VERSION_RESULT EQUAL 0)
message(WARNING "Can't match Git version from ${MAGNUMBINDINGS_VERSION_STRING}, generating a fallback versionBindings.h instead")
else()
message(WARNING "Can't match Git version, generating a fallback versionBindings.h instead: ${_MAGNUMBINDINGS_VERSION_ERROR}")
endif()
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/versionBindings.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/versionBindings.h)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/versionBindings.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR})
if(MAGNUM_WITH_PYTHON)
set(MagnumPython_SRCS
PythonBindings.h
StridedArrayViewPythonBindings.h)
add_custom_target(MagnumPython SOURCES ${MagnumPython_SRCS})
install(FILES ${MagnumPython_SRCS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR})
if(WITH_PYTHON)
add_custom_target(MagnumPython SOURCES Python.h)
set_target_properties(MagnumPython PROPERTIES FOLDER "Magnum/Python")
install(FILES Python.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR})
endif()
find_package(Magnum COMPONENTS GL SceneGraph)
@ -87,11 +38,3 @@ endif()
if(Magnum_SceneGraph_FOUND)
add_subdirectory(SceneGraph)
endif()
if(Magnum_Trade_FOUND)
add_subdirectory(Trade)
endif()
if(MAGNUM_BUILD_TESTS)
add_subdirectory(Test ${EXCLUDE_FROM_ALL_IF_TEST_TARGET})
endif()

10
src/Magnum/GL/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,7 +23,8 @@
# DEALINGS IN THE SOFTWARE.
#
if(MAGNUM_WITH_PYTHON)
add_custom_target(MagnumGLPython SOURCES PythonBindings.h)
install(FILES PythonBindings.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/GL)
if(WITH_PYTHON)
add_custom_target(MagnumGLPython SOURCES Python.h)
set_target_properties(MagnumGLPython PROPERTIES FOLDER "Magnum/Python")
install(FILES Python.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/GL)
endif()

9
src/Magnum/GL/PythonBindings.h → src/Magnum/GL/Python.h

@ -1,10 +1,9 @@
#ifndef Magnum_GL_PythonBindings_h
#define Magnum_GL_PythonBindings_h
#ifndef Magnum_GL_Python_h
#define Magnum_GL_Python_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -31,7 +30,7 @@
#include <pybind11/pybind11.h>
#include <Magnum/GL/GL.h>
#include "Magnum/PythonBindings.h"
#include "Magnum/Python.h"
namespace Magnum { namespace GL {

20
src/Magnum/PythonBindings.h → src/Magnum/Python.h

@ -1,10 +1,9 @@
#ifndef Magnum_PythonBindings_h
#define Magnum_PythonBindings_h
#ifndef Magnum_Python_h
#define Magnum_Python_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -46,9 +45,20 @@ template<class T> struct PyImageViewHolder: std::unique_ptr<T> {
};
template<class T> PyImageViewHolder<T> pyImageViewHolder(const T& view, pybind11::object owner) {
return PyImageViewHolder<T>{new T{view}, std::move(owner)};
return PyImageViewHolder<T>{new T{view}, owner};
}
/* This is a variant of https://github.com/pybind/pybind11/issues/1178,
implemented on the client side instead of patching pybind itself */
template<class, bool> struct PyNonDestructibleBaseDeleter;
template<class T> struct PyNonDestructibleBaseDeleter<T, false> {
void operator()(T*) { CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ }
};
template<class T> struct PyNonDestructibleBaseDeleter<T, true> {
void operator()(T* ptr) { delete ptr; }
};
template<class T, class... Args> using PyNonDestructibleClass = pybind11::class_<T, Args..., std::unique_ptr<T, PyNonDestructibleBaseDeleter<T, std::is_destructible<T>::value>>>;
}
PYBIND11_DECLARE_HOLDER_TYPE(T, Magnum::PyImageViewHolder<T>)

10
src/Magnum/SceneGraph/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,7 +23,8 @@
# DEALINGS IN THE SOFTWARE.
#
if(MAGNUM_WITH_PYTHON)
add_custom_target(MagnumSceneGraphPython SOURCES PythonBindings.h)
install(FILES PythonBindings.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/SceneGraph)
if(WITH_PYTHON)
add_custom_target(MagnumSceneGraphPython SOURCES Python.h)
set_target_properties(MagnumSceneGraphPython PROPERTIES FOLDER "Magnum/Python")
install(FILES Python.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/SceneGraph)
endif()

29
src/Magnum/SceneGraph/PythonBindings.h → src/Magnum/SceneGraph/Python.h

@ -1,10 +1,9 @@
#ifndef Magnum_SceneGraph_PythonBindings_h
#define Magnum_SceneGraph_PythonBindings_h
#ifndef Magnum_SceneGraph_Python_h
#define Magnum_SceneGraph_Python_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -29,7 +28,6 @@
#include <memory> /* :( */
#include <pybind11/pybind11.h>
#include <Corrade/Utility/Assert.h>
#include <Magnum/SceneGraph/AbstractFeature.h>
namespace Magnum { namespace SceneGraph {
@ -64,27 +62,22 @@ template<class T> struct PyFeatureHolder: std::unique_ptr<T> {
/* Hey this needs docs. */
/* This template parameter can't be just Object, as that makes MSVC confused
when CRTP'ing something else than a class named Object -- it fails inside
the Object{} call in the constructor, saying `error C2614:
'Magnum::SceneGraph::PyObject<SomeOtherName>': illegal member initialization:
'Object' is not a base or member`. */
template<class Object_> class PyObject: public Object_ {
template<class Object> class PyObject: public Object {
public:
template<class ...Args> explicit PyObject(Args&&... args): Object_{std::forward<Args>(args)...} {}
template<class ...Args> explicit PyObject(Args&&... args): Object{std::forward<Args>(args)...} {}
PyObject(const PyObject<Object_>&) = delete;
PyObject(PyObject<Object_>&&) = delete;
PyObject(const PyObject<Object>&) = delete;
PyObject(PyObject<Object>&&) = delete;
PyObject<Object_>& operator=(const PyObject<Object_>&) = delete;
PyObject<Object_>& operator=(PyObject<Object_>&&) = delete;
PyObject<Object>& operator=(const PyObject<Object>&) = delete;
PyObject<Object>& operator=(PyObject<Object>&&) = delete;
private:
void doErase() override {
/* When deleting a parent, disconnect this from the parent instead
of deleting it. Deletion is then handled by Python itself. */
CORRADE_INTERNAL_ASSERT(Object_::parent());
Object_::setParent(nullptr);
CORRADE_INTERNAL_ASSERT(Object::parent());
Object::setParent(nullptr);
pybind11::cast(this).dec_ref();
}
};

119
src/Magnum/StridedArrayViewPythonBindings.h

@ -1,119 +0,0 @@
#ifndef Magnum_StridedArrayViewPythonBindings_h
#define Magnum_StridedArrayViewPythonBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <Magnum/Magnum.h>
#include "Corrade/Containers/StridedArrayViewPythonBindings.h"
namespace Corrade { namespace Containers { namespace Implementation {
/* This expands Containers::Implementation::pythonFormatString() with Magnum
types. Using e.g. "3f" instead of "fff" as that makes Numpy understand even
the slices as arrays in a concrete type (or it at least repr()s them as
such), with "fff" it gives back an untyped tuple. */
#define _c(type, string) \
template<> constexpr const char* pythonFormatString<Magnum::type>() { return string; }
_c(Half, "e")
_c(Vector2, "2f")
_c(Vector2h, "2e")
_c(Vector2d, "2d")
_c(Vector2ub, "2B")
_c(Vector2b, "2b")
_c(Vector2us, "2H")
_c(Vector2s, "2h")
_c(Vector2ui, "2I")
_c(Vector2i, "2i")
_c(Vector3, "3f")
_c(Vector3h, "3e")
_c(Vector3d, "3d")
_c(Vector3ub, "3B")
_c(Vector3b, "3b")
_c(Vector3us, "3H")
_c(Vector3s, "3h")
_c(Vector3ui, "3I")
_c(Vector3i, "3i")
_c(Vector4, "4f")
_c(Vector4h, "4e")
_c(Vector4d, "4d")
_c(Vector4ub, "4B")
_c(Vector4b, "4b")
_c(Vector4us, "4H")
_c(Vector4s, "4h")
_c(Vector4ui, "4I")
_c(Vector4i, "4i")
_c(Matrix2x2, "4f")
_c(Matrix2x2d, "4d")
_c(Matrix2x3, "6f")
_c(Matrix2x3d, "6d")
_c(Matrix2x4, "8f")
_c(Matrix2x4d, "8d")
_c(Matrix3x2, "6f")
_c(Matrix3x2d, "6d")
_c(Matrix3x3, "9f")
_c(Matrix3x3d, "9d")
_c(Matrix3x4, "12f")
_c(Matrix3x4d, "12d")
_c(Matrix4x2, "8f")
_c(Matrix4x2d, "8d")
_c(Matrix4x3, "12f")
_c(Matrix4x3d, "12d")
_c(Matrix4x4, "16f")
_c(Matrix4x4d, "16d")
_c(Range1D, "2f")
_c(Range1Dd, "2d")
_c(Range1Di, "2i")
_c(Range2D, "4f")
_c(Range2Dd, "4d")
_c(Range2Di, "4i")
_c(Range3D, "6f")
_c(Range3Dd, "6d")
_c(Range3Di, "6i")
_c(Complex, "2f")
_c(Complexd, "2d")
_c(DualComplex, "4f")
_c(DualComplexd, "4f")
_c(Quaternion, "4f")
_c(Quaterniond, "4d")
_c(DualQuaternion, "8f")
_c(DualQuaterniond, "8d")
_c(Deg, "f")
_c(Degd, "d")
_c(Rad, "f")
_c(Radd, "d")
#undef _c
}
}}
#endif

30
src/Magnum/Test/CMakeLists.txt

@ -1,30 +0,0 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# Prefixed with project name to avoid conflicts with VersionTest in Magnum and
# related repos
corrade_add_test(MagnumBindingsVersionTest VersionTest.cpp LIBRARIES Magnum::Magnum)
target_include_directories(MagnumBindingsVersionTest PRIVATE ${PROJECT_BINARY_DIR}/src)

67
src/Magnum/Test/VersionTest.cpp

@ -1,67 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Numeric.h>
#include "Magnum/Magnum.h"
#include "Magnum/versionBindings.h"
namespace Magnum { namespace Test { namespace {
struct VersionTest: TestSuite::Tester {
explicit VersionTest();
void test();
};
VersionTest::VersionTest() {
addTests({&VersionTest::test});
}
void VersionTest::test() {
Debug{} << "MAGNUMBINDINGS_VERSION_YEAR:" << MAGNUMBINDINGS_VERSION_YEAR;
Debug{} << "MAGNUMBINDINGS_VERSION_MONTH:" << MAGNUMBINDINGS_VERSION_MONTH;
#ifdef MAGNUMBINDINGS_VERSION_COMMIT
Debug{} << "MAGNUMBINDINGS_VERSION_COMMIT:" << MAGNUMBINDINGS_VERSION_COMMIT;
Debug{} << "MAGNUMBINDINGS_VERSION_HASH:" << Debug::hex << MAGNUMBINDINGS_VERSION_HASH;
Debug{} << "MAGNUMBINDINGS_VERSION_STRING:" << MAGNUMBINDINGS_VERSION_STRING;
#else
Debug{} << "No Git version information available.";
#endif
CORRADE_COMPARE_AS(MAGNUMBINDINGS_VERSION_YEAR, 2019, TestSuite::Compare::GreaterOrEqual);
CORRADE_COMPARE_AS(MAGNUMBINDINGS_VERSION_YEAR, 2100, TestSuite::Compare::LessOrEqual);
CORRADE_COMPARE_AS(MAGNUMBINDINGS_VERSION_MONTH, 0, TestSuite::Compare::Greater);
CORRADE_COMPARE_AS(MAGNUMBINDINGS_VERSION_MONTH, 12, TestSuite::Compare::LessOrEqual);
#ifdef MAGNUMBINDINGS_VERSION_COMMIT
CORRADE_COMPARE_AS(MAGNUMBINDINGS_VERSION_COMMIT, 0, TestSuite::Compare::GreaterOrEqual);
#endif
}
}}}
CORRADE_TEST_MAIN(Magnum::Test::VersionTest)

30
src/Magnum/Trade/CMakeLists.txt

@ -1,30 +0,0 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
if(MAGNUM_WITH_PYTHON)
add_custom_target(MagnumTradePython SOURCES PythonBindings.h)
install(FILES PythonBindings.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Trade)
endif()

103
src/Magnum/Trade/PythonBindings.h

@ -1,103 +0,0 @@
#ifndef Magnum_Trade_PythonBindings_h
#define Magnum_Trade_PythonBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <memory> /* :( */
#include <pybind11/pybind11.h>
#include "Magnum/Trade/Data.h"
#include "Magnum/Trade/MaterialData.h" /* :( */
#include "Magnum/Trade/MeshData.h" /* :( */
#include "Magnum/Trade/SceneData.h"
namespace Magnum { namespace Trade {
namespace Implementation {
/* For assertions only */
template<class T> inline bool pyDataFlagsNeedOwner(const T& data) {
return !(data.dataFlags() & (DataFlag::Owned|DataFlag::Global));
}
inline bool pyDataFlagsNeedOwner(const MaterialData& data) {
return
!(data.attributeDataFlags() & (DataFlag::Owned|DataFlag::Global)) ||
!(data.layerDataFlags() & (DataFlag::Owned|DataFlag::Global));
}
inline bool pyDataFlagsNeedOwner(const MeshData& data) {
return
!(data.indexDataFlags() & (DataFlag::Owned|DataFlag::Global)) ||
!(data.vertexDataFlags() & (DataFlag::Owned|DataFlag::Global));
}
inline bool pyDataFlagsNeedOwner(const MeshAttributeData& data) {
return data.data().data();
}
}
/* Stores additional stuff needed for proper refcounting of non-owning FooData.
Better than subclassing each FooData class because then we would need to
wrap it every time it's exposed to Python, making 3rd party bindings
unnecessarily complex */
template<class T> struct PyDataHolder: std::unique_ptr<T> {
explicit PyDataHolder(T* object): PyDataHolder{object, pybind11::none{}} {
/* Data without an owner can only be self-owned, global or empty */
CORRADE_INTERNAL_ASSERT(!Implementation::pyDataFlagsNeedOwner(*object));
}
explicit PyDataHolder(T* object, pybind11::object owner): std::unique_ptr<T>{object}, owner{std::move(owner)} {}
pybind11::object owner;
};
template<class T> PyDataHolder<T> pyDataHolder(T&& data, pybind11::object owner) {
return PyDataHolder<T>{new T{std::move(data)}, std::move(owner)};
}
/* Compared to PyDataHolder this stores two owner objects. Has to be a template
even though it's only ever used for a single type because
PYBIND11_DECLARE_HOLDER_TYPE() wants it to be so. */
template<class T> struct PySceneFieldDataHolder: std::unique_ptr<SceneFieldData> {
explicit PySceneFieldDataHolder(SceneFieldData* object): PySceneFieldDataHolder{object, pybind11::none{}, pybind11::none{}} {
/* Data without owners can only be empty */
CORRADE_INTERNAL_ASSERT(!object->mappingData().data() && !object->fieldData().data());
}
explicit PySceneFieldDataHolder(SceneFieldData* object, pybind11::object mappingOwner, pybind11::object fieldOwner): std::unique_ptr<T>{object}, mappingOwner{std::move(mappingOwner)}, fieldOwner{std::move(fieldOwner)} {}
pybind11::object mappingOwner, fieldOwner;
};
inline PySceneFieldDataHolder<SceneFieldData> pySceneFieldDataHolder(SceneFieldData&& data, pybind11::object mappingOwner, pybind11::object fieldOwner) {
return PySceneFieldDataHolder<SceneFieldData>{new SceneFieldData{std::move(data)}, std::move(mappingOwner), std::move(fieldOwner)};
}
}}
PYBIND11_DECLARE_HOLDER_TYPE(T, Magnum::Trade::PyDataHolder<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, Magnum::Trade::PySceneFieldDataHolder<T>)
#endif

39
src/Magnum/versionBindings.h.cmake

@ -1,39 +0,0 @@
#ifndef Magnum_versionBindings_h
#define Magnum_versionBindings_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* Note: this header is deliberately not included from anywhere except
VersionTest to avoid triggering a full rebuild every time the Git commit
hash changes. */
#define MAGNUMBINDINGS_VERSION_YEAR ${MAGNUMBINDINGS_VERSION_YEAR}
#define MAGNUMBINDINGS_VERSION_MONTH ${MAGNUMBINDINGS_VERSION_MONTH}
#cmakedefine MAGNUMBINDINGS_VERSION_COMMIT${MAGNUMBINDINGS_VERSION_COMMIT}
#cmakedefine MAGNUMBINDINGS_VERSION_HASH 0x${MAGNUMBINDINGS_VERSION_HASH}
#cmakedefine MAGNUMBINDINGS_VERSION_STRING "${MAGNUMBINDINGS_VERSION_STRING}"
#endif

33
src/python/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -27,23 +26,9 @@
# Thanks, CMake, for making the recommended way of installing pacakges so
# useless that it's impossible to call find_package() consistently independent
# of whether it's installed system-wide or added through add_subdirectory().
# This also means we can't use pybind11_VERSION below but have to extract it
# from some private cache variables instead. THIS IS ABSOLUTELY AWFUL, FFS.
# This is absolutely awful.
if(NOT COMMAND pybind11_add_module)
find_package(pybind11 CONFIG REQUIRED)
elseif(NOT pybind11_VERSION)
set(pybind11_VERSION ${PYBIND11_VERSION_MAJOR}.${PYBIND11_VERSION_MINOR}.${PYBIND11_VERSION_PATCH})
endif()
# In pybind11 2.2.4 and below, pybind11_add_module() added the include
# directories as non-system. That, combined with Corrade's warning level, added
# an insane amount of warnings to the build. Since 2.3 it was possible to
# override that by passing SYSTEM to pybind11_add_module(), HOWEVER since 2.6
# doing so causes an ANNOYING warning because they made that a default. That
# all in a span of barely two years. Can't things just stay stable for a little
# moment?!
if(pybind11_VERSION VERSION_LESS 2.6)
set(pybind11_add_module_SYSTEM SYSTEM)
endif()
# UGH FFS
@ -61,22 +46,17 @@ add_subdirectory(magnum)
# CMake 3.12, so I need to do two passes, first replacing variables using
# configure_file() and then replacing generator expressions with file(GENERATE)
foreach(target
corrade
corrade_containers
corrade_pluginmanager
corrade_utility
magnum_gl
magnum_materialtools
magnum_meshtools
magnum_primitives
magnum_scenegraph
magnum_scenetools
magnum_shaders
magnum_platform_cgl
magnum_platform_egl
magnum_platform_glx
magnum_platform_glfw
magnum_platform_sdl2
magnum_text
magnum_trade)
if(TARGET ${target})
set(${target}_file $<TARGET_FILE:${target}>)
@ -86,10 +66,3 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.cmake
${CMAKE_CURRENT_BINARY_DIR}/setup.py.in)
file(GENERATE OUTPUT ${output_dir}/setup.py
INPUT ${CMAKE_CURRENT_BINARY_DIR}/setup.py.in)
# MagnumPythonBindings library and alias, just for superprojects to have
# something to link to get to the headers
add_library(MagnumPythonBindings INTERFACE)
set_target_properties(MagnumPythonBindings PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/src)
add_library(MagnumBindings::Python ALIAS MagnumPythonBindings)

108
src/python/corrade/CMakeLists.txt

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,33 +23,13 @@
# DEALINGS IN THE SOFTWARE.
#
# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER
# property that would have to be set on each target separately.
set(CMAKE_FOLDER "Corrade/Python")
# *Not* REQUIRED
find_package(Corrade COMPONENTS
PluginManager)
set(corrade_SRCS
corrade.cpp)
# Extra libraries to link to. Populated only in case of CORRADE_BUILD_STATIC.
set(corrade_LIBS )
set(corrade_containers_SRCS
containers.cpp)
set(corrade_pluginmanager_SRCS
pluginmanager.cpp)
set(corrade_utility_SRCS
utility.cpp)
# If Corrade is not built as static, compile the sub-libraries as separate
# modules
if(NOT CORRADE_BUILD_STATIC)
pybind11_add_module(corrade_containers ${pybind11_add_module_SYSTEM} ${corrade_containers_SRCS})
pybind11_add_module(corrade_containers SYSTEM ${corrade_containers_SRCS})
target_include_directories(corrade_containers PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
@ -58,81 +37,28 @@ if(NOT CORRADE_BUILD_STATIC)
Corrade::Containers
Corrade::Utility)
set_target_properties(corrade_containers PROPERTIES
FOLDER "python/corrade"
OUTPUT_NAME "containers"
LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade)
pybind11_add_module(corrade_utility ${pybind11_add_module_SYSTEM} ${corrade_utility_SRCS})
target_include_directories(corrade_utility PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
target_link_libraries(corrade_utility PRIVATE
Corrade::Utility)
set_target_properties(corrade_utility PROPERTIES
OUTPUT_NAME "utility"
LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade)
if(Corrade_PluginManager_FOUND)
pybind11_add_module(corrade_pluginmanager ${pybind11_add_module_SYSTEM} ${corrade_pluginmanager_SRCS})
target_include_directories(corrade_pluginmanager PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
target_link_libraries(corrade_pluginmanager PRIVATE
Corrade::PluginManager)
set_target_properties(corrade_pluginmanager PROPERTIES
OUTPUT_NAME "pluginmanager"
LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade)
endif()
# Otherwise put it all into one library so it's easier to install (which is the
# point of static builds). It also nicely avoids problems with multiply-defined
# global data. Unless the static libraries are linked into multiple Python
# modules, that is, which is (on Unix at least) attempted to be solved by the
# MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL option below.
# global data.
else()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/staticconfigure.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/staticconfigure.h)
list(APPEND corrade_SRCS
${corrade_containers_SRCS}
${corrade_utility_SRCS})
list(APPEND corrade_LIBS
Corrade::Containers
Corrade::Utility)
set(corrade_SRCS
corrade.cpp
${corrade_containers_SRCS})
if(Corrade_PluginManager_FOUND)
list(APPEND corrade_SRCS ${corrade_pluginmanager_SRCS})
list(APPEND corrade_LIBS Corrade::PluginManager)
endif()
pybind11_add_module(corrade SYSTEM ${corrade_SRCS})
target_include_directories(corrade PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
target_link_libraries(corrade PRIVATE Corrade::Utility ${corrade_LIBS})
set_target_properties(corrade PROPERTIES
FOLDER "python"
OUTPUT_NAME "_corrade"
LIBRARY_OUTPUT_DIRECTORY ${output_dir})
endif()
# If the option is enabled, the setdlopenflags() code in __init__.py is used,
# otherwise it's commented out
if(MAGNUM_BUILD_STATIC AND UNIX AND MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL)
set(_MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL "")
else()
set(_MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL "## ")
endif()
# ${output_dir} contains $<CONFIG> on multi-config builds, and configure_file()
# cannot expand that during the configure step so it has to put the result into
# a temporary location and then file(GENERATE) does the rest. It's important to
# ensure that the file put in ${CMAKE_CURRENT_BINARY_DIR} isn't named
# __init__.py as that may cause Python to wrongly treat the directory as a
# package, which it isn't.
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in
${CMAKE_CURRENT_BINARY_DIR}/__init__.py.in)
file(GENERATE OUTPUT ${output_dir}/corrade/__init__.py
INPUT ${CMAKE_CURRENT_BINARY_DIR}/__init__.py.in)
pybind11_add_module(corrade ${pybind11_add_module_SYSTEM} ${corrade_SRCS})
target_include_directories(corrade PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python
${PROJECT_BINARY_DIR}/src/python) # for static build
target_link_libraries(corrade PRIVATE Corrade::Utility ${corrade_LIBS})
set_target_properties(corrade PROPERTIES
OUTPUT_NAME "_corrade"
LIBRARY_OUTPUT_DIRECTORY ${output_dir})
if(MAGNUM_BUILD_TESTS)
add_subdirectory(test)
endif()
INPUT ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py)

3
src/python/corrade/EnumOperators.h

@ -3,8 +3,7 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a

13
src/python/corrade/PyBuffer.h

@ -3,8 +3,7 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -30,7 +29,7 @@
#include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/StridedArrayView.h>
#include "Corrade/PythonBindings.h"
#include "Corrade/Python.h"
#include "bootstrap.h"
@ -62,7 +61,7 @@ template<class Class, bool(*getter)(Class&, Py_buffer&, int)> void enableBetterB
/* Set the memory owner to the object and increase its reference count.
We need to keep the object around because buffer->shapes /
buffer->strides might be referring to it, moreover setting it to
buffer->strides might be refering to it, moreover setting it to
something else (like ArrayView's memory owner object) would mean
Python calls the releasebuffer on that object instead of on us,
leading to reference count getting negative in many cases. */
@ -78,4 +77,10 @@ template<class Class, bool(*getter)(Class&, Py_buffer&, int)> void enableBetterB
}
/** @todo remove when https://github.com/pybind/pybind11/pull/1852 is merged
and released */
namespace pybind11 {
PYBIND11_RUNTIME_EXCEPTION(buffer_error, PyExc_BufferError)
}
#endif

29
src/Corrade/PluginManager/CMakeLists.txt → src/python/corrade/__init__.py

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -24,10 +23,24 @@
# DEALINGS IN THE SOFTWARE.
#
if(MAGNUM_WITH_PYTHON)
set(CorradePluginManagerPython_HEADERS
PythonBindings.h)
"""Root Corrade module"""
add_custom_target(CorradePluginManagerPython SOURCES ${CorradePluginManagerPython_HEADERS})
install(FILES ${CorradePluginManagerPython_HEADERS} DESTINATION ${CORRADE_INCLUDE_INSTALL_DIR}/PluginManager)
endif()
import sys
# In case Corrade is built statically, the whole core project is put into
# _corrade. If corrade is built dynamically, there's no core library at the
# moment.
try:
from _corrade import *
# The following feels extremely hackish, but without that it wouldn't be
# possible to do `import corrade.containers`, which is weird
# (`from corrade import containers` works, tho, for whatever reason)
for i in ['containers']:
if i in globals(): sys.modules['corrade.' + i] = globals()[i]
except ImportError:
pass
# Prevent all submodules being pulled in when saying `from corrade import *` --
# this is consistent with behavior in magnum
__all__ = []

82
src/python/corrade/__init__.py.in

@ -1,82 +0,0 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
"""Root Corrade module"""
# If MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL is enabled in CMake, the lines
# below are included, otherwise they are commented out. What it does is a
# futile attempt to make Corrade (and Magnum) built as static libraries work
# together when built into multiple dynamic Python modules.
${_MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL}import sys
${_MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL}import ctypes
${_MAGNUM_BUILD_PYTHON_BINDINGS_RTLD_GLOBAL}sys.setdlopenflags(sys.getdlopenflags()|ctypes.RTLD_GLOBAL)
# On Windows, if a known directory layout is detected, add paths containing
# binaries to the DLL search path
import platform
if platform.system() == 'Windows':
import os
# os.add_dll_directory() is only since Python 3.8, in earlier versions
# PATH is used and that alone may be sufficient
if hasattr(os, 'add_dll_directory'):
# The variable might be empty, or might contain empty parts, so skip
# all empty items. There's no splitWithoutEmptyParts() like in Corrade,
# sigh. Using """ to prevent accidental syntax errors if the path
# itself would contain quotes.
for directory in """${MAGNUM_PYTHON_BINDINGS_DLL_PATH}""".split(';'):
if not directory:
continue
# If the directory is relative, interpret is as relative to parent
# dir. Also add it only if it exists.
bin_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), directory)
if os.path.exists(bin_path):
os.add_dll_directory(bin_path)
from _corrade import *
import sys
# In case Corrade is built statically, the whole core project is put into
# _corrade. The following feels extremely hackish, but without that it wouldn't
# be possible to do `import corrade.containers`, which is weird
# (`from corrade import containers` works, tho, for whatever reason)
for i in ['containers', 'pluginmanager', 'utility']:
if i in globals(): sys.modules['corrade.' + i] = globals()[i]
# Just to not have the variable leak into stubs generated by pybind11-stubgen
# TODO any way to exclude it?
del i
# Prevent all submodules being pulled in when saying `from corrade import *` --
# this is consistent with behavior in magnum
__all__ = [
# TARGET_*, BUILD_* are omitted as `from corrade import *` would pull them
# to globals and this would likely cause conflicts (magnum also defines
# BUILD_*)
]
# kate: hl python

22
src/python/corrade/bootstrap.h

@ -3,8 +3,7 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -26,20 +25,7 @@
DEALINGS IN THE SOFTWARE.
*/
#include <pybind11/detail/common.h> /* for PYBIND11_VERSION_* */
namespace pybind11 {
/* pybind11 2.6 changes py::module to py::module_ to be compatible with C++
modules. In order to be forward-compatible, we use module_ everywhere
and define it as an alias to module on < 2.6 */
#if PYBIND11_VERSION_MAJOR*100 + PYBIND11_VERSION_MINOR >= 206
class module_;
#else
class module;
typedef module module_;
#endif
}
namespace pybind11 { class module; }
namespace Corrade {}
namespace corrade {
@ -47,9 +33,7 @@ namespace corrade {
using namespace Corrade;
namespace py = pybind11;
void containers(py::module_& m);
void pluginmanager(py::module_& m);
void utility(py::module_& m);
void containers(py::module& m);
}

1043
src/python/corrade/containers.cpp

File diff suppressed because it is too large Load Diff

107
src/python/corrade/corrade.cpp

@ -1,8 +1,7 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
@ -29,8 +28,8 @@
#include "corrade/bootstrap.h"
#ifdef CORRADE_BUILD_STATIC
#include "corrade/staticconfigure.h"
#ifndef CORRADE_BUILD_STATIC
#error this file should be compiled only in the static build
#endif
namespace py = pybind11;
@ -39,104 +38,6 @@ namespace py = pybind11;
is released */
extern "C" PYBIND11_EXPORT PyObject* PyInit__corrade();
PYBIND11_MODULE(_corrade, m) {
m.doc() = "Root Corrade module";
m.attr("BUILD_DEPRECATED") =
#ifdef CORRADE_BUILD_DEPRECATED
true
#else
false
#endif
;
m.attr("BUILD_STATIC") =
#ifdef CORRADE_BUILD_STATIC
true
#else
false
#endif
;
m.attr("BUILD_MULTITHREADED") =
#ifdef CORRADE_BUILD_MULTITHREADED
true
#else
false
#endif
;
m.attr("TARGET_APPLE") =
#ifdef CORRADE_TARGET_APPLE
true
#else
false
#endif
;
m.attr("TARGET_IOS") =
#ifdef CORRADE_TARGET_IOS
true
#else
false
#endif
;
m.attr("TARGET_IOS_SIMULATOR") =
#ifdef CORRADE_TARGET_IOS_SIMULATOR
true
#else
false
#endif
;
m.attr("TARGET_UNIX") =
#ifdef CORRADE_TARGET_UNIX
true
#else
false
#endif
;
m.attr("TARGET_WINDOWS") =
#ifdef CORRADE_TARGET_WINDOWS
true
#else
false
#endif
;
m.attr("TARGET_WINDOWS_RT") =
#ifdef CORRADE_TARGET_WINDOWS_RT
true
#else
false
#endif
;
m.attr("TARGET_EMSCRIPTEN") =
#ifdef CORRADE_TARGET_EMSCRIPTEN
true
#else
false
#endif
;
m.attr("TARGET_ANDROID") =
#ifdef CORRADE_TARGET_ANDROID
true
#else
false
#endif
;
/* Not exposing CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT as this
is a plugin itself and so if this works, plugin manager should too */
/* In case Corrade is a bunch of static libraries, put everything into a
single shared lib to make it easier to install (which is the point of
static builds) and avoid issues with multiply-defined global symbols.
These need to be defined in the order they depend on. */
#ifdef CORRADE_BUILD_STATIC
py::module_ containers = m.def_submodule("containers");
py::module containers = m.def_submodule("containers");
corrade::containers(containers);
py::module_ utility = m.def_submodule("utility");
corrade::utility(utility);
/* PluginManager needs Utility::ConfigurationGroup, needs to be defined
after */
#ifdef Corrade_PluginManager_FOUND
py::module_ pluginmanager = m.def_submodule("pluginmanager");
corrade::pluginmanager(pluginmanager);
#endif
#endif
}

190
src/python/corrade/pluginmanager.cpp

@ -1,190 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "pluginmanager.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h> /* for pluginList() and aliasList() */
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Corrade/Containers/StringIterable.h>
#include <Corrade/PluginManager/AbstractManager.h>
#include <Corrade/PluginManager/AbstractPlugin.h>
#include <Corrade/PluginManager/PluginMetadata.h>
#include <Corrade/Utility/ConfigurationGroup.h>
#include "Corrade/PythonBindings.h"
#include "corrade/bootstrap.h"
#include "corrade/EnumOperators.h"
namespace corrade {
void pluginmanager(py::module_& m) {
m.doc() = "Plugin management";
#ifndef CORRADE_BUILD_STATIC
/* Need ConfigurationGroup from there. These are a part of the same module
in the static build, no need to import (also can't import because there
it's _corrade.*) */
py::module_::import("corrade.utility");
#endif
py::enum_<PluginManager::LoadState> loadState{m, "LoadState", "Plugin load state"};
loadState
.value("NOT_FOUND", PluginManager::LoadState::NotFound)
.value("WRONG_PLUGIN_VERSION", PluginManager::LoadState::WrongPluginVersion)
.value("WRONG_INTERFACE_VERSION", PluginManager::LoadState::WrongInterfaceVersion)
.value("WRONG_METADATA_FILE", PluginManager::LoadState::WrongMetadataFile)
.value("UNRESOLVED_DEPENDENCY", PluginManager::LoadState::UnresolvedDependency)
.value("STATIC", PluginManager::LoadState::Static)
.value("LOADED", PluginManager::LoadState::Loaded)
.value("NOT_LOADED", PluginManager::LoadState::NotLoaded)
.value("UNLOAD_FAILED", PluginManager::LoadState::UnloadFailed)
.value("REQUIRED", PluginManager::LoadState::Required)
.value("USED", PluginManager::LoadState::Used);
corrade::enumOperators(loadState);
py::class_<PluginManager::PluginMetadata>{m, "PluginMetadata", "Plugin metadata"}
.def_property_readonly("name", [](PluginManager::PluginMetadata& self) {
/** @todo drop std::string in favor of our own string caster */
return std::string{self.name()};
}, "Plugin name")
.def_property_readonly("depends", [](PluginManager::PluginMetadata& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.depends())
out.push_back(i);
return out;
}, "Plugins on which this plugin depends")
.def_property_readonly("used_by", [](PluginManager::PluginMetadata& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.usedBy())
out.push_back(i);
return out;
}, "Plugins which depend on this plugin")
.def_property_readonly("provides", [](PluginManager::PluginMetadata& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.provides())
out.push_back(i);
return out;
}, "Plugins which are provided by this plugin")
/** @todo data? no plugin uses this at the moment */
.def_property_readonly("configuration", static_cast<Utility::ConfigurationGroup&(PluginManager::PluginMetadata::*)()>(&PluginManager::PluginMetadata::configuration), "Initial plugin-specific configuration", py::return_value_policy::reference_internal);
PyNonDestructibleClass<PluginManager::AbstractManager> manager{m, "AbstractManager", "Base for plugin managers"};
manager.attr("VERSION") = PluginManager::AbstractManager::Version;
manager
.def_property_readonly("plugin_interface", [](PluginManager::AbstractManager& self) {
/** @todo drop std::string in favor of our own string caster */
return std::string{self.pluginInterface()};
}, "Plugin interface string")
.def_property("plugin_directory",
/** @todo drop std::string in favor of our own string caster */
[](PluginManager::AbstractManager& self) {
return std::string{self.pluginDirectory()};
}, [](PluginManager::AbstractManager& self, const std::string& directory) {
self.setPluginDirectory(directory);
}, "Plugin directory")
.def("reload_plugin_directory", &PluginManager::AbstractManager::reloadPluginDirectory, "Reload plugin directory")
.def("set_preferred_plugins", [](PluginManager::AbstractManager& self, const std::string& alias, const std::vector<std::string>& plugins) {
if(self.loadState(alias) == PluginManager::LoadState::NotFound) {
PyErr_SetNone(PyExc_KeyError);
throw py::error_already_set{};
}
/** @todo drop all this once StringIterable can be a view on
std::strings */
Containers::Array<Containers::StringView> pluginViews{NoInit, plugins.size()};
for(std::size_t i = 0; i != plugins.size(); ++i)
pluginViews[i] = plugins[i];
self.setPreferredPlugins(alias, pluginViews);
}, "Set preferred plugins for given alias", py::arg("alias"), py::arg("plugins"))
.def_property_readonly("plugin_list", [](PluginManager::AbstractManager& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.pluginList())
out.push_back(i);
return out;
}, "List of all available plugin names")
.def_property_readonly("alias_list", [](PluginManager::AbstractManager& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.aliasList())
out.push_back(i);
return out;
}, "List of all available alias names")
.def("metadata", [](PluginManager::AbstractManager& self, const std::string& plugin) {
return self.metadata(plugin);
}, "Plugin metadata", py::arg("plugin"), py::return_value_policy::reference_internal)
/** @todo drop std::string in favor of our own string caster */
.def("load_state", [](PluginManager::AbstractManager& self, const std::string& plugin) {
return self.loadState(plugin);
}, "Load state of a plugin", py::arg("plugin"))
.def("load", [](PluginManager::AbstractManager& self, const std::string& plugin) {
/** @todo log redirection -- but we'd need assertions to not be
part of that so when it dies, the user can still see why */
const PluginManager::LoadState state = self.load(plugin);
if(!(state & PluginManager::LoadState::Loaded)) {
PyErr_Format(PyExc_RuntimeError, "can't load plugin %s", plugin.data());
throw py::error_already_set{};
}
return state;
}, "Load a plugin", py::arg("plugin"))
.def("unload", [](PluginManager::AbstractManager& self, const std::string& plugin) {
/** @todo log redirection -- but we'd need assertions to not be
part of that so when it dies, the user can still see why */
const PluginManager::LoadState state = self.unload(plugin);
if(state != PluginManager::LoadState::NotLoaded && state != PluginManager::LoadState::Static) {
PyErr_Format(PyExc_RuntimeError, "can't unload plugin %s", plugin.data());
throw py::error_already_set{};
}
return state;
}, "Unload a plugin", py::arg("plugin"))
.def("register_external_manager", &PluginManager::AbstractManager::registerExternalManager, "Register an external manager for resolving inter-manager dependencies", py::arg("manager"), py::keep_alive<1, 2>());
py::class_<PluginManager::AbstractPlugin, PluginManager::PyPluginHolder<PluginManager::AbstractPlugin>>{m, "AbstractPlugin", "Base class for plugin interfaces"}
/* Plugin interface string, search paths, suffix, metadata file suffix
are meant to be overriden in subclasses */
.def_property_readonly("plugin", [](PluginManager::AbstractPlugin& self) {
/** @todo drop std::string in favor of our own string caster */
return std::string{self.plugin()};
}, "Plugin identifier string")
.def_property_readonly("metadata", &PluginManager::AbstractPlugin::metadata, "Plugin metadata", py::return_value_policy::reference_internal)
.def_property_readonly("configuration", static_cast<Utility::ConfigurationGroup&(PluginManager::AbstractPlugin::*)()>(&PluginManager::AbstractPlugin::configuration), "Plugin-specific configuration", py::return_value_policy::reference_internal);
}
}
#ifndef CORRADE_BUILD_STATIC
extern "C" PYBIND11_EXPORT PyObject* PyInit_pluginmanager();
PYBIND11_MODULE(pluginmanager, m) {
corrade::pluginmanager(m);
}
#endif

102
src/python/corrade/pluginmanager.h

@ -1,102 +0,0 @@
#ifndef corrade_pluginmanager_h
#define corrade_pluginmanager_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <memory> /* :( */
#include <pybind11/pybind11.h>
#include <pybind11/stl.h> /** @todo remove once I can return Array<String> directly */
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Corrade/PluginManager/Manager.h>
#include "Corrade/PythonBindings.h"
#include "Corrade/PluginManager/PythonBindings.h"
#include "corrade/bootstrap.h"
namespace corrade {
template<class T> void plugin(py::class_<T, PluginManager::PyPluginHolder<T>, PluginManager::AbstractPlugin>& c) {
c
.def_property_readonly_static("plugin_interface", [](const py::object&) {
/** @todo drop std::string in favor of our own string caster */
return std::string{T::pluginInterface()};
}, "Plugin interface string")
.def_property_readonly_static("plugin_search_paths", [](const py::object&) {
/** @todo drop std::string in favor of our own string caster */
std::vector<std::string> out;
for(auto&& i: T::pluginSearchPaths())
out.push_back(i);
return out;
}, "Plugin search paths")
.def_property_readonly_static("plugin_suffix", [](const py::object&) {
/** @todo drop std::string in favor of our own string caster */
return std::string{T::pluginSuffix()};
}, "Plugin binary suffix")
.def_property_readonly_static("plugin_metadata_suffix", [](const py::object&) {
/** @todo drop std::string in favor of our own string caster */
return std::string{T::pluginMetadataSuffix()};
}, "Plugin metadata file suffix")
/** @todo plugin interface string, search paths, suffix, metadata file
suffix (all are static properties) */
.def_property_readonly("manager", [](const T& self) {
return pyObjectHolderFor<PluginManager::PyPluginHolder>(self).manager;
}, "Manager owning this plugin instance");
}
template<class T> void manager(py::class_<PluginManager::Manager<T>, PluginManager::AbstractManager>& c) {
c
.def(py::init<const std::string&>(), py::arg("plugin_directory") = std::string{}, "Constructor")
.def("instantiate", [](PluginManager::Manager<T>& self, const std::string& plugin) {
/* This causes a double lookup, but well... better than dying */
if(!(self.loadState(plugin) & PluginManager::LoadState::Loaded)) {
PyErr_Format(PyExc_RuntimeError, "plugin %s is not loaded", plugin.data());
throw py::error_already_set{};
}
auto loaded = self.instantiate(plugin);
if(!loaded) {
PyErr_Format(PyExc_RuntimeError, "can't instantiate plugin %s", plugin.data());
throw py::error_already_set{};
}
return PluginManager::pyPluginHolder(std::move(loaded), py::cast(self));
}, "Instantiate a plugin")
.def("load_and_instantiate", [](PluginManager::Manager<T>& self, const std::string& plugin) {
auto loaded = self.loadAndInstantiate(plugin);
if(!loaded) {
PyErr_Format(PyExc_RuntimeError, "can't load and instantiate plugin %s", plugin.data());
throw py::error_already_set{};
}
return PluginManager::pyPluginHolder(std::move(loaded), py::cast(self));
}, "Load and instantiate plugin");
}
}
#endif

30
src/python/corrade/staticconfigure.h.cmake

@ -1,30 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* Named corrade/staticconfigure.h to avoid it colliding with Corrade/configure.h
on case-insensitive filesystems */
#cmakedefine Corrade_PluginManager_FOUND

36
src/python/corrade/test/CMakeLists.txt

@ -1,36 +0,0 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER
# property that would have to be set on each target separately.
set(CMAKE_FOLDER "Corrade/Python/Test")
foreach(_test optional stridedarrayview)
pybind11_add_module(test_${_test} ${pybind11_add_module_SYSTEM} test_${_test}.cpp)
target_include_directories(test_${_test} PRIVATE ${PROJECT_SOURCE_DIR}/src)
target_link_libraries(test_${_test} PRIVATE Corrade::Containers)
set_target_properties(test_${_test} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${output_dir})
endforeach()

8
src/python/corrade/test/__init__.py

@ -1,8 +1,7 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
@ -28,7 +27,4 @@ import os
import sys
# TODO: do this differently / more robustly
sys.path = [
os.path.join(os.path.dirname(__file__), os.environ.get('CMAKE_BINARY_DIR', '../../../../build'), 'src/python'),
os.path.join(os.path.dirname(__file__), os.environ.get('CMAKE_BINARY_DIR', '../../../../build'), 'src/python/Release')
] + sys.path
sys.path = [os.path.join(os.path.dirname(__file__), os.environ.get('CMAKE_BINARY_DIR', '../../../../build'), 'src/python')] + sys.path

1
src/python/corrade/test/broken.conf

@ -1 +0,0 @@
]]] yes this is invalid!!!

6
src/python/corrade/test/file.conf

@ -1,6 +0,0 @@
someKey=42
[someGroup]
value=hello
[someGroup/subgroup]
anotherValue=another
[emptyGroup]

1718
src/python/corrade/test/test_containers.py

File diff suppressed because it is too large Load Diff

186
src/python/corrade/test/test_containers_numpy.py

@ -1,186 +0,0 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022, 2023, 2024, 2025, 2026
# Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
import unittest
from corrade import containers
import test_stridedarrayview
try:
import numpy as np
except ModuleNotFoundError:
raise unittest.SkipTest("numpy not installed")
class StridedArrayViewCustomType(unittest.TestCase):
# This tests exposing statically typed StridedArrayView instances from C++,
# see StridedArrayViewCustomDynamicType below for types specified
# dynamically and types inherited from the buffer protocol. The short and
# mutable_int variants tested in test_containers, as for those memoryview
# works well... well, for one dimension it does.
def test_mutable_vector3d(self):
a = test_stridedarrayview.MutableContainer3d()
self.assertEqual(type(a.view), containers.MutableStridedArrayView2D)
self.assertEqual(a.view.format, 'ddd')
self.assertEqual(a.list, [
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0]
])
a.view[0][1] = [-765.6581, 3.5, 1.125]
a.view[1][2] = [4.666, 0.25, -7.5]
self.assertEqual(a.list, [
[0.0, 0.0, 0.0],
[-765.6581, 3.5, 1.125],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[4.666, 0.25, -7.5]
])
# memoryview ... doesn't understand the type. HAH
mav = memoryview(a.view[0])
with self.assertRaisesRegex(NotImplementedError, "unsupported format ddd"):
self.assertEqual(mav[1], [-765.6581, 3.5, 1.125])
# Test that numpy understands the type and has changes reflected
av = np.array(a.view, copy=False)
a.view[1][0] = [-3.33, 1.0, 0.0]
# Converting to a tuple, otherwise numpy always compares to False
self.assertEqual(tuple(av[1][0]), (-3.33, 1.0, 0.0))
self.assertEqual(tuple(av[1][1]), (0.0, 0.0, 0.0))
self.assertEqual(tuple(av[1][2]), (4.666, 0.25, -7.5))
# And the other way around as well
av[1][1] = (1.0, 0.125, 1.125)
self.assertEqual(a.list, [
[0.0, 0.0, 0.0],
[-765.6581, 3.5, 1.125],
[0.0, 0.0, 0.0],
[-3.33, 1.0, 0.0],
[1.0, 0.125, 1.125],
[4.666, 0.25, -7.5]
])
def test_mutable_long_float(self):
a = test_stridedarrayview.MutableContainerlf()
self.assertEqual(type(a.view), containers.MutableStridedArrayView2D)
self.assertEqual(a.view.format, 'Qf')
self.assertEqual(a.list, [
(0, 0.0),
(0, 0.0),
(0, 0.0),
(0, 0.0),
(0, 0.0),
(0, 0.0)
])
a.view[0][1] = (7656581356781257, 1.125)
a.view[1][2] = (4666025, -7.5)
self.assertEqual(a.list, [
(0, 0.0),
(7656581356781257, 1.125),
(0, 0.0),
(0, 0.0),
(0, 0.0),
(4666025, -7.5)
])
# memoryview ... doesn't understand the type. HAH
mav = memoryview(a.view[0])
with self.assertRaisesRegex(NotImplementedError, "unsupported format Qf"):
self.assertEqual(mav[1], (7656581356781257, 1.125))
# Test that numpy understands the type and has changes reflected
av = np.array(a.view, copy=False)
a.view[1][0] = (333106832, 0.0)
# Converting to a tuple, otherwise numpy always compares to False
self.assertEqual(tuple(av[1][0]), (333106832, 0.0))
self.assertEqual(tuple(av[1][1]), (0, 0.0))
self.assertEqual(tuple(av[1][2]), (4666025, -7.5))
# And the other way around as well
av[1][1] = (1001, 1.125)
self.assertEqual(a.list, [
(0, 0.0),
(7656581356781257, 1.125),
(0, 0.0),
(333106832, 0.0),
(1001, 1.125),
(4666025, -7.5)
])
class StridedArrayViewCustomDynamicType(unittest.TestCase):
def test_binding_short_short(self):
a = test_stridedarrayview.MutableContainerDynamicType('hh')
self.assertEqual(a.view.size, (2, 3))
self.assertEqual(a.view.stride, (12, 4))
self.assertEqual(a.view.format, 'hh')
# Test that numpy understands the type and has changes reflected
av = np.array(a.view, copy=False)
av[1][0] = (22563, -17665)
a.view[0][1] = (15, 34)
a.view[1][1] = (-22, 18)
# Converting to a tuple, otherwise numpy always compares to False
self.assertEqual(tuple(av[0][1]), (15, 34))
self.assertEqual(tuple(av[1][0]), (22563, -17665))
self.assertEqual(tuple(av[1][1]), (-22, 18))
# And the other way around as well
self.assertEqual(a.view[0][0], (0, 0))
self.assertEqual(a.view[0][1], (15, 34))
self.assertEqual(a.view[0][2], (0, 0))
self.assertEqual(a.view[1][0], (22563, -17665))
self.assertEqual(a.view[1][1], (-22, 18))
self.assertEqual(a.view[1][2], (0, 0))
def test_init_long(self):
a = np.array([[1, 2, 3], [-4, 5000000000, 6]], np.dtype('q'))
self.assertEqual(a.dtype, 'int64')
b = containers.MutableStridedArrayView2D(a)
self.assertEqual(b.size, (2, 3))
self.assertEqual(b.stride, (24, 8))
self.assertEqual(b.format, 'q')
b[1, 1] *= 2
self.assertEqual(b[0, 2], 3)
self.assertEqual(b[1, 0], -4)
self.assertEqual(b[1, 1], 10000000000)
def test_init_double(self):
a = np.array([[[1.0], [2.0]], [[-4.0], [5.0]]], np.dtype('d'))
self.assertEqual(a.dtype, 'float64')
b = containers.MutableStridedArrayView3D(a)
self.assertEqual(b.size, (2, 2, 1))
self.assertEqual(b.stride, (16, 8, 8))
self.assertEqual(b.format, 'd')
b[1, 1, 0] *= -2.0
self.assertEqual(b[0, 1, 0], 2.0)
self.assertEqual(b[1, 1, 0], -10.0)

76
src/python/corrade/test/test_optional.cpp

@ -1,76 +0,0 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022, 2023, 2024, 2025, 2026
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <pybind11/pybind11.h>
#include "../bootstrap.h" /* for module / _module alias */
#include "Corrade/Containers/OptionalPythonBindings.h"
using namespace Corrade;
namespace py = pybind11;
namespace {
struct Foo {
Foo(int a): a{a} {}
int a;
};
Containers::Optional<int> simpleType(bool set) {
return set ? Containers::optional(5) : Containers::NullOpt;
}
Containers::Optional<Foo> nestedType(bool set) {
return set ? Containers::optional(Foo{15}) : Containers::NullOpt;
}
int acquireSimpleType(Containers::Optional<int> value) {
return value ? *value : -1;
}
int acquireNestedType(Containers::Optional<Foo> value) {
return value ? value->a : -1;
}
}
/* TODO: remove declaration when https://github.com/pybind/pybind11/pull/1863
is released */
extern "C" PYBIND11_EXPORT PyObject* PyInit_test_optional();
PYBIND11_MODULE(test_optional, m) {
py::module_::import("corrade.containers");
py::class_<Foo>{m, "Foo"}
.def(py::init<int>())
.def_readwrite("a", &Foo::a);
m.def("simple_type", simpleType);
m.def("nested_type", nestedType);
m.def("acquire_simple_type", acquireSimpleType);
m.def("acquire_nested_type", acquireNestedType);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save