mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
Commit patch by cfsworks to move pgraph stuff to extensions
This commit is contained in:
parent
d792c93026
commit
566feda34d
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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__());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
5
panda/src/pgraph/p3pgraph_ext_composite.cxx
Normal file
5
panda/src/pgraph/p3pgraph_ext_composite.cxx
Normal 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"
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
259
panda/src/pgraph/pandaNode_ext.cxx
Normal file
259
panda/src/pgraph/pandaNode_ext.cxx
Normal 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
|
||||
|
50
panda/src/pgraph/pandaNode_ext.h
Normal file
50
panda/src/pgraph/pandaNode_ext.h
Normal 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
|
@ -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
|
||||
|
@ -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) {
|
||||
|
174
panda/src/pgraph/renderState_ext.cxx
Normal file
174
panda/src/pgraph/renderState_ext.cxx
Normal 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
|
42
panda/src/pgraph/renderState_ext.h
Normal file
42
panda/src/pgraph/renderState_ext.h
Normal 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
|
@ -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
|
||||
|
@ -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) {
|
||||
|
214
panda/src/pgraph/transformState_ext.cxx
Normal file
214
panda/src/pgraph/transformState_ext.cxx
Normal 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
|
43
panda/src/pgraph/transformState_ext.h
Normal file
43
panda/src/pgraph/transformState_ext.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user