Browse Source

python: expose trade.TextureData and related importer APIs.

next
Vladimír Vondruš 3 years ago
parent
commit
513fbc547d
  1. 16
      doc/python/magnum.trade.rst
  2. 15
      src/python/magnum/test/image.gltf
  3. 60
      src/python/magnum/test/test_trade.py
  4. 36
      src/python/magnum/test/texture.gltf
  5. 30
      src/python/magnum/trade.cpp

16
doc/python/magnum.trade.rst

@ -402,6 +402,22 @@
:raise IndexError: If :p:`id` is negative or not less than :ref:`mesh_count`
:raise KeyError: If :p:`name` was not found
.. py:property:: magnum.trade.AbstractImporter.texture_count
:raise AssertionError: If no file is opened
.. py:function:: magnum.trade.AbstractImporter.texture_for_name
:raise AssertionError: If no file is opened
.. py:function:: magnum.trade.AbstractImporter.texture_name
:raise AssertionError: If no file is opened
:raise IndexError: If :p:`id` is negative or not less than :ref:`texture_count`
.. TODO this needs distinction by parameter names, at least
.. py:function:: magnum.trade.AbstractImporter.texture
:raise AssertionError: If no file is opened
:raise RuntimeError: If texture import fails
:raise IndexError: If :p:`id` is negative or not less than :ref:`texture_count`
:raise KeyError: If :p:`name` was not found
.. py:property:: magnum.trade.AbstractImporter.image1d_count
:raise AssertionError: If no file is opened
.. py:property:: magnum.trade.AbstractImporter.image2d_count

15
src/python/magnum/test/image.gltf

@ -1,15 +0,0 @@
{
"asset": {
"version": "2.0"
},
"images": [
{
"uri": "nonexistent.foo",
"name": "A broken image"
},
{
"uri": "rgb.png",
"name": "A named image"
}
]
}

60
src/python/magnum/test/test_trade.py

@ -66,6 +66,8 @@ class ImageData(unittest.TestCase):
image.pixel_size
with self.assertRaisesRegex(AttributeError, "image is compressed"):
image.pixels
with self.assertRaisesRegex(AttributeError, "image is compressed"):
image.mutable_pixels
def test_convert_view(self):
# The only way to get an image instance is through a manager
@ -1044,6 +1046,19 @@ class SceneData(unittest.TestCase):
with self.assertRaisesRegex(NotImplementedError, "access to this scene field type is not implemented yet, sorry"):
scene.mutable_field(string_field)
class SceneData(unittest.TestCase):
def test(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
texture = importer.texture("A texture")
self.assertEqual(texture.type, trade.TextureType.TEXTURE2D)
self.assertEqual(texture.minification_filter, SamplerFilter.NEAREST)
self.assertEqual(texture.magnification_filter, SamplerFilter.LINEAR)
self.assertEqual(texture.mipmap_filter, SamplerMipmap.NEAREST)
self.assertEqual(texture.wrapping, (SamplerWrapping.MIRRORED_REPEAT, SamplerWrapping.CLAMP_TO_EDGE, SamplerWrapping.REPEAT))
self.assertEqual(texture.image, 1)
class Importer(unittest.TestCase):
def test_manager(self):
manager = trade.ImporterManager()
@ -1232,6 +1247,17 @@ class Importer(unittest.TestCase):
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.mesh('')
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.texture_count
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.texture_for_name('')
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.texture_name(0)
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.texture(0)
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.texture('')
with self.assertRaisesRegex(AssertionError, "no file opened"):
importer.image1d_count
with self.assertRaisesRegex(AssertionError, "no file opened"):
@ -1287,6 +1313,11 @@ class Importer(unittest.TestCase):
with self.assertRaisesRegex(IndexError, "ID out of bounds"):
importer.mesh(0)
with self.assertRaises(IndexError):
importer.texture_name(0)
with self.assertRaises(IndexError):
importer.texture(0)
with self.assertRaises(IndexError):
importer.image1d_level_count(0)
with self.assertRaises(IndexError):
@ -1438,6 +1469,29 @@ class Importer(unittest.TestCase):
with self.assertRaisesRegex(RuntimeError, "import failed"):
importer.mesh('A broken mesh')
def test_texture_by_name(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
texture = importer.texture("A texture")
self.assertEqual(texture.image, 1)
def test_texture_by_name_not_found(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
with self.assertRaises(KeyError):
importer.texture('Nonexistent')
def test_texture_failed(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
with self.assertRaisesRegex(RuntimeError, "import failed"):
importer.texture(1)
with self.assertRaisesRegex(RuntimeError, "import failed"):
importer.texture("A broken texture")
def test_image2d(self):
manager = trade.ImporterManager()
manager_refcount = sys.getrefcount(manager)
@ -1471,14 +1525,14 @@ class Importer(unittest.TestCase):
def test_image2d_by_name(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'image.gltf'))
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
image = importer.image2d('A named image')
self.assertEqual(image.size, Vector2i(3, 2))
def test_image2d_by_name_not_found(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'image.gltf'))
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
with self.assertRaises(KeyError):
importer.image2d('Nonexistent')
@ -1494,7 +1548,7 @@ class Importer(unittest.TestCase):
def test_image2d_failed(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'image.gltf'))
importer.open_file(os.path.join(os.path.dirname(__file__), 'texture.gltf'))
with self.assertRaisesRegex(RuntimeError, "import failed"):
importer.image2d(0)

36
src/python/magnum/test/texture.gltf

@ -0,0 +1,36 @@
{
"asset": {
"version": "2.0"
},
"images": [
{
"uri": "nonexistent.foo",
"name": "A broken image"
},
{
"uri": "rgb.png",
"name": "A named image"
}
],
"samplers": [
{
"wrapS": 33648,
"wrapT": 33071,
"minFilter": 9984,
"magFilter": 9729
}
],
"textures": [
{
"source": 0
},
{
"name": "A broken texture"
},
{
"name": "A texture",
"sampler": 0,
"source": 1
}
]
}

30
src/python/magnum/trade.cpp

@ -42,6 +42,7 @@
#include <Magnum/Trade/ImageData.h>
#include <Magnum/Trade/MeshData.h>
#include <Magnum/Trade/SceneData.h>
#include <Magnum/Trade/TextureData.h>
#include "Corrade/Containers/PythonBindings.h"
#include "Corrade/Containers/OptionalPythonBindings.h"
@ -1453,6 +1454,29 @@ void trade(py::module_& m) {
return sceneFieldView(self, id, self.mutableField(id));
}, "Mutable data for given field", py::arg("name"));
py::enum_<Trade::TextureType>{m, "TextureType", "Texture type"}
.value("TEXTURE1D", Trade::TextureType::Texture1D)
.value("TEXTURE1D_ARRAY", Trade::TextureType::Texture1DArray)
.value("TEXTURE2D", Trade::TextureType::Texture2D)
.value("TEXTURE2D_ARRAY", Trade::TextureType::Texture2DArray)
.value("TEXTURE3D", Trade::TextureType::Texture3D)
.value("CUBE_MAP", Trade::TextureType::CubeMap)
.value("CUBE_MAP_ARRAY", Trade::TextureType::CubeMapArray);
py::class_<Trade::TextureData>{m, "TextureData", "Texture data"}
.def_property_readonly("type", &Trade::TextureData::type, "Texture type")
.def_property_readonly("minification_filter", &Trade::TextureData::minificationFilter, "Minification filter")
.def_property_readonly("magnification_filter", &Trade::TextureData::magnificationFilter, "Magnification filter")
.def_property_readonly("mipmap_filter", &Trade::TextureData::mipmapFilter, "Mipmap filter")
.def_property_readonly("wrapping", [](Trade::TextureData& self) {
return std::make_tuple(
self.wrapping()[0],
self.wrapping()[1],
self.wrapping()[2]
);
}, "Wrapping")
.def_property_readonly("image", &Trade::TextureData::image, "Image ID");
/* Importer. Skipping file callbacks and openState as those operate with
void*. Leaving the name as AbstractImporter (instead of Importer) to
avoid needless name differences and because in the future there *might*
@ -1555,6 +1579,12 @@ void trade(py::module_& m) {
return {};
}, "String name for given custom mesh attribute", py::arg("name"))
.def_property_readonly("texture_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::textureCount>, "Texture count")
.def("texture_for_name", checkOpenedString<Int, &Trade::AbstractImporter::textureForName>, "Texture ID for given name", py::arg("name"))
.def("texture_name", checkOpenedBoundsReturnsString<UnsignedInt, &Trade::AbstractImporter::textureName, &Trade::AbstractImporter::textureCount>, "Texture name", py::arg("id"))
.def("texture", checkOpenedBoundsResult<Trade::TextureData, &Trade::AbstractImporter::texture, &Trade::AbstractImporter::textureCount>, "Texture", py::arg("id"))
.def("texture", checkOpenedBoundsResultString<Trade::TextureData, &Trade::AbstractImporter::texture, &Trade::AbstractImporter::textureForName>, "Texture for given name", py::arg("name"))
.def_property_readonly("image1d_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::image1DCount>, "One-dimensional image count")
.def_property_readonly("image2d_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::image2DCount>, "Two-dimensional image count")
.def_property_readonly("image3d_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::image3DCount>, "Three-dimensional image count")

Loading…
Cancel
Save