1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 // This file is generated by a script. Do not edit directly. Edit the
26 // wrapVec.template.cpp file to make changes.
27
28 #include "pxr/pxr.h"
29 #include "pxr/base/gf/vec2i.h"
30
31 #include "pxr/base/gf/pyBufferUtils.h"
32
33 #include "pxr/base/tf/py3Compat.h"
34 #include "pxr/base/tf/pyContainerConversions.h"
35 #include "pxr/base/tf/pyUtils.h"
36 #include "pxr/base/tf/stringUtils.h"
37 #include "pxr/base/tf/wrapTypeHelpers.h"
38
39
40 #include <boost/python/class.hpp>
41 #include <boost/python/def.hpp>
42 #include <boost/python/make_constructor.hpp>
43 #include <boost/python/operators.hpp>
44 #include <boost/python/overloads.hpp>
45 #include <boost/python/tuple.hpp>
46 #include <boost/python/slice.hpp>
47
48 #include <boost/functional/hash.hpp>
49
50 #include <string>
51
52 using namespace boost::python;
53
54 using std::string;
55
56 PXR_NAMESPACE_USING_DIRECTIVE
57
58 namespace {
59
60 ////////////////////////////////////////////////////////////////////////
61 // Python buffer protocol support.
62
63 #if PY_MAJOR_VERSION == 2
64 // Python's getreadbuf interface function.
65 static Py_ssize_t
getreadbuf(PyObject * self,Py_ssize_t segment,void ** ptrptr)66 getreadbuf(PyObject *self, Py_ssize_t segment, void **ptrptr) {
67 if (segment != 0) {
68 // Always one-segment.
69 PyErr_SetString(PyExc_ValueError, "accessed non-existent segment");
70 return -1;
71 }
72 GfVec2i &vec = extract<GfVec2i &>(self);
73 *ptrptr = static_cast<void *>(vec.data());
74 // Return size in bytes.
75 return sizeof(GfVec2i);
76 }
77
78 // Python's getwritebuf interface function.
79 static Py_ssize_t
getwritebuf(PyObject * self,Py_ssize_t segment,void ** ptrptr)80 getwritebuf(PyObject *self, Py_ssize_t segment, void **ptrptr) {
81 PyErr_SetString(PyExc_ValueError, "writable buffers supported only with "
82 "new-style buffer protocol.");
83 return -1;
84 }
85
86 // Python's getsegcount interface function.
87 static Py_ssize_t
getsegcount(PyObject * self,Py_ssize_t * lenp)88 getsegcount(PyObject *self, Py_ssize_t *lenp) {
89 if (lenp)
90 *lenp = sizeof(GfVec2i);
91 return 1; // Always one contiguous segment.
92 }
93
94 // Python's getcharbuf interface function.
95 static Py_ssize_t
getcharbuf(PyObject * self,Py_ssize_t segment,const char ** ptrptr)96 getcharbuf(PyObject *self, Py_ssize_t segment, const char **ptrptr) {
97 PyErr_SetString(PyExc_ValueError, "cannot treat binary data as text");
98 return -1;
99 }
100 #endif
101
102 // Python's getbuffer interface function.
103 static int
getbuffer(PyObject * self,Py_buffer * view,int flags)104 getbuffer(PyObject *self, Py_buffer *view, int flags) {
105 if (view == NULL) {
106 PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
107 return -1;
108 }
109
110 // We don't support fortran order.
111 if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) {
112 PyErr_SetString(PyExc_ValueError, "Fortran contiguity unsupported");
113 return -1;
114 }
115
116 GfVec2i &vec = extract<GfVec2i &>(self);
117
118 view->obj = self;
119 view->buf = static_cast<void *>(vec.data());
120 view->len = sizeof(GfVec2i);
121 view->readonly = 0;
122 view->itemsize = sizeof(int);
123 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
124 view->format = Gf_GetPyBufferFmtFor<int>();
125 } else {
126 view->format = NULL;
127 }
128 if ((flags & PyBUF_ND) == PyBUF_ND) {
129 view->ndim = 1;
130 static Py_ssize_t shape = 2;
131 view->shape = &shape;
132 } else {
133 view->ndim = 0;
134 view->shape = NULL;
135 }
136 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
137 static Py_ssize_t strides = sizeof(int);
138 view->strides = &strides;
139 } else {
140 view->strides = NULL;
141 }
142 view->suboffsets = NULL;
143 view->internal = NULL;
144
145 Py_INCREF(self); // need to retain a reference to self.
146 return 0;
147 }
148
149 // This structure serves to instantiate a PyBufferProcs instance with pointers
150 // to the right buffer protocol functions.
151 static PyBufferProcs bufferProcs = {
152 #if PY_MAJOR_VERSION == 2
153 (readbufferproc) getreadbuf, /*bf_getreadbuffer*/
154 (writebufferproc) getwritebuf, /*bf_getwritebuffer*/
155 (segcountproc) getsegcount, /*bf_getsegcount*/
156 (charbufferproc) getcharbuf, /*bf_getcharbuffer*/
157 #endif
158 (getbufferproc) getbuffer,
159 (releasebufferproc) 0,
160 };
161
162 // End python buffer protocol support.
163 ////////////////////////////////////////////////////////////////////////
164
165
__repr__(GfVec2i const & self)166 static string __repr__(GfVec2i const &self) {
167 string elems;
168 for (size_t i = 0; i < self.dimension; ++i)
169 elems += (i ? ", " : "") + TfPyRepr(self[i]);
170
171 return TF_PY_REPR_PREFIX + "Vec2i(" + elems + ")";
172 }
173
__hash__(GfVec2i const & self)174 static size_t __hash__(GfVec2i const &self) {
175 return boost::hash<GfVec2i>()(self);
176 }
177
178
179
180
181 static int
normalizeIndex(int index)182 normalizeIndex(int index) {
183 return TfPyNormalizeIndex(index, 2, true /*throw error*/);
184 }
185
__len__(const GfVec2i & self)186 static int __len__(const GfVec2i &self) { return 2; }
187
188 // Implements __getitem__ for a single index
__getitem__(const GfVec2i & self,int index)189 static int __getitem__(const GfVec2i &self, int index) {
190 return self[normalizeIndex(index)];
191 }
192
193 // Implements __getitem__ for a slice
__getslice__(const GfVec2i & self,slice indices)194 static list __getslice__(const GfVec2i &self, slice indices) {
195 list result;
196
197 const int* begin = self.data();
198 const int* end = begin + 2;
199
200 slice::range<const int*> bounds;
201 try {
202 // This appears to be a typo in the boost headers. The method
203 // name should be "get_indices".
204 //
205 bounds = indices.get_indicies<>(begin, end);
206 } catch (std::invalid_argument) {
207 return result;
208 }
209
210 while (bounds.start != bounds.stop) {
211 result.append(*bounds.start);
212 bounds.start += bounds.step;
213 }
214 // Unlike STL ranges, bounds represents a *closed* interval. This
215 // means that we must append exactly one more item at the end of
216 // the list.
217 //
218 result.append(*bounds.start);
219
220 return result;
221 }
222
__setitem__(GfVec2i & self,int index,int value)223 static void __setitem__(GfVec2i &self, int index, int value) {
224 self[normalizeIndex(index)] = value;
225 }
226
227 // Handles refcounting & extraction for PySequence_GetItem.
_SequenceGetItem(PyObject * seq,Py_ssize_t i)228 static int _SequenceGetItem(PyObject *seq, Py_ssize_t i) {
229 boost::python::handle<> h(PySequence_GetItem(seq, i));
230 return extract<int>(boost::python::object(h));
231 }
232
_SequenceCheckItem(PyObject * seq,Py_ssize_t i)233 static bool _SequenceCheckItem(PyObject *seq, Py_ssize_t i) {
234 boost::python::handle<> h(PySequence_GetItem(seq, i));
235 extract<int> e((boost::python::object(h)));
236 return e.check();
237 }
238
__setslice__(GfVec2i & self,slice indices,object values)239 static void __setslice__(GfVec2i &self, slice indices, object values) {
240 // Verify our arguments
241 //
242 PyObject* valuesObj = values.ptr();
243
244 if (!PySequence_Check(valuesObj)) {
245 TfPyThrowTypeError("value must be a sequence");
246 }
247
248 int* begin = self.data();
249 int* end = begin + 2;
250
251 Py_ssize_t sliceLength = -1;
252
253 slice::range<int*> bounds;
254
255 // Convince g++ that we're not using uninitialized values.
256 //
257 bounds.start = 0;
258 bounds.stop = 0;
259 bounds.step = 0;
260
261 try {
262 // This appears to be a typo in the boost headers. The method
263 // name should be "get_indices".
264 //
265 bounds = indices.get_indicies<>(begin, end);
266 } catch (std::invalid_argument) {
267 sliceLength = 0;
268 }
269
270 // If sliceLength was not set in the exception handling code above,
271 // figure out how long it really is.
272 //
273 if (sliceLength == -1) {
274 sliceLength = ((bounds.stop - bounds.start) / bounds.step) + 1;
275 }
276
277 if (PySequence_Length(valuesObj) != sliceLength) {
278 TfPyThrowValueError(
279 TfStringPrintf(
280 "attempt to assign sequence of size %zd to slice of size %zd",
281 PySequence_Length(valuesObj), sliceLength));
282 }
283
284 // Short circuit for empty slices
285 //
286 if (sliceLength == 0) {
287 return;
288 }
289
290 // Make sure that all items can be extracted before changing the GfVec2i.
291 //
292 for (Py_ssize_t i = 0; i < sliceLength; ++i) {
293 // This will throw a TypeError if any of the items cannot be converted.
294 _SequenceGetItem(valuesObj, i);
295 }
296
297 for (Py_ssize_t i = 0; i < sliceLength; ++i) {
298 *bounds.start = _SequenceGetItem(valuesObj, i);
299 bounds.start += bounds.step;
300 }
301 }
302
__contains__(const GfVec2i & self,int value)303 static bool __contains__(const GfVec2i &self, int value) {
304 for (size_t i = 0; i < 2; ++i) {
305 if (self[i] == value)
306 return true;
307 }
308 return false;
309 }
310
311 #if PY_MAJOR_VERSION == 2
__truediv__(const GfVec2i & self,int value)312 static GfVec2i __truediv__(const GfVec2i &self, int value)
313 {
314 return self / value;
315 }
316
__itruediv__(GfVec2i & self,int value)317 static GfVec2i __itruediv__(GfVec2i &self, int value)
318 {
319 return self /= value;
320 }
321 #endif
322
323 template <class V>
__init__()324 static V *__init__() {
325 // Default contstructor zero-initializes from python.
326 return new V(0);
327 }
328
329 struct FromPythonTuple {
FromPythonTuple__anon8895018e0111::FromPythonTuple330 FromPythonTuple() {
331 converter::registry::
332 push_back(&_convertible, &_construct,
333 boost::python::type_id<GfVec2i>());
334 }
335
336 private:
337
_convertible__anon8895018e0111::FromPythonTuple338 static void *_convertible(PyObject *obj_ptr) {
339 // If this object is a GfVec already, disregard.
340 if (PyObject_HasAttrString(obj_ptr, "__isGfVec"))
341 return 0;
342
343 typedef int Scalar;
344
345 // XXX: Would like to allow general sequences, but currently clients
346 // depend on this behavior.
347 if ((PyTuple_Check(obj_ptr) || PyList_Check(obj_ptr)) &&
348 PySequence_Size(obj_ptr) == 2 &&
349 _SequenceCheckItem(obj_ptr, 0) &&
350 _SequenceCheckItem(obj_ptr, 1)) {
351 return obj_ptr;
352 }
353 return 0;
354 }
355
_construct__anon8895018e0111::FromPythonTuple356 static void _construct(PyObject *obj_ptr, converter::
357 rvalue_from_python_stage1_data *data) {
358 typedef int Scalar;
359 void *storage = ((converter::rvalue_from_python_storage<GfVec2i>*)data)
360 ->storage.bytes;
361 new (storage)
362 GfVec2i(
363 _SequenceGetItem(obj_ptr, 0),
364 _SequenceGetItem(obj_ptr, 1));
365 data->convertible = storage;
366 }
367 };
368
369 // This adds support for python's builtin pickling library
370 // This is used by our Shake plugins which need to pickle entire classes
371 // (including code), which we don't support in pxml.
372 struct PickleSuite : boost::python::pickle_suite
373 {
getinitargs__anon8895018e0111::PickleSuite374 static boost::python::tuple getinitargs(const GfVec2i &v) {
375 return boost::python::make_tuple(v[0], v[1]);
376 }
377 };
378
379 } // anonymous namespace
380
wrapVec2i()381 void wrapVec2i()
382 {
383 typedef GfVec2i Vec;
384 typedef int Scalar;
385
386 static const size_t _dimension = 2;
387 static const bool _true = true;
388
389 def("Dot", (Scalar (*)( const Vec &, const Vec &))GfDot);
390
391
392 class_<GfVec2i> cls("Vec2i", no_init);
393 cls
394 .def("__init__", make_constructor(__init__<Vec>))
395
396 // A tag indicating that this is a GfVec class, for internal use.
397 .def_readonly("__isGfVec", _true)
398
399 .def_pickle(PickleSuite())
400
401
402 .def(init<Vec>())
403 .def(init<Scalar>())
404 .def(init<Scalar, Scalar>())
405
406 .def(TfTypePythonClass())
407
408 .def("__len__", __len__ )
409 .def("__getitem__", __getitem__ )
410 .def("__getitem__", __getslice__ )
411 .def("__setitem__", __setitem__ )
412 .def("__setitem__", __setslice__ )
413 .def("__contains__", __contains__ )
414
415 .def_readonly("dimension", _dimension)
416
417
418 .def(self == self)
419 .def(self != self)
420 .def(self += self)
421 .def(self -= self)
422 .def(self *= double())
423 .def(self * double())
424 .def(double() * self)
425 .def(self /= int())
426 .def(self / int())
427 .def(-self)
428 .def(self + self)
429 .def(self - self)
430 .def(self * self)
431 .def(str(self))
432
433 #if PY_MAJOR_VERSION == 2
434 // Needed only to support "from __future__ import division" in
435 // python 2. In python 3 builds boost::python adds this for us.
436 .def("__truediv__", __truediv__ )
437 .def("__itruediv__", __itruediv__ )
438 #endif
439
440 .def("Axis", &Vec::Axis).staticmethod("Axis")
441
442 .def("XAxis", &Vec::XAxis).staticmethod("XAxis")
443 .def("YAxis", &Vec::YAxis).staticmethod("YAxis")
444
445 .def("GetDot", (Scalar (*)(const Vec &, const Vec &))GfDot)
446
447
448 .def("__repr__", __repr__)
449 .def("__hash__", __hash__)
450 ;
451 to_python_converter<std::vector<GfVec2i>,
452 TfPySequenceToPython<std::vector<GfVec2i> > >();
453
454 // Install buffer protocol: set the tp_as_buffer slot to point to a
455 // structure of function pointers that implement the buffer protocol for
456 // this type, and set the type flags to indicate that this type supports the
457 // buffer protocol.
458 auto *typeObj = reinterpret_cast<PyTypeObject *>(cls.ptr());
459 typeObj->tp_as_buffer = &bufferProcs;
460 typeObj->tp_flags |= (TfPy_TPFLAGS_HAVE_NEWBUFFER |
461 TfPy_TPFLAGS_HAVE_GETCHARBUFFER);
462
463 // Allow appropriate tuples to be passed where Vecs are expected.
464 FromPythonTuple();
465
466 // Allow conversion of lists of GfVec2i to std::vector<GfVec2i>
467 TfPyContainerConversions::from_python_sequence<
468 std::vector<GfVec2i>,
469 TfPyContainerConversions::variable_capacity_policy >();
470 }
471