mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -04:00
bamify NodePath's parents etc too, to better support common nodes
This commit is contained in:
parent
9e6bab46ab
commit
981890183b
@ -84,31 +84,6 @@ any_path(PandaNode *node, Thread *current_thread) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: NodePath::Constructor
|
|
||||||
// Access: Published
|
|
||||||
// Description: Constructs a NodePath with the indicated parent
|
|
||||||
// NodePath and child node; the child node must be a
|
|
||||||
// stashed or unstashed child of the parent.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE NodePath::
|
|
||||||
NodePath(const NodePath &parent, PandaNode *child_node,
|
|
||||||
Thread *current_thread) :
|
|
||||||
_error_type(ET_fail)
|
|
||||||
{
|
|
||||||
nassertv(!parent.is_empty());
|
|
||||||
nassertv(child_node != (PandaNode *)NULL);
|
|
||||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
|
||||||
_head = PandaNode::get_component(parent._head, child_node, pipeline_stage,
|
|
||||||
current_thread);
|
|
||||||
nassertv(_head != (NodePathComponent *)NULL);
|
|
||||||
|
|
||||||
if (_head != (NodePathComponent *)NULL) {
|
|
||||||
_error_type = ET_ok;
|
|
||||||
}
|
|
||||||
_backup_key = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NodePath::Copy Constructor
|
// Function: NodePath::Copy Constructor
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -2387,6 +2362,37 @@ get_name() const {
|
|||||||
return node()->get_name();
|
return node()->get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::encode_full_path_to_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: Converts the NodePath object into a single
|
||||||
|
// stream of data using a BamWriter, and returns that
|
||||||
|
// data as a string string. Returns empty string on
|
||||||
|
// failure.
|
||||||
|
//
|
||||||
|
// This is different from NodePath::write_bam_stream()
|
||||||
|
// and PandaNode::encode_to_bam_stream(), in that it
|
||||||
|
// encodes the *entire graph* of all nodes connected to
|
||||||
|
// the NodePath, including all parent nodes and
|
||||||
|
// siblings. (The other methods only encode this node
|
||||||
|
// and the nodes below it.) This may be necessary for
|
||||||
|
// correct streaming of related NodePaths and
|
||||||
|
// restoration of instances, etc., but it does mean you
|
||||||
|
// must detach() a node before writing it if you want to
|
||||||
|
// limit the nodes that get written.
|
||||||
|
//
|
||||||
|
// This method is used by __reduce__ to handle streaming
|
||||||
|
// of NodePaths to a pickle file.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE string NodePath::
|
||||||
|
encode_full_path_to_bam_stream() const {
|
||||||
|
string data;
|
||||||
|
if (!encode_full_path_to_bam_stream(data)) {
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE ostream &operator << (ostream &out, const NodePath &node_path) {
|
INLINE ostream &operator << (ostream &out, const NodePath &node_path) {
|
||||||
node_path.output(out);
|
node_path.output(out);
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
#include "pStatTimer.h"
|
#include "pStatTimer.h"
|
||||||
#include "modelNode.h"
|
#include "modelNode.h"
|
||||||
#include "py_panda.h"
|
#include "py_panda.h"
|
||||||
|
#include "bam.h"
|
||||||
|
|
||||||
// stack seems to overflow on Intel C++ at 7000. If we need more than
|
// stack seems to overflow on Intel C++ at 7000. If we need more than
|
||||||
// 7000, need to increase stack size.
|
// 7000, need to increase stack size.
|
||||||
@ -136,6 +137,36 @@ static ConfigVariableEnum<EmptyNodePathType> empty_node_path
|
|||||||
// ***End temporary transition code for operator bool
|
// ***End temporary transition code for operator bool
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description: Constructs a NodePath with the indicated parent
|
||||||
|
// NodePath and child node; the child node must be a
|
||||||
|
// stashed or unstashed child of the parent.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
NodePath::
|
||||||
|
NodePath(const NodePath &parent, PandaNode *child_node,
|
||||||
|
Thread *current_thread) :
|
||||||
|
_error_type(ET_fail)
|
||||||
|
{
|
||||||
|
nassertv(child_node != (PandaNode *)NULL);
|
||||||
|
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||||
|
|
||||||
|
if (parent.is_empty()) {
|
||||||
|
// Special case: constructing a NodePath at the root.
|
||||||
|
_head = PandaNode::attach(NULL, child_node, 0, pipeline_stage, current_thread);
|
||||||
|
} else {
|
||||||
|
_head = PandaNode::get_component(parent._head, child_node, pipeline_stage,
|
||||||
|
current_thread);
|
||||||
|
}
|
||||||
|
nassertv(_head != (NodePathComponent *)NULL);
|
||||||
|
|
||||||
|
if (_head != (NodePathComponent *)NULL) {
|
||||||
|
_error_type = ET_ok;
|
||||||
|
}
|
||||||
|
_backup_key = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NodePath::__copy__
|
// Function: NodePath::__copy__
|
||||||
@ -236,20 +267,6 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||||||
// (e.g. this), and the arguments necessary to reconstruct this
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
// object.
|
// object.
|
||||||
|
|
||||||
if (is_empty()) {
|
|
||||||
// Reconstruct an empty NodePath. Not a 100% reconstruction,
|
|
||||||
// because we lose the specific error status, but I don't think
|
|
||||||
// that matters much.
|
|
||||||
PyObject *this_class = PyObject_Type(self);
|
|
||||||
if (this_class == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *result = Py_BuildValue("(O())", this_class);
|
|
||||||
Py_DECREF(this_class);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BamWriter *writer = NULL;
|
BamWriter *writer = NULL;
|
||||||
if (pickler != NULL) {
|
if (pickler != NULL) {
|
||||||
PyObject *py_writer = PyObject_GetAttrString(pickler, "bamWriter");
|
PyObject *py_writer = PyObject_GetAttrString(pickler, "bamWriter");
|
||||||
@ -262,13 +279,12 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a non-empty NodePath. We need to streamify the
|
// We have a non-empty NodePath.
|
||||||
// underlying node.
|
|
||||||
|
|
||||||
string bam_stream;
|
string bam_stream;
|
||||||
if (!node()->encode_to_bam_stream(bam_stream, writer)) {
|
if (!encode_full_path_to_bam_stream(bam_stream, writer)) {
|
||||||
ostringstream stream;
|
ostringstream stream;
|
||||||
stream << "Could not bamify object of type " << node()->get_type() << "\n";
|
stream << "Could not bamify " << this;
|
||||||
string message = stream.str();
|
string message = stream.str();
|
||||||
PyErr_SetString(PyExc_TypeError, message.c_str());
|
PyErr_SetString(PyExc_TypeError, message.c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -6606,6 +6622,153 @@ write_bam_stream(ostream &out) const {
|
|||||||
return okflag;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::encode_full_path_to_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: Converts the NodePath object into a single
|
||||||
|
// stream of data using a BamWriter, and stores that
|
||||||
|
// data in the indicated string. Returns true on
|
||||||
|
// success, false on failure.
|
||||||
|
//
|
||||||
|
// This is different from NodePath::write_bam_stream()
|
||||||
|
// and PandaNode::encode_to_bam_stream(), in that it
|
||||||
|
// encodes the *entire graph* of all nodes connected to
|
||||||
|
// the NodePath, including all parent nodes and
|
||||||
|
// siblings. (The other methods only encode this node
|
||||||
|
// and the nodes below it.) This may be necessary for
|
||||||
|
// correct streaming of related NodePaths and
|
||||||
|
// restoration of instances, etc., but it does mean you
|
||||||
|
// must detach() a node before writing it if you want to
|
||||||
|
// limit the nodes that get written.
|
||||||
|
//
|
||||||
|
// This method is used by __reduce__ to handle streaming
|
||||||
|
// of NodePaths to a pickle file.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool NodePath::
|
||||||
|
encode_full_path_to_bam_stream(string &data, BamWriter *writer) const {
|
||||||
|
data.clear();
|
||||||
|
ostringstream stream;
|
||||||
|
|
||||||
|
DatagramOutputFile dout;
|
||||||
|
if (!dout.open(stream)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BamWriter local_writer;
|
||||||
|
if (writer == NULL) {
|
||||||
|
// Create our own writer.
|
||||||
|
|
||||||
|
if (!dout.write_header(_bam_header)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
writer = &local_writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer->set_target(&dout);
|
||||||
|
|
||||||
|
// Write an initial Datagram to represent the error type and
|
||||||
|
// number of nodes.
|
||||||
|
int num_nodes = get_num_nodes();
|
||||||
|
Datagram dg;
|
||||||
|
dg.add_uint8(_error_type);
|
||||||
|
dg.add_int32(num_nodes);
|
||||||
|
|
||||||
|
if (!dout.put_datagram(dg)) {
|
||||||
|
writer->set_target(NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now write the nodes, one at a time.
|
||||||
|
for (int i = 0; i < num_nodes; ++i) {
|
||||||
|
PandaNode *node = get_node(num_nodes - i - 1);
|
||||||
|
nassertr(node != NULL, false);
|
||||||
|
if (!writer->write_object(node)) {
|
||||||
|
writer->set_target(NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer->set_target(NULL);
|
||||||
|
|
||||||
|
data = stream.str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::decode_full_path_from_bam_stream
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Reads the string created by a previous call to
|
||||||
|
// encode_full_path_to_bam_stream(), and extracts and
|
||||||
|
// returns the NodePath on that string. Returns NULL on
|
||||||
|
// error.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
NodePath NodePath::
|
||||||
|
decode_full_path_from_bam_stream(const string &data, BamReader *reader) {
|
||||||
|
NodePath result;
|
||||||
|
|
||||||
|
istringstream stream(data);
|
||||||
|
|
||||||
|
DatagramInputFile din;
|
||||||
|
if (!din.open(stream)) {
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
BamReader local_reader;
|
||||||
|
if (reader == NULL) {
|
||||||
|
// Create a local reader.
|
||||||
|
|
||||||
|
string head;
|
||||||
|
if (!din.read_header(head, _bam_header.size())) {
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head != _bam_header) {
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
reader = &local_reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader->set_source(&din);
|
||||||
|
|
||||||
|
// One initial datagram to encode the error type, and the number of nodes.
|
||||||
|
Datagram dg;
|
||||||
|
if (!din.get_datagram(dg)) {
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
DatagramIterator dgi(dg);
|
||||||
|
ErrorType error_type = (ErrorType)dgi.get_uint8();
|
||||||
|
int num_nodes = dgi.get_int32();
|
||||||
|
if (num_nodes == 0) {
|
||||||
|
// An empty NodePath.
|
||||||
|
result._error_type = error_type;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// A real NodePath. Ignore error_type.
|
||||||
|
for (int i = 0; i < num_nodes; ++i) {
|
||||||
|
TypedWritable *object = reader->read_object();
|
||||||
|
|
||||||
|
if (object == (TypedWritable *)NULL ||
|
||||||
|
!object->is_of_type(PandaNode::get_class_type())) {
|
||||||
|
reader->set_source(NULL);
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reader->resolve()) {
|
||||||
|
reader->set_source(NULL);
|
||||||
|
return NodePath::fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
PandaNode *node = DCAST(PandaNode, object);
|
||||||
|
result = NodePath(result, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader->set_source(NULL);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NodePath::find_common_ancestor
|
// Function: NodePath::find_common_ancestor
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -7542,7 +7705,6 @@ py_decode_NodePath_from_bam_stream(const string &data) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NodePath
|
NodePath
|
||||||
py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &data) {
|
py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &data) {
|
||||||
|
|
||||||
BamReader *reader = NULL;
|
BamReader *reader = NULL;
|
||||||
if (unpickler != NULL) {
|
if (unpickler != NULL) {
|
||||||
PyObject *py_reader = PyObject_GetAttrString(unpickler, "bamReader");
|
PyObject *py_reader = PyObject_GetAttrString(unpickler, "bamReader");
|
||||||
@ -7555,13 +7717,7 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &da
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PT(PandaNode) node = PandaNode::decode_from_bam_stream(data, reader);
|
return NodePath::decode_full_path_from_bam_stream(data, reader);
|
||||||
if (node == (PandaNode *)NULL) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "Could not unpack bam stream");
|
|
||||||
return NodePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NodePath(node);
|
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ PUBLISHED:
|
|||||||
INLINE NodePath(const string &top_node_name, Thread *current_thread = Thread::get_current_thread());
|
INLINE NodePath(const string &top_node_name, Thread *current_thread = Thread::get_current_thread());
|
||||||
INLINE NodePath(PandaNode *node, Thread *current_thread = Thread::get_current_thread());
|
INLINE NodePath(PandaNode *node, Thread *current_thread = Thread::get_current_thread());
|
||||||
INLINE static NodePath any_path(PandaNode *node, Thread *current_thread = Thread::get_current_thread());
|
INLINE static NodePath any_path(PandaNode *node, Thread *current_thread = Thread::get_current_thread());
|
||||||
INLINE NodePath(const NodePath &parent, PandaNode *child_node,
|
NodePath(const NodePath &parent, PandaNode *child_node,
|
||||||
Thread *current_thread = Thread::get_current_thread());
|
Thread *current_thread = Thread::get_current_thread());
|
||||||
|
|
||||||
INLINE NodePath(const NodePath ©);
|
INLINE NodePath(const NodePath ©);
|
||||||
INLINE void operator = (const NodePath ©);
|
INLINE void operator = (const NodePath ©);
|
||||||
@ -869,6 +869,10 @@ PUBLISHED:
|
|||||||
BLOCKING bool write_bam_file(const string &filename) const;
|
BLOCKING bool write_bam_file(const string &filename) const;
|
||||||
BLOCKING bool write_bam_stream(ostream &out) const;
|
BLOCKING bool write_bam_stream(ostream &out) const;
|
||||||
|
|
||||||
|
INLINE string encode_full_path_to_bam_stream() const;
|
||||||
|
bool encode_full_path_to_bam_stream(string &data, BamWriter *writer = NULL) const;
|
||||||
|
static NodePath decode_full_path_from_bam_stream(const string &data, BamReader *reader = NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static NodePathComponent *
|
static NodePathComponent *
|
||||||
find_common_ancestor(const NodePath &a, const NodePath &b,
|
find_common_ancestor(const NodePath &a, const NodePath &b,
|
||||||
|
@ -82,7 +82,7 @@ get_bam_modified() const {
|
|||||||
// efficient to use the same BamWriter to serialize all
|
// efficient to use the same BamWriter to serialize all
|
||||||
// of them together.
|
// of them together.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
string TypedWritable::
|
INLINE string TypedWritable::
|
||||||
encode_to_bam_stream() const {
|
encode_to_bam_stream() const {
|
||||||
string data;
|
string data;
|
||||||
if (!encode_to_bam_stream(data)) {
|
if (!encode_to_bam_stream(data)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user