Commit patch by cfsworks to move pgraph stuff to extensions

This commit is contained in:
rdb 2014-04-04 09:23:58 +00:00
parent d792c93026
commit 566feda34d
17 changed files with 827 additions and 656 deletions

View File

@ -3200,8 +3200,7 @@ if (not RUNTIME):
TargetAdd('libp3pgraph.in', opts=OPTS, input=IGATEFILES)
TargetAdd('libp3pgraph.in', opts=['IMOD:core', 'ILIB:libp3pgraph', 'SRCDIR:panda/src/pgraph'])
TargetAdd('libp3pgraph_igate.obj', input='libp3pgraph.in', opts=["DEPENDENCYONLY","BIGOBJ"])
TargetAdd('p3pgraph_nodePath_ext.obj', opts=OPTS, input='nodePath_ext.cxx')
TargetAdd('p3pgraph_nodePathCollection_ext.obj', opts=OPTS, input='nodePathCollection_ext.cxx')
TargetAdd('p3pgraph_ext_composite.obj', opts=OPTS, input='p3pgraph_ext_composite.cxx')
#
# DIRECTORY: panda/src/cull/
@ -3543,8 +3542,7 @@ if (not RUNTIME):
TargetAdd('libpanda.dll', input='p3putil_typedWritable_ext.obj')
TargetAdd('libpanda.dll', input='p3pnmimage_pfmFile_ext.obj')
TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj')
TargetAdd('libpanda.dll', input='p3pgraph_nodePath_ext.obj')
TargetAdd('libpanda.dll', input='p3pgraph_nodePathCollection_ext.obj')
TargetAdd('libpanda.dll', input='p3pgraph_ext_composite.obj')
TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian_ext.obj')
if PkgSkip("FREETYPE")==0:

View File

@ -116,7 +116,8 @@
#define COMBINED_SOURCES \
$[TARGET]_composite1.cxx $[TARGET]_composite2.cxx \
$[TARGET]_composite3.cxx $[TARGET]_composite4.cxx
$[TARGET]_composite3.cxx $[TARGET]_composite4.cxx \
$[TARGET]_ext_composite.cxx
#define INCLUDED_SOURCES \
accumulatedAttribs.cxx \
alphaTestAttrib.cxx \
@ -277,6 +278,7 @@
occluderEffect.I occluderEffect.h \
occluderNode.I occluderNode.h \
pandaNode.I pandaNode.h \
pandaNode_ext.h pandaNode_ext.cxx \
pandaNodeChain.I pandaNodeChain.h \
planeNode.I planeNode.h \
polylightEffect.I polylightEffect.h \
@ -289,6 +291,7 @@
renderEffects.I renderEffects.h \
renderModeAttrib.I renderModeAttrib.h \
renderState.I renderState.h \
renderState_ext.h renderState_ext.cxx \
rescaleNormalAttrib.I rescaleNormalAttrib.h \
sceneGraphReducer.I sceneGraphReducer.h \
sceneSetup.I sceneSetup.h \
@ -307,6 +310,7 @@
texGenAttrib.I texGenAttrib.h \
textureStageCollection.I textureStageCollection.h \
transformState.I transformState.h \
transformState_ext.h transformState_ext.cxx \
transparencyAttrib.I transparencyAttrib.h \
weakNodePath.I weakNodePath.h \
workingNodePath.I workingNodePath.h

View File

@ -12,6 +12,8 @@
//
////////////////////////////////////////////////////////////////////
#include "pandaNode_ext.h"
#ifndef CPPPARSER
#ifdef STDFLOAT_DOUBLE
IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3d;
@ -33,7 +35,7 @@ IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f;
INLINE void Extension<NodePath>::
get_python_tag_keys(vector_string &keys) const {
nassertv_always(!_this->is_empty());
_this->node()->get_python_tag_keys(keys);
invoke_extension(_this->node()).get_python_tag_keys(keys);
}
////////////////////////////////////////////////////////////////////
@ -49,7 +51,7 @@ get_tag_keys() const {
Py_INCREF(Py_None);
return Py_None;
}
return _this->node()->get_tag_keys();
return invoke_extension(_this->node()).get_tag_keys();
}
////////////////////////////////////////////////////////////////////
@ -66,7 +68,7 @@ get_python_tag_keys() const {
Py_INCREF(Py_None);
return Py_None;
}
return _this->node()->get_python_tag_keys();
return invoke_extension(_this->node()).get_python_tag_keys();
}
////////////////////////////////////////////////////////////////////
@ -85,7 +87,7 @@ get_python_tag_keys() const {
INLINE void Extension<NodePath>::
set_python_tag(const string &key, PyObject *value) {
nassertv_always(!_this->is_empty());
_this->node()->set_python_tag(key, value);
invoke_extension(_this->node()).set_python_tag(key, value);
}
////////////////////////////////////////////////////////////////////
@ -104,7 +106,7 @@ get_python_tag(const string &key) const {
Py_INCREF(Py_None);
return Py_None;
}
return _this->node()->get_python_tag(key);
return invoke_extension(_this->node()).get_python_tag(key);
}
////////////////////////////////////////////////////////////////////
@ -122,7 +124,7 @@ has_python_tag(const string &key) const {
if (_this->is_empty()) {
return false;
}
return _this->node()->has_python_tag(key);
return invoke_extension(_this->node()).has_python_tag(key);
}
////////////////////////////////////////////////////////////////////
@ -136,7 +138,7 @@ has_python_tag(const string &key) const {
INLINE void Extension<NodePath>::
clear_python_tag(const string &key) {
nassertv_always(!_this->is_empty());
_this->node()->clear_python_tag(key);
invoke_extension(_this->node()).clear_python_tag(key);
}
////////////////////////////////////////////////////////////////////

View File

@ -40,7 +40,7 @@ __copy__() const {
// If we do have a node, duplicate it, and wrap it in a new
// NodePath.
return NodePath(_this->node()->__copy__());
return NodePath(invoke_extension(_this->node()).__copy__());
}
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,5 @@
#include "nodePath_ext.cxx"
#include "nodePathCollection_ext.cxx"
#include "pandaNode_ext.cxx"
#include "renderState_ext.cxx"
#include "transformState_ext.cxx"

View File

@ -632,73 +632,6 @@ copy_subgraph(Thread *current_thread) const {
return r_copy_subgraph(inst_map, current_thread);
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::__copy__
// Access: Published
// Description: A special Python method that is invoked by
// copy.copy(node). Unlike the PandaNode copy
// constructor, which creates a new node without
// children, this shares child pointers (essentially
// making every child an instance). This is intended to
// simulate the behavior of copy.copy() for other
// objects.
////////////////////////////////////////////////////////////////////
PT(PandaNode) PandaNode::
__copy__() const {
Thread *current_thread = Thread::get_current_thread();
PT(PandaNode) node_dupe = make_copy();
Children children = get_children(current_thread);
int num_children = children.get_num_children();
for (int i = 0; i < num_children; ++i) {
node_dupe->add_child(children.get_child(i), children.get_child_sort(i));
}
return node_dupe;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::__deepcopy__
// Access: Published
// Description: A special Python method that is invoked by
// copy.deepcopy(node). This calls copy_subgraph()
// unless the node is already present in the provided
// dictionary.
////////////////////////////////////////////////////////////////////
PyObject *PandaNode::
__deepcopy__(PyObject *self, PyObject *memo) const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode;
// Borrowed reference.
PyObject *dupe = PyDict_GetItem(memo, self);
if (dupe != NULL) {
// Already in the memo dictionary.
Py_INCREF(dupe);
return dupe;
}
PT(PandaNode) node_dupe = copy_subgraph();
// DTool_CreatePyInstanceTyped() steals a C++ reference.
node_dupe->ref();
dupe = DTool_CreatePyInstanceTyped
((void *)node_dupe.p(), Dtool_PandaNode, true, false,
node_dupe->get_type_index());
if (PyDict_SetItem(memo, self, dupe) != 0) {
Py_DECREF(dupe);
return NULL;
}
return dupe;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::count_num_descendants
// Access: Published
@ -1509,118 +1442,6 @@ clear_tag(const string &key, Thread *current_thread) {
mark_bam_modified();
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_python_tag
// Access: Published
// Description: Associates an arbitrary Python object with a
// user-defined key which is stored on the node. This
// is similar to set_tag(), except it can store any
// Python object instead of just a string. However, the
// Python object is not recorded to a bam file.
//
// Each unique key stores a different string value.
// There is no effective limit on the number of
// different keys that may be stored or on the length of
// any one key's value.
////////////////////////////////////////////////////////////////////
void PandaNode::
set_python_tag(const string &key, PyObject *value) {
Thread *current_thread = Thread::get_current_thread();
int pipeline_stage = current_thread->get_pipeline_stage();
nassertv(pipeline_stage == 0);
CDWriter cdata(_cycler);
Py_XINCREF(value);
pair<PythonTagData::iterator, bool> result;
result = cdata->_python_tag_data.insert(PythonTagData::value_type(key, value));
if (!result.second) {
// The insert was unsuccessful; that means the key was already
// present in the map. In this case, we should decrement the
// original value's reference count and replace it with the new
// object.
PythonTagData::iterator ti = result.first;
PyObject *old_value = (*ti).second;
Py_XDECREF(old_value);
(*ti).second = value;
}
// Even though the python tag isn't recorded in the bam stream?
mark_bam_modified();
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_python_tag
// Access: Published
// Description: Retrieves the Python object that was previously
// set on this node for the particular key, if any. If
// no value has been previously set, returns None.
////////////////////////////////////////////////////////////////////
PyObject *PandaNode::
get_python_tag(const string &key) const {
CDReader cdata(_cycler);
PythonTagData::const_iterator ti;
ti = cdata->_python_tag_data.find(key);
if (ti != cdata->_python_tag_data.end()) {
PyObject *result = (*ti).second;
Py_XINCREF(result);
return result;
}
Py_INCREF(Py_None);
return Py_None;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::has_python_tag
// Access: Published
// Description: Returns true if a Python object has been defined on
// this node for the particular key (even if that object
// is None), or false if no object has been set.
////////////////////////////////////////////////////////////////////
bool PandaNode::
has_python_tag(const string &key) const {
CDReader cdata(_cycler);
PythonTagData::const_iterator ti;
ti = cdata->_python_tag_data.find(key);
return (ti != cdata->_python_tag_data.end());
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_python_tag
// Access: Published
// Description: Removes the Python object defined for this key on
// this particular node. After a call to
// clear_python_tag(), has_python_tag() will return
// false for the indicated key.
////////////////////////////////////////////////////////////////////
void PandaNode::
clear_python_tag(const string &key) {
Thread *current_thread = Thread::get_current_thread();
int pipeline_stage = current_thread->get_pipeline_stage();
nassertv(pipeline_stage == 0);
CDWriter cdata(_cycler, current_thread);
PythonTagData::iterator ti;
ti = cdata->_python_tag_data.find(key);
if (ti != cdata->_python_tag_data.end()) {
PyObject *value = (*ti).second;
Py_XDECREF(value);
cdata->_python_tag_data.erase(ti);
}
// Even though the python tag isn't recorded in the bam stream?
mark_bam_modified();
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::copy_tags
// Access: Published
@ -1743,80 +1564,6 @@ get_tag_keys(vector_string &keys) const {
}
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: Filename::get_python_tag_keys
// Access: Published
// Description: Fills the given vector up with the
// list of Python tags on this PandaNode.
//
// It is the user's responsibility to ensure that the
// keys vector is empty before making this call;
// otherwise, the new files will be appended to it.
////////////////////////////////////////////////////////////////////
void PandaNode::
get_python_tag_keys(vector_string &keys) const {
CDReader cdata(_cycler);
if (!cdata->_python_tag_data.empty()) {
PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
while (ti != cdata->_python_tag_data.end()) {
keys.push_back((*ti).first);
++ti;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: Filename::get_tag_keys
// Access: Published
// Description: This variant on get_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *PandaNode::
get_tag_keys() const {
vector_string keys;
get_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Filename::get_python_tag_keys
// Access: Published
// Description: This variant on get_python_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *PandaNode::
get_python_tag_keys() const {
vector_string keys;
get_python_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
}
return result;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: PandaNode::compare_tags
// Access: Published

View File

@ -45,6 +45,7 @@
#include "copyOnWriteObject.h"
#include "copyOnWritePointer.h"
#include "lightReMutex.h"
#include "extension.h"
#ifdef HAVE_PYTHON
@ -118,10 +119,8 @@ PUBLISHED:
virtual PandaNode *make_copy() const;
PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
#ifdef HAVE_PYTHON
PT(PandaNode) __copy__() const;
PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
#endif
EXTENSION(PT(PandaNode) __copy__() const);
EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
@ -202,16 +201,15 @@ PUBLISHED:
void clear_tag(const string &key,
Thread *current_thread = Thread::get_current_thread());
void get_tag_keys(vector_string &keys) const;
#ifdef HAVE_PYTHON
PyObject *get_tag_keys() const;
void set_python_tag(const string &key, PyObject *value);
PyObject *get_python_tag(const string &key) const;
bool has_python_tag(const string &key) const;
void clear_python_tag(const string &key);
void get_python_tag_keys(vector_string &keys) const;
PyObject *get_python_tag_keys() const;
#endif // HAVE_PYTHON
EXTENSION(PyObject *get_tag_keys() const);
EXTENSION(void set_python_tag(const string &key, PyObject *value));
EXTENSION(PyObject *get_python_tag(const string &key) const);
EXTENSION(bool has_python_tag(const string &key) const);
EXTENSION(void clear_python_tag(const string &key));
EXTENSION(void get_python_tag_keys(vector_string &keys) const);
EXTENSION(PyObject *get_python_tag_keys() const);
INLINE bool has_tags() const;
void copy_tags(PandaNode *other);
@ -784,6 +782,7 @@ private:
friend class WorkingNodePath;
friend class PandaNodePipelineReader;
friend class EggLoader;
friend class Extension<PandaNode>;
};
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,259 @@
// Filename: pandaNode_ext.cxx
// Created by: CFSworks (30Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pandaNode_ext.h"
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::__copy__
// Access: Published
// Description: A special Python method that is invoked by
// copy.copy(node). Unlike the PandaNode copy
// constructor, which creates a new node without
// children, this shares child pointers (essentially
// making every child an instance). This is intended to
// simulate the behavior of copy.copy() for other
// objects.
////////////////////////////////////////////////////////////////////
PT(PandaNode) Extension<PandaNode>::
__copy__() const {
Thread *current_thread = Thread::get_current_thread();
PT(PandaNode) node_dupe = _this->make_copy();
PandaNode::Children children = _this->get_children(current_thread);
int num_children = children.get_num_children();
for (int i = 0; i < num_children; ++i) {
node_dupe->add_child(children.get_child(i), children.get_child_sort(i));
}
return node_dupe;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::__deepcopy__
// Access: Published
// Description: A special Python method that is invoked by
// copy.deepcopy(node). This calls copy_subgraph()
// unless the node is already present in the provided
// dictionary.
////////////////////////////////////////////////////////////////////
PyObject *Extension<PandaNode>::
__deepcopy__(PyObject *self, PyObject *memo) const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode;
// Borrowed reference.
PyObject *dupe = PyDict_GetItem(memo, self);
if (dupe != NULL) {
// Already in the memo dictionary.
Py_INCREF(dupe);
return dupe;
}
PT(PandaNode) node_dupe = _this->copy_subgraph();
// DTool_CreatePyInstanceTyped() steals a C++ reference.
node_dupe->ref();
dupe = DTool_CreatePyInstanceTyped
((void *)node_dupe.p(), Dtool_PandaNode, true, false,
node_dupe->get_type_index());
if (PyDict_SetItem(memo, self, dupe) != 0) {
Py_DECREF(dupe);
return NULL;
}
return dupe;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::set_python_tag
// Access: Published
// Description: Associates an arbitrary Python object with a
// user-defined key which is stored on the node. This
// is similar to set_tag(), except it can store any
// Python object instead of just a string. However, the
// Python object is not recorded to a bam file.
//
// Each unique key stores a different string value.
// There is no effective limit on the number of
// different keys that may be stored or on the length of
// any one key's value.
////////////////////////////////////////////////////////////////////
void Extension<PandaNode>::
set_python_tag(const string &key, PyObject *value) {
Thread *current_thread = Thread::get_current_thread();
int pipeline_stage = current_thread->get_pipeline_stage();
nassertv(pipeline_stage == 0);
PandaNode::CDWriter cdata(_this->_cycler);
Py_XINCREF(value);
pair<PandaNode::PythonTagData::iterator, bool> result;
result = cdata->_python_tag_data.insert(PandaNode::PythonTagData::value_type(key, value));
if (!result.second) {
// The insert was unsuccessful; that means the key was already
// present in the map. In this case, we should decrement the
// original value's reference count and replace it with the new
// object.
PandaNode::PythonTagData::iterator ti = result.first;
PyObject *old_value = (*ti).second;
Py_XDECREF(old_value);
(*ti).second = value;
}
// Even though the python tag isn't recorded in the bam stream?
_this->mark_bam_modified();
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::get_python_tag
// Access: Published
// Description: Retrieves the Python object that was previously
// set on this node for the particular key, if any. If
// no value has been previously set, returns None.
////////////////////////////////////////////////////////////////////
PyObject *Extension<PandaNode>::
get_python_tag(const string &key) const {
PandaNode::CDReader cdata(_this->_cycler);
PandaNode::PythonTagData::const_iterator ti;
ti = cdata->_python_tag_data.find(key);
if (ti != cdata->_python_tag_data.end()) {
PyObject *result = (*ti).second;
Py_XINCREF(result);
return result;
}
Py_INCREF(Py_None);
return Py_None;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::has_python_tag
// Access: Published
// Description: Returns true if a Python object has been defined on
// this node for the particular key (even if that object
// is None), or false if no object has been set.
////////////////////////////////////////////////////////////////////
bool Extension<PandaNode>::
has_python_tag(const string &key) const {
PandaNode::CDReader cdata(_this->_cycler);
PandaNode::PythonTagData::const_iterator ti;
ti = cdata->_python_tag_data.find(key);
return (ti != cdata->_python_tag_data.end());
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::clear_python_tag
// Access: Published
// Description: Removes the Python object defined for this key on
// this particular node. After a call to
// clear_python_tag(), has_python_tag() will return
// false for the indicated key.
////////////////////////////////////////////////////////////////////
void Extension<PandaNode>::
clear_python_tag(const string &key) {
Thread *current_thread = Thread::get_current_thread();
int pipeline_stage = current_thread->get_pipeline_stage();
nassertv(pipeline_stage == 0);
PandaNode::CDWriter cdata(_this->_cycler, current_thread);
PandaNode::PythonTagData::iterator ti;
ti = cdata->_python_tag_data.find(key);
if (ti != cdata->_python_tag_data.end()) {
PyObject *value = (*ti).second;
Py_XDECREF(value);
cdata->_python_tag_data.erase(ti);
}
// Even though the python tag isn't recorded in the bam stream?
_this->mark_bam_modified();
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::get_python_tag_keys
// Access: Published
// Description: Fills the given vector up with the
// list of Python tags on this PandaNode.
//
// It is the user's responsibility to ensure that the
// keys vector is empty before making this call;
// otherwise, the new files will be appended to it.
////////////////////////////////////////////////////////////////////
void Extension<PandaNode>::
get_python_tag_keys(vector_string &keys) const {
PandaNode::CDReader cdata(_this->_cycler);
if (!cdata->_python_tag_data.empty()) {
PandaNode::PythonTagData::const_iterator ti = cdata->_python_tag_data.begin();
while (ti != cdata->_python_tag_data.end()) {
keys.push_back((*ti).first);
++ti;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::get_tag_keys
// Access: Published
// Description: This variant on get_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *Extension<PandaNode>::
get_tag_keys() const {
vector_string keys;
_this->get_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<PandaNode>::get_python_tag_keys
// Access: Published
// Description: This variant on get_python_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *Extension<PandaNode>::
get_python_tag_keys() const {
vector_string keys;
get_python_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
}
return result;
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,50 @@
// Filename: pandaNode_ext.h
// Created by: CFSworks (30Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 PANDANODE_EXT_H
#define PANDANODE_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "pandaNode.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<PandaNode>
// Description : This class defines the extension methods for
// PandaNode, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<PandaNode> : public ExtensionBase<PandaNode> {
public:
PT(PandaNode) __copy__() const;
PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
PyObject *get_tag_keys() const;
void set_python_tag(const string &key, PyObject *value);
PyObject *get_python_tag(const string &key) const;
bool has_python_tag(const string &key) const;
void clear_python_tag(const string &key);
void get_python_tag_keys(vector_string &keys) const;
PyObject *get_python_tag_keys() const;
};
#endif // HAVE_PYTHON
#endif // PANDANODE_EXT_H

View File

@ -733,126 +733,6 @@ unref() const {
return false;
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// composition cache. For each tuple in the list, the
// first element is the source render, and the second
// is the result render. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *RenderState::
get_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
LightReMutexHolder holder(*_states_lock);
size_t cache_size = _composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) {
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
if (!_composition_cache.has_element(i)) {
a = Py_None;
Py_INCREF(a);
b = Py_None;
Py_INCREF(b);
} else {
const RenderState *source = _composition_cache.get_key(i);
if (source == (RenderState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState,
true, true, source->get_type_index());
}
const RenderState *result = _composition_cache.get_data(i)._result;
if (result == (RenderState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState,
true, true, result->get_type_index());
}
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
PyList_SET_ITEM(list, i, tuple);
}
return list;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_invert_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// invert_composition cache. For each tuple in the list, the
// first element is the source render, and the second
// is the result render. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->invert_compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *RenderState::
get_invert_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
LightReMutexHolder holder(*_states_lock);
size_t cache_size = _invert_composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) {
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
if (!_invert_composition_cache.has_element(i)) {
a = Py_None;
Py_INCREF(a);
b = Py_None;
Py_INCREF(b);
} else {
const RenderState *source = _invert_composition_cache.get_key(i);
if (source == (RenderState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState,
true, true, source->get_type_index());
}
const RenderState *result = _invert_composition_cache.get_data(i)._result;
if (result == (RenderState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState,
true, true, result->get_type_index());
}
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
PyList_SET_ITEM(list, i, tuple);
}
return list;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_auto_shader_state
// Access: Published
@ -2271,45 +2151,6 @@ update_pstats(int old_referenced_bits, int new_referenced_bits) {
#endif // DO_PSTATS
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_states
// Access: Published, Static
// Description: Returns a list of all of the RenderState objects
// in the state cache. The order of elements in this
// cache is arbitrary.
////////////////////////////////////////////////////////////////////
PyObject *RenderState::
get_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
if (_states == (States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*_states_lock);
size_t num_states = _states->get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
const RenderState *state = _states->get_key(si);
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState,
true, true, state->get_type_index());
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, a);
++i;
}
nassertr(i == num_states, list);
return list;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: RenderState::init_states
// Access: Public, Static

View File

@ -126,10 +126,8 @@ PUBLISHED:
INLINE int get_invert_composition_cache_size() const;
INLINE const RenderState *get_invert_composition_cache_source(int n) const;
INLINE const RenderState *get_invert_composition_cache_result(int n) const;
#ifdef HAVE_PYTHON
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
#endif // HAVE_PYTHON
EXTENSION(PyObject *get_composition_cache() const);
EXTENSION(PyObject *get_invert_composition_cache() const);
const RenderState *get_auto_shader_state() const;
@ -146,9 +144,7 @@ PUBLISHED:
static void list_cycles(ostream &out);
static void list_states(ostream &out);
static bool validate_states();
#ifdef HAVE_PYTHON
static PyObject *get_states();
#endif // HAVE_PYTHON
EXTENSION(static PyObject *get_states());
PUBLISHED:
// These methods are intended for use by low-level code, but they're
@ -363,6 +359,7 @@ private:
friend class GraphicsStateGuardian;
friend class RenderAttribRegistry;
friend class Extension<RenderState>;
};
INLINE ostream &operator << (ostream &out, const RenderState &state) {

View File

@ -0,0 +1,174 @@
// Filename: renderState_ext.cxx
// Created by: CFSworks (31Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 "renderState_ext.h"
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: Extension<RenderState>::get_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// composition cache. For each tuple in the list, the
// first element is the source render, and the second
// is the result render. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *Extension<RenderState>::
get_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
LightReMutexHolder holder(*RenderState::_states_lock);
size_t cache_size = _this->_composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) {
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
if (!_this->_composition_cache.has_element(i)) {
a = Py_None;
Py_INCREF(a);
b = Py_None;
Py_INCREF(b);
} else {
const RenderState *source = _this->_composition_cache.get_key(i);
if (source == (RenderState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState,
true, true, source->get_type_index());
}
const RenderState *result = _this->_composition_cache.get_data(i)._result;
if (result == (RenderState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState,
true, true, result->get_type_index());
}
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
PyList_SET_ITEM(list, i, tuple);
}
return list;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<RenderState>::get_invert_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// invert_composition cache. For each tuple in the list, the
// first element is the source render, and the second
// is the result render. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->invert_compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *Extension<RenderState>::
get_invert_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
LightReMutexHolder holder(*RenderState::_states_lock);
size_t cache_size = _this->_invert_composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) {
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
if (!_this->_invert_composition_cache.has_element(i)) {
a = Py_None;
Py_INCREF(a);
b = Py_None;
Py_INCREF(b);
} else {
const RenderState *source = _this->_invert_composition_cache.get_key(i);
if (source == (RenderState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState,
true, true, source->get_type_index());
}
const RenderState *result = _this->_invert_composition_cache.get_data(i)._result;
if (result == (RenderState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState,
true, true, result->get_type_index());
}
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
PyList_SET_ITEM(list, i, tuple);
}
return list;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<RenderState>::get_states
// Access: Published, Static
// Description: Returns a list of all of the RenderState objects
// in the state cache. The order of elements in this
// cache is arbitrary.
////////////////////////////////////////////////////////////////////
PyObject *Extension<RenderState>::
get_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
if (RenderState::_states == (RenderState::States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*RenderState::_states_lock);
size_t num_states = RenderState::_states->get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = RenderState::_states->get_size();
for (int si = 0; si < size; ++si) {
if (!RenderState::_states->has_element(si)) {
continue;
}
const RenderState *state = RenderState::_states->get_key(si);
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState,
true, true, state->get_type_index());
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, a);
++i;
}
nassertr(i == num_states, list);
return list;
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,42 @@
// Filename: renderState_ext.h
// Created by: CFSworks (31Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 RENDERSTATE_EXT_H
#define RENDERSTATE_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "renderState.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<RenderState>
// Description : This class defines the extension methods for
// RenderState, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<RenderState> : public ExtensionBase<RenderState> {
public:
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
static PyObject *get_states();
};
#endif // HAVE_PYTHON
#endif // RENDERSTATE_EXT_H

View File

@ -818,134 +818,6 @@ validate_composition_cache() const {
return true;
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// composition cache. For each tuple in the list, the
// first element is the source transform, and the second
// is the result transform. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *TransformState::
get_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_states_lock);
size_t num_states = _composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
const TransformState *source = _composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple);
++i;
}
nassertr(i == num_states, list);
return list;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_invert_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// invert_composition cache. For each tuple in the list, the
// first element is the source transform, and the second
// is the result transform. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->invert_compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *TransformState::
get_invert_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_states_lock);
size_t num_states = _invert_composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _invert_composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_invert_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
const TransformState *source = _invert_composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _invert_composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple);
++i;
}
nassertr(i == num_states, list);
return list;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::output
// Access: Published
@ -1529,81 +1401,6 @@ validate_states() {
return true;
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_states
// Access: Published, Static
// Description: Returns a list of all of the TransformState objects
// in the state cache. The order of elements in this
// cache is arbitrary.
////////////////////////////////////////////////////////////////////
PyObject *TransformState::
get_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
if (_states == (States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*_states_lock);
size_t num_states = _states->get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
const TransformState *state = _states->get_key(si);
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
true, true, state->get_type_index());
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, a);
++i;
}
nassertr(i == num_states, list);
return list;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_unused_states
// Access: Published, Static
// Description: Returns a list of all of the "unused" TransformState
// objects in the state cache. See
// get_num_unused_states().
////////////////////////////////////////////////////////////////////
PyObject *TransformState::
get_unused_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
if (_states == (States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*_states_lock);
PyObject *list = PyList_New(0);
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
const TransformState *state = _states->get_key(si);
if (state->get_cache_ref_count() == state->get_ref_count()) {
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
true, true, state->get_type_index());
PyList_Append(list, a);
Py_DECREF(a);
}
}
return list;
}
#endif // HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::init_states
// Access: Public, Static

View File

@ -32,6 +32,7 @@
#include "deletedChain.h"
#include "simpleHashMap.h"
#include "cacheStats.h"
#include "extension.h"
class GraphicsStateGuardianBase;
class FactoryParams;
@ -190,10 +191,8 @@ PUBLISHED:
INLINE const TransformState *get_invert_composition_cache_source(int n) const;
INLINE const TransformState *get_invert_composition_cache_result(int n) const;
bool validate_composition_cache() const;
#ifdef HAVE_PYTHON
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
#endif // HAVE_PYTHON
EXTENSION(PyObject *get_composition_cache() const);
EXTENSION(PyObject *get_invert_composition_cache() const);
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
@ -206,10 +205,8 @@ PUBLISHED:
static void list_cycles(ostream &out);
static void list_states(ostream &out);
static bool validate_states();
#ifdef HAVE_PYTHON
static PyObject *get_states();
static PyObject *get_unused_states();
#endif // HAVE_PYTHON
EXTENSION(static PyObject *get_states());
EXTENSION(static PyObject *get_unused_states());
public:
@ -405,6 +402,8 @@ public:
private:
static TypeHandle _type_handle;
friend class Extension<TransformState>;
};
INLINE ostream &operator << (ostream &out, const TransformState &state) {

View File

@ -0,0 +1,214 @@
// Filename: transformState_ext.cxx
// Created by: CFSworks (30Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 "transformState_ext.h"
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: Extension<TransformState>::get_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// composition cache. For each tuple in the list, the
// first element is the source transform, and the second
// is the result transform. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *Extension<TransformState>::
get_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_this->_states_lock);
size_t num_states = _this->_composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _this->_composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_this->_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
const TransformState *source = _this->_composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _this->_composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple);
++i;
}
nassertr(i == num_states, list);
return list;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<TransformState>::get_invert_composition_cache
// Access: Published
// Description: Returns a list of 2-tuples that represents the
// invert_composition cache. For each tuple in the list, the
// first element is the source transform, and the second
// is the result transform. If both are None, there is
// no entry in the cache at that slot.
//
// In general, a->invert_compose(source) == result.
//
// This has no practical value other than for examining
// the cache for performance analysis.
////////////////////////////////////////////////////////////////////
PyObject *Extension<TransformState>::
get_invert_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_this->_states_lock);
size_t num_states = _this->_invert_composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _this->_invert_composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_this->_invert_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2);
PyObject *a, *b;
const TransformState *source = _this->_invert_composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None;
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _this->_invert_composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple);
++i;
}
nassertr(i == num_states, list);
return list;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<TransformState>::get_states
// Access: Published, Static
// Description: Returns a list of all of the TransformState objects
// in the state cache. The order of elements in this
// cache is arbitrary.
////////////////////////////////////////////////////////////////////
PyObject *Extension<TransformState>::
get_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
if (TransformState::_states == (TransformState::States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*TransformState::_states_lock);
size_t num_states = TransformState::_states->get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = TransformState::_states->get_size();
for (int si = 0; si < size; ++si) {
if (!TransformState::_states->has_element(si)) {
continue;
}
const TransformState *state = TransformState::_states->get_key(si);
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
true, true, state->get_type_index());
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, a);
++i;
}
nassertr(i == num_states, list);
return list;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<TransformState>::get_unused_states
// Access: Published, Static
// Description: Returns a list of all of the "unused" TransformState
// objects in the state cache. See
// get_num_unused_states().
////////////////////////////////////////////////////////////////////
PyObject *Extension<TransformState>::
get_unused_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
if (TransformState::_states == (TransformState::States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*TransformState::_states_lock);
PyObject *list = PyList_New(0);
int size = TransformState::_states->get_size();
for (int si = 0; si < size; ++si) {
if (!TransformState::_states->has_element(si)) {
continue;
}
const TransformState *state = TransformState::_states->get_key(si);
if (state->get_cache_ref_count() == state->get_ref_count()) {
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
true, true, state->get_type_index());
PyList_Append(list, a);
Py_DECREF(a);
}
}
return list;
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,43 @@
// Filename: transformState_ext.h
// Created by: CFSworks (31Mar14)
//
////////////////////////////////////////////////////////////////////
//
// 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 TRANSFORMSTATE_EXT_H
#define TRANSFORMSTATE_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "transformState.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<TransformState>
// Description : This class defines the extension methods for
// TransformState, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<TransformState> : public ExtensionBase<TransformState> {
public:
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
static PyObject *get_states();
static PyObject *get_unused_states();
};
#endif // HAVE_PYTHON
#endif // TRANSFORMSTATE_EXT_H