nodePathCollection_ext.cxx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file nodePathCollection_ext.cxx
  10. * @author rdb
  11. * @date 2013-12-09
  12. */
  13. #include "nodePathCollection_ext.h"
  14. #ifdef HAVE_PYTHON
  15. #ifndef CPPPARSER
  16. extern struct Dtool_PyTypedObject Dtool_NodePath;
  17. #ifdef STDFLOAT_DOUBLE
  18. extern struct Dtool_PyTypedObject Dtool_LPoint3d;
  19. #else
  20. extern struct Dtool_PyTypedObject Dtool_LPoint3f;
  21. #endif
  22. #endif
  23. /**
  24. * This special constructor accepts a Python list of NodePaths. Since this
  25. * constructor accepts a generic PyObject *, it should be the last constructor
  26. * listed in the class record.
  27. */
  28. void Extension<NodePathCollection>::
  29. __init__(PyObject *self, PyObject *sequence) {
  30. PyObject *fast = PySequence_Fast(sequence, "NodePathCollection constructor requires a sequence");
  31. if (fast == nullptr) {
  32. return;
  33. }
  34. Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
  35. _this->reserve(size);
  36. for (int i = 0; i < size; ++i) {
  37. PyObject *item = PySequence_Fast_GET_ITEM(fast, i);
  38. if (item == nullptr) {
  39. return;
  40. }
  41. NodePath *path;
  42. if (!DtoolInstance_GetPointer(item, path, Dtool_NodePath)) {
  43. // Unable to add item--probably it wasn't of the appropriate type.
  44. std::ostringstream stream;
  45. stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath";
  46. std::string str = stream.str();
  47. PyErr_SetString(PyExc_TypeError, str.c_str());
  48. Py_DECREF(fast);
  49. return;
  50. } else {
  51. _this->add_path(*path);
  52. }
  53. }
  54. Py_DECREF(fast);
  55. }
  56. /**
  57. * This special Python method is implement to provide support for the pickle
  58. * module.
  59. */
  60. PyObject *Extension<NodePathCollection>::
  61. __reduce__(PyObject *self) const {
  62. // Here we will return a 4-tuple: (Class, (args), None, iterator), where
  63. // iterator is an iterator that will yield successive NodePaths.
  64. // We should return at least a 2-tuple, (Class, (args)): the necessary class
  65. // object whose constructor we should call (e.g. this), and the arguments
  66. // necessary to reconstruct this object.
  67. PyObject *this_class = (PyObject *)self->ob_type;
  68. if (this_class == nullptr) {
  69. return nullptr;
  70. }
  71. PyObject *self_iter = PyObject_GetIter(self);
  72. if (self_iter == nullptr) {
  73. return nullptr;
  74. }
  75. // Since a NodePathCollection is itself an iterator, we can simply pass it
  76. // as the fourth tuple component.
  77. return Py_BuildValue("(O()ON)", this_class, Py_None, self_iter);
  78. }
  79. /**
  80. * Returns the tight bounds as a 2-tuple of LPoint3 objects. This is a
  81. * convenience function for Python users, among which the use of
  82. * calc_tight_bounds may be confusing. Returns None if calc_tight_bounds
  83. * returned false.
  84. */
  85. PyObject *Extension<NodePathCollection>::
  86. get_tight_bounds() const {
  87. LPoint3 *min_point = new LPoint3;
  88. LPoint3 *max_point = new LPoint3;
  89. if (_this->calc_tight_bounds(*min_point, *max_point)) {
  90. #ifdef STDFLOAT_DOUBLE
  91. PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3d, true, false);
  92. PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3d, true, false);
  93. #else
  94. PyObject *min_inst = DTool_CreatePyInstance((void*) min_point, Dtool_LPoint3f, true, false);
  95. PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false);
  96. #endif
  97. return Py_BuildValue("NN", min_inst, max_inst);
  98. }
  99. else {
  100. return Py_NewRef(Py_None);
  101. }
  102. }
  103. #endif // HAVE_PYTHON