Browse Source

python: support bit field access in SceneData.

next
Vladimír Vondruš 3 years ago
parent
commit
007fe23731
  1. 8
      src/python/magnum/test/scene.gltf
  2. 69
      src/python/magnum/test/test_trade.py
  3. 33
      src/python/magnum/trade.cpp

8
src/python/magnum/test/scene.gltf

@ -40,14 +40,18 @@
"camera": 1,
"extras": {
"aNumber": 5,
"aString": "hello!"
"aString": "hello!",
"yes": true
},
"children": [3]
},
{
"camera": 0,
"translation": [4, 5, 6],
"children": [0]
"children": [0],
"extras": {
"yes": false
}
},
{
"name": "A broken node",

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

@ -29,7 +29,7 @@ import sys
import tempfile
import unittest
from corrade import pluginmanager
from corrade import containers, pluginmanager
from magnum import *
from magnum import primitives, trade
import magnum
@ -723,7 +723,7 @@ class SceneData(unittest.TestCase):
scene = importer.scene(0)
self.assertEqual(scene.mapping_type, trade.SceneMappingType.UNSIGNED_INT)
self.assertEqual(scene.mapping_bound, 4)
self.assertEqual(scene.field_count, 7)
self.assertEqual(scene.field_count, 8)
# TODO add some array extras once supported to have this different from
# the mapping bound
self.assertEqual(scene.field_size_bound, 4)
@ -821,8 +821,12 @@ class SceneData(unittest.TestCase):
scene = importer.scene(0)
scene_refcount = sys.getrefcount(scene)
translation_id = scene.field_id(trade.SceneField.TRANSLATION)
scene_field_yes = importer.scene_field_for_name('yes')
self.assertIsNotNone(scene_field_yes)
yes_id = scene.field_id(scene_field_yes)
translations = scene.field(translation_id)
self.assertIsInstance(translations, containers.StridedArrayView1D)
self.assertEqual(translations.size, (3, ))
self.assertEqual(translations.stride, (12, ))
self.assertEqual(translations.format, '3f')
@ -838,6 +842,7 @@ class SceneData(unittest.TestCase):
self.assertEqual(sys.getrefcount(scene), scene_refcount)
cameras = scene.field(trade.SceneField.CAMERA)
self.assertIsInstance(cameras, containers.StridedArrayView1D)
self.assertEqual(cameras.size, (2, ))
self.assertEqual(cameras.stride, (4, ))
self.assertEqual(cameras.format, 'I')
@ -848,7 +853,26 @@ class SceneData(unittest.TestCase):
del cameras
self.assertEqual(sys.getrefcount(scene), scene_refcount)
yeses1 = scene.field(scene_field_yes)
yeses2 = scene.field(yes_id)
self.assertIsInstance(yeses1, containers.StridedBitArrayView1D)
self.assertIsInstance(yeses2, containers.StridedBitArrayView1D)
self.assertEqual(yeses1.size, (2, ))
self.assertEqual(yeses2.size, (2, ))
self.assertEqual(yeses1.stride, (1, ))
self.assertEqual(yeses2.stride, (1, ))
self.assertEqual(list(yeses1), [True, False])
self.assertEqual(list(yeses2), [True, False])
self.assertIs(yeses1.owner, scene)
self.assertIs(yeses2.owner, scene)
self.assertEqual(sys.getrefcount(scene), scene_refcount + 2)
del yeses1
del yeses2
self.assertEqual(sys.getrefcount(scene), scene_refcount)
mutable_translations = scene.mutable_field(translation_id)
self.assertIsInstance(mutable_translations, containers.MutableStridedArrayView1D)
self.assertEqual(mutable_translations.size, (3, ))
self.assertEqual(mutable_translations.stride, (12, ))
self.assertEqual(mutable_translations.format, '3f')
@ -864,6 +888,7 @@ class SceneData(unittest.TestCase):
self.assertEqual(sys.getrefcount(scene), scene_refcount)
mutable_cameras = scene.mutable_field(trade.SceneField.CAMERA)
self.assertIsInstance(mutable_cameras, containers.MutableStridedArrayView1D)
self.assertEqual(mutable_cameras.size, (2, ))
self.assertEqual(mutable_cameras.stride, (4, ))
self.assertEqual(mutable_cameras.format, 'I')
@ -874,6 +899,24 @@ class SceneData(unittest.TestCase):
del mutable_cameras
self.assertEqual(sys.getrefcount(scene), scene_refcount)
mutable_yeses1 = scene.mutable_field(scene_field_yes)
mutable_yeses2 = scene.mutable_field(yes_id)
self.assertIsInstance(mutable_yeses1, containers.MutableStridedBitArrayView1D)
self.assertIsInstance(mutable_yeses2, containers.MutableStridedBitArrayView1D)
self.assertEqual(mutable_yeses1.size, (2, ))
self.assertEqual(mutable_yeses2.size, (2, ))
self.assertEqual(mutable_yeses1.stride, (1, ))
self.assertEqual(mutable_yeses2.stride, (1, ))
self.assertEqual(list(mutable_yeses1), [True, False])
self.assertEqual(list(mutable_yeses2), [True, False])
self.assertIs(mutable_yeses1.owner, scene)
self.assertIs(mutable_yeses2.owner, scene)
self.assertEqual(sys.getrefcount(scene), scene_refcount + 2)
del mutable_yeses1
del mutable_yeses2
self.assertEqual(sys.getrefcount(scene), scene_refcount)
def test_mutable_mapping_access(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'scene.gltf'))
@ -922,6 +965,24 @@ class SceneData(unittest.TestCase):
mutable_cameras[1] = 13378
self.assertEqual(cameras[1], 13378)
scene_field_yes = importer.scene_field_for_name('yes')
self.assertIsNotNone(scene_field_yes)
yes_id = scene.field_id(scene_field_yes)
yeses1 = scene.field(scene_field_yes)
yeses2 = scene.field(yes_id)
mutable_yeses1 = scene.mutable_field(scene_field_yes)
mutable_yeses2 = scene.mutable_field(yes_id)
self.assertEqual(yeses1[0], True)
self.assertEqual(yeses2[1], False)
self.assertEqual(mutable_yeses1[0], True)
self.assertEqual(mutable_yeses2[1], False)
mutable_yeses1[0] = False
mutable_yeses2[1] = True
self.assertEqual(yeses1[0], False)
self.assertEqual(yeses2[1], True)
def test_pointer_field_access(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), 'scene.gltf'))
@ -1375,7 +1436,7 @@ class Importer(unittest.TestCase):
self.assertEqual(importer.scene_field_for_name('aString'), trade.SceneField.CUSTOM(1))
scene = importer.scene(0)
self.assertEqual(scene.field_count, 7)
self.assertEqual(scene.field_count, 8)
self.assertTrue(scene.has_field(importer.scene_field_for_name('aString')))
def test_scene_by_name(self):
@ -1383,7 +1444,7 @@ class Importer(unittest.TestCase):
importer.open_file(os.path.join(os.path.dirname(__file__), 'scene.gltf'))
scene = importer.scene("A scene")
self.assertEqual(scene.field_count, 7)
self.assertEqual(scene.field_count, 8)
def test_scene_by_name_not_found(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')

33
src/python/magnum/trade.cpp

@ -26,6 +26,7 @@
#include <pybind11/pybind11.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StridedBitArrayView.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Corrade/Containers/Triple.h>
#include <Magnum/ImageView.h>
@ -1407,26 +1408,30 @@ void trade(py::module_& m) {
PyErr_SetNone(PyExc_KeyError);
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */
/** @todo handle arrays (return a 2D (bit) view) */
if(self.fieldArraySize(*found) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array fields not implemented yet, sorry");
throw py::error_already_set{};
}
return sceneFieldView(self, *found, self.field(*found));
/** @todo annotate the return type properly in the docs */
if(self.fieldType(*found) == Trade::SceneFieldType::Bit)
return pyCastButNotShitty(Containers::pyArrayViewHolder(self.fieldBits(*found), py::cast(self)));
return pyCastButNotShitty(sceneFieldView(self, *found, self.field(*found)));
}, "Data for given named field", py::arg("name"))
.def("field", [](Trade::SceneData& self, UnsignedInt id) {
if(id >= self.fieldCount()) {
PyErr_SetNone(PyExc_IndexError);
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */
/** @todo handle arrays (return a 2D (bit) view) */
if(self.fieldArraySize(id) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array fields not implemented yet, sorry");
throw py::error_already_set{};
}
return sceneFieldView(self, id, self.field(id));
/** @todo annotate the return type properly in the docs */
if(self.fieldType(id) == Trade::SceneFieldType::Bit)
return pyCastButNotShitty(Containers::pyArrayViewHolder(self.fieldBits(id), py::cast(self)));
return pyCastButNotShitty(sceneFieldView(self, id, self.field(id)));
}, "Data for given field", py::arg("name"))
.def("mutable_field", [](Trade::SceneData& self, Trade::SceneField name) {
const Containers::Optional<UnsignedInt> found = self.findFieldId(name);
@ -1438,13 +1443,15 @@ void trade(py::module_& m) {
PyErr_SetString(PyExc_AttributeError, "scene data is not mutable");
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */
/** @todo handle arrays (return a 2D (bit) view) */
if(self.fieldArraySize(*found) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array fields not implemented yet, sorry");
throw py::error_already_set{};
}
return sceneFieldView(self, *found, self.mutableField(*found));
/** @todo annotate the return type properly in the docs */
if(self.fieldType(*found) == Trade::SceneFieldType::Bit)
return pyCastButNotShitty(Containers::pyArrayViewHolder(self.mutableFieldBits(*found), py::cast(self)));
return pyCastButNotShitty(sceneFieldView(self, *found, self.mutableField(*found)));
}, "Mutable data for given named field", py::arg("name"))
.def("mutable_field", [](Trade::SceneData& self, UnsignedInt id) {
if(id >= self.fieldCount()) {
@ -1455,13 +1462,15 @@ void trade(py::module_& m) {
PyErr_SetString(PyExc_AttributeError, "scene data is not mutable");
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */
/** @todo handle arrays (return a 2D (bit) view) */
if(self.fieldArraySize(id) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array fields not implemented yet, sorry");
throw py::error_already_set{};
}
return sceneFieldView(self, id, self.mutableField(id));
/** @todo annotate the return type properly in the docs */
if(self.fieldType(id) == Trade::SceneFieldType::Bit)
return pyCastButNotShitty(Containers::pyArrayViewHolder(self.mutableFieldBits(id), py::cast(self)));
return pyCastButNotShitty(sceneFieldView(self, id, self.mutableField(id)));
}, "Mutable data for given field", py::arg("name"))
.def_property_readonly("owner", [](Trade::SceneData& self) {

Loading…
Cancel
Save