Make NodePathCollection and TextureCollection constructors extensions

This commit is contained in:
rdb 2015-02-11 14:14:03 +01:00
parent cbd70ad8af
commit a6eb3fa442
13 changed files with 229 additions and 145 deletions

View File

@ -163,14 +163,12 @@ call_function(ostream &out, int indent_level, bool convert_result,
if (pexprs.empty() && !defconstruct.empty()) { if (pexprs.empty() && !defconstruct.empty()) {
return_expr = defconstruct; return_expr = defconstruct;
} else if (_extension) { } else if (_extension) {
// Extension constructors are a special case. We allocate memory, but // Extension constructors are a special case. We assume there is a
// the actual construction is done by an __init__ method, similar to how // default constructor for the class, and the actual construction is
// it works in Python. // done by an __init__ method.
InterfaceMaker::indent(out, indent_level); InterfaceMaker::indent(out, indent_level);
_return_type->get_new_type()->output_instance(out, "result", &parser); _return_type->get_new_type()->output_instance(out, "result", &parser);
out << " = (" << _cpptype->get_local_name(&parser) out << " = new " << _cpptype->get_local_name(&parser) << ";\n";
<< " *) " << _cpptype->get_local_name(&parser)
<< "::operator new(sizeof(" << _cpptype->get_local_name(&parser) << "));\n";
InterfaceMaker::indent(out, indent_level) InterfaceMaker::indent(out, indent_level)
<< get_call_str("result", pexprs) << ";\n"; << get_call_str("result", pexprs) << ";\n";

View File

@ -3260,8 +3260,7 @@ if (not RUNTIME):
TargetAdd('libp3gobj.in', opts=OPTS, input=IGATEFILES) TargetAdd('libp3gobj.in', opts=OPTS, input=IGATEFILES)
TargetAdd('libp3gobj.in', opts=['IMOD:panda3d.core', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj']) TargetAdd('libp3gobj.in', opts=['IMOD:panda3d.core', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj'])
TargetAdd('libp3gobj_igate.obj', input='libp3gobj.in', opts=["DEPENDENCYONLY"]) TargetAdd('libp3gobj_igate.obj', input='libp3gobj.in', opts=["DEPENDENCYONLY"])
TargetAdd('p3gobj_geomVertexArrayData_ext.obj', opts=OPTS, input='geomVertexArrayData_ext.cxx') TargetAdd('p3gobj_ext_composite.obj', opts=OPTS, input='p3gobj_ext_composite.cxx')
TargetAdd('p3gobj_internalName_ext.obj', opts=OPTS, input='internalName_ext.cxx')
# #
# DIRECTORY: panda/src/pgraphnodes/ # DIRECTORY: panda/src/pgraphnodes/
@ -3725,8 +3724,7 @@ if (not RUNTIME):
TargetAdd('core.pyd', input='p3putil_pythonCallbackObject.obj') TargetAdd('core.pyd', input='p3putil_pythonCallbackObject.obj')
TargetAdd('core.pyd', input='p3pnmimage_pfmFile_ext.obj') TargetAdd('core.pyd', input='p3pnmimage_pfmFile_ext.obj')
TargetAdd('core.pyd', input='p3event_pythonTask.obj') TargetAdd('core.pyd', input='p3event_pythonTask.obj')
TargetAdd('core.pyd', input='p3gobj_geomVertexArrayData_ext.obj') TargetAdd('core.pyd', input='p3gobj_ext_composite.obj')
TargetAdd('core.pyd', input='p3gobj_internalName_ext.obj')
TargetAdd('core.pyd', input='p3pgraph_ext_composite.obj') TargetAdd('core.pyd', input='p3pgraph_ext_composite.obj')
TargetAdd('core.pyd', input='p3display_graphicsStateGuardian_ext.obj') TargetAdd('core.pyd', input='p3display_graphicsStateGuardian_ext.obj')
TargetAdd('core.pyd', input='p3display_graphicsWindow_ext.obj') TargetAdd('core.pyd', input='p3display_graphicsWindow_ext.obj')

View File

@ -24,11 +24,6 @@
template<class Element> template<class Element>
void Extension<PointerToArray<Element> >:: void Extension<PointerToArray<Element> >::
__init__(PyObject *self, PyObject *source) { __init__(PyObject *self, PyObject *source) {
// We have to pre-initialize self's "this" pointer when we receive
// self in the constructor--the caller can't initialize this for us.
new (this->_this) PointerToArray<Element>(get_type_handle(Element));
((Dtool_PyInstDef *)self)->_ptr_to_object = this->_this;
#if PY_VERSION_HEX >= 0x02060000 #if PY_VERSION_HEX >= 0x02060000
if (PyObject_CheckBuffer(source)) { if (PyObject_CheckBuffer(source)) {
// User passed a buffer object. // User passed a buffer object.

View File

@ -8,7 +8,8 @@
#define LOCAL_LIBS \ #define LOCAL_LIBS \
p3pstatclient p3event p3linmath p3mathutil p3pnmimage p3gsgbase p3putil p3pstatclient p3event p3linmath p3mathutil p3pnmimage p3gsgbase p3putil
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx \
$[TARGET]_ext_composite.cxx
#define SOURCES \ #define SOURCES \
adaptiveLru.I adaptiveLru.h \ adaptiveLru.I adaptiveLru.h \
@ -30,7 +31,7 @@
geomLinestrips.h \ geomLinestrips.h \
geomPoints.h \ geomPoints.h \
geomVertexArrayData.h geomVertexArrayData.I \ geomVertexArrayData.h geomVertexArrayData.I \
geomVertexArrayData_ext.h geomVertexArrayData_ext.cxx \ geomVertexArrayData_ext.h \
geomVertexArrayFormat.h geomVertexArrayFormat.I \ geomVertexArrayFormat.h geomVertexArrayFormat.I \
geomCacheEntry.h geomCacheEntry.I \ geomCacheEntry.h geomCacheEntry.I \
geomCacheManager.h geomCacheManager.I \ geomCacheManager.h geomCacheManager.I \
@ -43,7 +44,7 @@
geomVertexWriter.h geomVertexWriter.I \ geomVertexWriter.h geomVertexWriter.I \
indexBufferContext.I indexBufferContext.h \ indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \ internalName.I internalName.h \
internalName_ext.h internalName_ext.cxx \ internalName_ext.h \
lens.h lens.I \ lens.h lens.I \
material.I material.h materialPool.I materialPool.h \ material.I material.h materialPool.I materialPool.h \
matrixLens.I matrixLens.h \ matrixLens.I matrixLens.h \
@ -103,6 +104,7 @@
geomLinestrips.cxx \ geomLinestrips.cxx \
geomPoints.cxx \ geomPoints.cxx \
geomVertexArrayData.cxx \ geomVertexArrayData.cxx \
geomVertexArrayData_ext.cxx \
geomVertexArrayFormat.cxx \ geomVertexArrayFormat.cxx \
geomCacheEntry.cxx \ geomCacheEntry.cxx \
geomCacheManager.cxx \ geomCacheManager.cxx \
@ -116,6 +118,7 @@
indexBufferContext.cxx \ indexBufferContext.cxx \
material.cxx \ material.cxx \
internalName.cxx \ internalName.cxx \
internalName_ext.cxx \
lens.cxx \ lens.cxx \
materialPool.cxx matrixLens.cxx \ materialPool.cxx matrixLens.cxx \
occlusionQueryContext.cxx \ occlusionQueryContext.cxx \
@ -131,6 +134,7 @@
sliderTable.cxx \ sliderTable.cxx \
texture.cxx \ texture.cxx \
textureCollection.cxx \ textureCollection.cxx \
textureCollection_ext.cxx \
textureContext.cxx \ textureContext.cxx \
texturePeeker.cxx \ texturePeeker.cxx \
texturePool.cxx \ texturePool.cxx \

View File

@ -0,0 +1,3 @@
#include "internalName_ext.cxx"
#include "geomVertexArrayData_ext.cxx"
#include "textureCollection_ext.cxx"

View File

@ -49,79 +49,6 @@ operator = (const TextureCollection &copy) {
_textures = copy._textures; _textures = copy._textures;
} }
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TextureCollection::Constructor
// Access: Published
// Description: This special constructor accepts a Python list of
// Textures. Since this constructor accepts a generic
// PyObject *, it should be the last constructor listed
// in the class record.
////////////////////////////////////////////////////////////////////
TextureCollection::
TextureCollection(PyObject *self, PyObject *sequence) {
// We have to pre-initialize self's "this" pointer when we receive
// self in the constructor--the caller can't initialize this for us.
((Dtool_PyInstDef *)self)->_ptr_to_object = this;
if (!PySequence_Check(sequence)) {
// If passed with a non-sequence, this isn't the right constructor.
PyErr_SetString(PyExc_TypeError, "TextureCollection constructor requires a sequence");
return;
}
int size = PySequence_Size(sequence);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_GetItem(sequence, i);
if (item == NULL) {
return;
}
PyObject *result = PyObject_CallMethod(self, (char *)"add_texture", (char *)"O", item);
Py_DECREF(item);
if (result == NULL) {
// Unable to add item--probably it wasn't of the appropriate type.
ostringstream stream;
stream << "Element " << i << " in sequence passed to TextureCollection constructor could not be added";
string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
return;
}
Py_DECREF(result);
}
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TextureCollection::__reduce__
// Access: Published
// Description: This special Python method is implement to provide
// support for the pickle module.
////////////////////////////////////////////////////////////////////
PyObject *TextureCollection::
__reduce__(PyObject *self) const {
// Here we will return a 4-tuple: (Class, (args), None, iterator),
// where iterator is an iterator that will yield successive
// Textures.
// We should return at least a 2-tuple, (Class, (args)): the
// necessary class object whose constructor we should call
// (e.g. this), and the arguments necessary to reconstruct this
// object.
PyObject *this_class = PyObject_Type(self);
if (this_class == NULL) {
return NULL;
}
// Since a TextureCollection is itself an iterator, we can simply
// pass it as the fourth tuple component.
PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self);
Py_DECREF(this_class);
return result;
}
#endif // HAVE_PYTHON
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextureCollection::add_texture // Function: TextureCollection::add_texture
// Access: Published // Access: Published
@ -270,6 +197,18 @@ clear() {
_textures.clear(); _textures.clear();
} }
////////////////////////////////////////////////////////////////////
// Function: TextureCollection::reserve
// Access: Published
// Description: This is a hint to Panda to allocate enough memory
// to hold the given number of NodePaths, if you know
// ahead of time how many you will be adding.
////////////////////////////////////////////////////////////////////
void TextureCollection::
reserve(size_t num) {
_textures.reserve(num);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextureCollection::find_texture // Function: TextureCollection::find_texture
// Access: Published // Access: Published

View File

@ -32,8 +32,8 @@ PUBLISHED:
INLINE ~TextureCollection(); INLINE ~TextureCollection();
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
TextureCollection(PyObject *self, PyObject *sequence); EXTENSION(TextureCollection(PyObject *self, PyObject *sequence));
PyObject *__reduce__(PyObject *self) const; EXTENSION(PyObject *__reduce__(PyObject *self) const);
#endif #endif
void add_texture(Texture *texture); void add_texture(Texture *texture);
@ -43,6 +43,7 @@ PUBLISHED:
void remove_duplicate_textures(); void remove_duplicate_textures();
bool has_texture(Texture *texture) const; bool has_texture(Texture *texture) const;
void clear(); void clear();
void reserve(size_t num);
Texture *find_texture(const string &name) const; Texture *find_texture(const string &name) const;
@ -74,5 +75,3 @@ INLINE ostream &operator << (ostream &out, const TextureCollection &col) {
#include "textureCollection.I" #include "textureCollection.I"
#endif #endif

View File

@ -0,0 +1,94 @@
// Filename: textureCollection_ext.cxx
// Created by: rdb (11Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "textureCollection_ext.h"
#ifdef HAVE_PYTHON
#ifndef CPPPARSER
extern struct Dtool_PyTypedObject Dtool_Texture;
#endif
////////////////////////////////////////////////////////////////////
// Function: TextureCollection::__init__
// Access: Published
// Description: This special constructor accepts a Python list of
// Textures. Since this constructor accepts a generic
// PyObject *, it should be the last constructor listed
// in the class record.
////////////////////////////////////////////////////////////////////
void Extension<TextureCollection>::
__init__(PyObject *self, PyObject *sequence) {
PyObject *fast = PySequence_Fast(sequence, "TextureCollection constructor requires a sequence");
if (fast == NULL) {
return;
}
Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
_this->reserve(size);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_Fast_GET_ITEM(fast, i);
if (item == NULL) {
return;
}
Texture *tex;
DTOOL_Call_ExtractThisPointerForType(item, &Dtool_Texture, (void **)&tex);
if (tex == (Texture *)NULL) {
// Unable to add item--probably it wasn't of the appropriate type.
ostringstream stream;
stream << "Element " << i << " in sequence passed to TextureCollection constructor is not a Texture";
string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
Py_DECREF(fast);
return;
} else {
_this->add_texture(tex);
}
}
Py_DECREF(fast);
}
////////////////////////////////////////////////////////////////////
// Function: TextureCollection::__reduce__
// Access: Published
// Description: This special Python method is implement to provide
// support for the pickle module.
////////////////////////////////////////////////////////////////////
PyObject *Extension<TextureCollection>::
__reduce__(PyObject *self) const {
// Here we will return a 4-tuple: (Class, (args), None, iterator),
// where iterator is an iterator that will yield successive
// Textures.
// We should return at least a 2-tuple, (Class, (args)): the
// necessary class object whose constructor we should call
// (e.g. this), and the arguments necessary to reconstruct this
// object.
PyObject *this_class = PyObject_Type(self);
if (this_class == NULL) {
return NULL;
}
// Since a TextureCollection is itself an iterator, we can simply
// pass it as the fourth tuple component.
PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self);
Py_DECREF(this_class);
return result;
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,42 @@
// Filename: textureCollection_ext.h
// Created by: rdb (11Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef TEXTURECOLLECTION_EXT_H
#define TEXTURECOLLECTION_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "textureCollection.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<TextureCollection>
// Description : This class defines the extension methods for
// TextureCollection, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<TextureCollection> : public ExtensionBase<TextureCollection> {
public:
void __init__(PyObject *self, PyObject *sequence);
PyObject *__reduce__(PyObject *self) const;
};
#endif // HAVE_PYTHON
#endif // TEXTURECOLLECTION_EXT_H

View File

@ -20,10 +20,6 @@
#include "colorAttrib.h" #include "colorAttrib.h"
#include "indent.h" #include "indent.h"
#ifdef HAVE_PYTHON
#include "py_panda.h"
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::Constructor // Function: NodePathCollection::Constructor
// Access: Published // Access: Published
@ -54,48 +50,6 @@ operator = (const NodePathCollection &copy) {
_node_paths = copy._node_paths; _node_paths = copy._node_paths;
} }
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::Constructor
// Access: Published
// Description: This special constructor accepts a Python list of
// NodePaths. Since this constructor accepts a generic
// PyObject *, it should be the last constructor listed
// in the class record.
////////////////////////////////////////////////////////////////////
NodePathCollection::
NodePathCollection(PyObject *self, PyObject *sequence) {
// We have to pre-initialize self's "this" pointer when we receive
// self in the constructor--the caller can't initialize this for us.
((Dtool_PyInstDef *)self)->_ptr_to_object = this;
if (!PySequence_Check(sequence)) {
// If passed with a non-sequence, this isn't the right constructor.
PyErr_SetString(PyExc_TypeError, "NodePathCollection constructor requires a sequence");
return;
}
int size = PySequence_Size(sequence);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_GetItem(sequence, i);
if (item == NULL) {
return;
}
PyObject *result = PyObject_CallMethod(self, (char *)"addPath", (char *)"O", item);
Py_DECREF(item);
if (result == NULL) {
// Unable to add item--probably it wasn't of the appropriate type.
ostringstream stream;
stream << "Element " << i << " in sequence passed to NodePathCollection constructor could not be added";
string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
return;
}
Py_DECREF(result);
}
}
#endif // HAVE_PYTHON
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::add_path // Function: NodePathCollection::add_path
// Access: Published // Access: Published
@ -244,6 +198,18 @@ clear() {
_node_paths.clear(); _node_paths.clear();
} }
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::reserve
// Access: Published
// Description: This is a hint to Panda to allocate enough memory
// to hold the given number of NodePaths, if you know
// ahead of time how many you will be adding.
////////////////////////////////////////////////////////////////////
void NodePathCollection::
reserve(size_t num) {
_node_paths.reserve(num);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::is_empty // Function: NodePathCollection::is_empty
// Access: Published // Access: Published

View File

@ -34,7 +34,7 @@ PUBLISHED:
INLINE ~NodePathCollection(); INLINE ~NodePathCollection();
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
NodePathCollection(PyObject *self, PyObject *sequence); EXTENSION(NodePathCollection(PyObject *self, PyObject *sequence));
EXTENSION(PyObject *__reduce__(PyObject *self) const); EXTENSION(PyObject *__reduce__(PyObject *self) const);
#endif #endif
@ -45,6 +45,7 @@ PUBLISHED:
void remove_duplicate_paths(); void remove_duplicate_paths();
bool has_path(const NodePath &path) const; bool has_path(const NodePath &path) const;
void clear(); void clear();
void reserve(size_t num);
bool is_empty() const; bool is_empty() const;
int get_num_paths() const; int get_num_paths() const;

View File

@ -17,6 +17,7 @@
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
#ifndef CPPPARSER #ifndef CPPPARSER
extern struct Dtool_PyTypedObject Dtool_NodePath;
#ifdef STDFLOAT_DOUBLE #ifdef STDFLOAT_DOUBLE
extern struct Dtool_PyTypedObject Dtool_LPoint3d; extern struct Dtool_PyTypedObject Dtool_LPoint3d;
#else #else
@ -24,6 +25,48 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3f;
#endif #endif
#endif #endif
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::__init__
// Access: Published
// Description: This special constructor accepts a Python list of
// NodePaths. Since this constructor accepts a generic
// PyObject *, it should be the last constructor listed
// in the class record.
////////////////////////////////////////////////////////////////////
void Extension<NodePathCollection>::
__init__(PyObject *self, PyObject *sequence) {
PyObject *fast = PySequence_Fast(sequence, "NodePathCollection constructor requires a sequence");
if (fast == NULL) {
return;
}
Py_ssize_t size = PySequence_Fast_GET_SIZE(fast);
_this->reserve(size);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_Fast_GET_ITEM(fast, i);
if (item == NULL) {
return;
}
NodePath *path;
DTOOL_Call_ExtractThisPointerForType(item, &Dtool_NodePath, (void **)&path);
if (path == (NodePath *)NULL) {
// Unable to add item--probably it wasn't of the appropriate type.
ostringstream stream;
stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath";
string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
Py_DECREF(fast);
return;
} else {
_this->add_path(*path);
}
}
Py_DECREF(fast);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::__reduce__ // Function: NodePathCollection::__reduce__
// Access: Published // Access: Published
@ -83,4 +126,4 @@ get_tight_bounds() const {
} }
} }
#endif #endif // HAVE_PYTHON

View File

@ -32,6 +32,8 @@
template<> template<>
class Extension<NodePathCollection> : public ExtensionBase<NodePathCollection> { class Extension<NodePathCollection> : public ExtensionBase<NodePathCollection> {
public: public:
void __init__(PyObject *self, PyObject *sequence);
PyObject *__reduce__(PyObject *self) const; PyObject *__reduce__(PyObject *self) const;
PyObject *get_tight_bounds() const; PyObject *get_tight_bounds() const;