Browse Source

python: expose scenetools.{parents_breadth,children_depth}_first().

next
Vladimír Vondruš 3 years ago
parent
commit
8d9d7d3230
  1. 8
      doc/python/magnum.scenetools.rst
  2. 28
      src/python/magnum/scenetools.cpp
  3. 35
      src/python/magnum/test/test_scenetools.py

8
doc/python/magnum.scenetools.rst

@ -39,6 +39,14 @@
:raise AssertionError: If size of :p:`objects_to_keep` is different than :raise AssertionError: If size of :p:`objects_to_keep` is different than
:ref:`trade.SceneData.mapping_bound` :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 .. py:function:: magnum.scenetools.absolute_field_transformations2d
:raise KeyError: If :p:`field` does not exist in :p:`scene` :raise KeyError: If :p:`field` does not exist in :p:`scene`
:raise IndexError: If :p:`field_id` negative or not less than :raise IndexError: If :p:`field_id` negative or not less than

28
src/python/magnum/scenetools.cpp

@ -161,6 +161,34 @@ void scenetools(py::module_& m) {
return SceneTools::filterObjects(scene, objectsToKeep); return SceneTools::filterObjects(scene, objectsToKeep);
}, "Filter objects in a scene", py::arg("scene"), py::arg("objects_to_keep")) }, "Filter objects in a scene", py::arg("scene"), py::arg("objects_to_keep"))
.def("parents_breadth_first", [](const Trade::SceneData& scene) {
const Containers::Optional<UnsignedInt> parentFieldId = scene.findFieldId(Trade::SceneField::Parent);
if(!parentFieldId) {
PyErr_SetString(PyExc_AssertionError, "the scene has no hierarchy");
throw py::error_already_set{};
}
/** @todo ugh, add type converters for Corrade arrays already */
std::vector<std::pair<UnsignedInt, Int>> out{scene.fieldSize(*parentFieldId)};
SceneTools::parentsBreadthFirstInto(scene,
Containers::stridedArrayView(out).slice(&decltype(out)::value_type::first),
Containers::stridedArrayView(out).slice(&decltype(out)::value_type::second));
return out;
}, "Retrieve parents in a breadth-first order", py::arg("scene"))
.def("children_depth_first", [](const Trade::SceneData& scene) {
const Containers::Optional<UnsignedInt> parentFieldId = scene.findFieldId(Trade::SceneField::Parent);
if(!parentFieldId) {
PyErr_SetString(PyExc_AssertionError, "the scene has no hierarchy");
throw py::error_already_set{};
}
/** @todo ugh, add type converters for Corrade arrays already */
std::vector<std::pair<UnsignedInt, UnsignedInt>> out{scene.fieldSize(*parentFieldId)};
SceneTools::childrenDepthFirstInto(scene,
Containers::stridedArrayView(out).slice(&decltype(out)::value_type::first),
Containers::stridedArrayView(out).slice(&decltype(out)::value_type::second));
return out;
}, "Retrieve children in a depth-first order", py::arg("scene"))
.def("absolute_field_transformations2d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation) { .def("absolute_field_transformations2d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation) {
const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field); const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field);
if(!fieldId) { if(!fieldId) {

35
src/python/magnum/test/test_scenetools.py

@ -313,6 +313,41 @@ class Filter(unittest.TestCase):
scenetools.filter_objects(scene, containers.BitArray.value_init(3)) scenetools.filter_objects(scene, containers.BitArray.value_init(3))
class Hierarchy(unittest.TestCase): class Hierarchy(unittest.TestCase):
def test_parents_breadth_first_children_depth_first(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), "scene.gltf"))
scene = importer.scene(0)
parents_breadth_first = scenetools.parents_breadth_first(scene)
children_depth_first = scenetools.children_depth_first(scene)
self.assertEqual(parents_breadth_first, [
# Root objects first, parent always before all its children
(1, -1),
(2, -1),
(3, 2),
(0, 3)
])
self.assertEqual(children_depth_first, [
# Object 1 has no children
(1, 0),
# Object 2 has one direct child and one grandchild, etc
(2, 2),
(3, 1),
(0, 0)
])
def test_parents_breadth_first_children_depth_first_no_hierarchy(self):
importer = trade.ImporterManager().load_and_instantiate('GltfImporter')
importer.open_file(os.path.join(os.path.dirname(__file__), "scene.gltf"))
scene = scenetools.filter_except_fields(importer.scene(0), [trade.SceneField.PARENT])
with self.assertRaisesRegex(AssertionError, "the scene has no hierarchy"):
scenetools.parents_breadth_first(scene)
with self.assertRaisesRegex(AssertionError, "the scene has no hierarchy"):
scenetools.children_depth_first(scene)
def test_absolute_field_transformations2d(self): def test_absolute_field_transformations2d(self):
# Static builds with non-static plugins cause assertions with non-owned # Static builds with non-static plugins cause assertions with non-owned
# array deleters used by PrimitiveImporter, skip in that case # array deleters used by PrimitiveImporter, skip in that case

Loading…
Cancel
Save