egg: add pickle support to most EggData classes

This commit is contained in:
rdb 2021-01-01 16:58:08 +01:00
parent f8ce339960
commit c77593f3f0
11 changed files with 285 additions and 2 deletions

View File

@ -4945,7 +4945,7 @@ if not RUNTIME and not PkgSkip("EGG"):
if "parser.h" in IGATEFILES: IGATEFILES.remove("parser.h")
TargetAdd('libp3egg.in', opts=OPTS, input=IGATEFILES)
TargetAdd('libp3egg.in', opts=['IMOD:panda3d.egg', 'ILIB:libp3egg', 'SRCDIR:panda/src/egg'])
PyTargetAdd('p3egg_eggGroupNode_ext.obj', opts=OPTS, input='eggGroupNode_ext.cxx')
PyTargetAdd('p3egg_ext_composite.obj', opts=OPTS, input='p3egg_ext_composite.cxx')
#
# DIRECTORY: panda/src/egg2pg/
@ -5035,7 +5035,7 @@ if not RUNTIME and not PkgSkip("EGG"):
PyTargetAdd('egg_module.obj', opts=['IMOD:panda3d.egg', 'ILIB:egg', 'IMPORT:panda3d.core'])
PyTargetAdd('egg.pyd', input='egg_module.obj')
PyTargetAdd('egg.pyd', input='p3egg_eggGroupNode_ext.obj')
PyTargetAdd('egg.pyd', input='p3egg_ext_composite.obj')
PyTargetAdd('egg.pyd', input='libp3egg_igate.obj')
PyTargetAdd('egg.pyd', input='libp3egg2pg_igate.obj')
PyTargetAdd('egg.pyd', input='libpandaegg.dll')

View File

@ -41,6 +41,8 @@ PUBLISHED:
virtual void write(std::ostream &out, int indent_level) const;
EXTENSION(PyObject *__reduce__() const);
private:
std::string _comment;

View File

@ -0,0 +1,32 @@
/**
* 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."
*
* @file eggComment_ext.cxx
* @author rdb
* @date 2021-01-01
*/
#include "eggComment_ext.h"
#ifdef HAVE_PYTHON
/**
* Implements pickle support.
*/
PyObject *Extension<EggComment>::
__reduce__() const {
extern struct Dtool_PyTypedObject Dtool_EggComment;
std::string node_name = _this->get_name();
std::string comment = _this->get_comment();
return Py_BuildValue("O(s#s#)", (PyObject *)&Dtool_EggComment,
node_name.data(), (Py_ssize_t)node_name.length(),
comment.data(), (Py_ssize_t)comment.length());
}
#endif

View File

@ -0,0 +1,37 @@
/**
* 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."
*
* @file eggComment_ext.h
* @author rdb
* @date 2021-01-01
*/
#ifndef EGGCOMMENT_EXT_H
#define EGGCOMMENT_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "eggComment.h"
#include "py_panda.h"
/**
* This class defines the extension methods for EggComment, which are
* called instead of any C++ methods with the same prototype.
*/
template<>
class Extension<EggComment> : public ExtensionBase<EggComment> {
public:
PyObject *__reduce__() const;
};
#endif // HAVE_PYTHON
#endif // EGGCOMMENT_EXT_H

View File

@ -36,6 +36,8 @@ PUBLISHED:
virtual void write(std::ostream &out, int indent_level) const;
EXTENSION(PyObject *__reduce__() const);
private:
CoordinateSystem _value;

View File

@ -0,0 +1,32 @@
/**
* 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."
*
* @file eggCoordinateSystem_ext.cxx
* @author rdb
* @date 2021-01-01
*/
#include "eggCoordinateSystem_ext.h"
#ifdef HAVE_PYTHON
/**
* Implements pickle support.
*/
PyObject *Extension<EggCoordinateSystem>::
__reduce__() const {
extern struct Dtool_PyTypedObject Dtool_EggCoordinateSystem;
// We can't use the regular EggNode handling for EggCoordinateSystem, because
// the <CoordinateSystem> node is removed from the EggData after reading.
// Oh well, this is more efficient anyway.
int value = _this->get_value();
return Py_BuildValue("O(i)", (PyObject *)&Dtool_EggCoordinateSystem, value);
}
#endif

View File

@ -0,0 +1,37 @@
/**
* 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."
*
* @file eggCoordinateSystem_ext.h
* @author rdb
* @date 2021-01-01
*/
#ifndef EGGCOORDINATESYSTEM_EXT_H
#define EGGCOORDINATESYSTEM_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "eggCoordinateSystem.h"
#include "py_panda.h"
/**
* This class defines the extension methods for EggCoordinateSystem, which are
* called instead of any C++ methods with the same prototype.
*/
template<>
class Extension<EggCoordinateSystem> : public ExtensionBase<EggCoordinateSystem> {
public:
PyObject *__reduce__() const;
};
#endif // HAVE_PYTHON
#endif // EGGCOORDINATESYSTEM_EXT_H

View File

@ -22,6 +22,7 @@
#include "lmatrix.h"
#include "pointerTo.h"
#include "referenceCount.h"
#include "extension.h"
class EggGroupNode;
class EggRenderMode;
@ -90,6 +91,7 @@ PUBLISHED:
void test_under_integrity() const { }
#endif // _DEBUG
EXTENSION(PyObject *__reduce__() const);
protected:
enum UnderFlags {

View File

@ -0,0 +1,93 @@
/**
* 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."
*
* @file eggNode_ext.cxx
* @author rdb
* @date 2021-01-01
*/
#include "eggNode_ext.h"
#include "eggData.h"
#ifdef HAVE_PYTHON
/**
* Implements pickle support.
*/
PyObject *Extension<EggNode>::
__reduce__() const {
extern struct Dtool_PyTypedObject Dtool_EggNode;
// Find the parse_egg_node function in this module.
PyObject *sys_modules = PyImport_GetModuleDict();
nassertr_always(sys_modules != nullptr, nullptr);
PyObject *module_name = PyObject_GetAttrString((PyObject *)&Dtool_EggNode, "__module__");
nassertr_always(module_name != nullptr, nullptr);
PyObject *module = PyDict_GetItem(sys_modules, module_name);
Py_DECREF(module_name);
nassertr_always(module != nullptr, nullptr);
PyObject *func;
if (_this->is_of_type(EggData::get_class_type())) {
func = PyObject_GetAttrString(module, "parse_egg_data");
} else {
func = PyObject_GetAttrString(module, "parse_egg_node");
}
nassertr_always(func != nullptr, nullptr);
// Get the egg syntax to pass to the parse_egg_node function.
std::ostringstream stream;
_this->write(stream, INT_MIN);
std::string data = stream.str();
size_t length = data.size();
// Trim trailing whitespace.
while (length > 0 && isspace(data[length - 1])) {
--length;
}
return Py_BuildValue("N(s#)", func, data.data(), (Py_ssize_t)length);
}
/**
* Parses an EggData from the raw egg syntax.
*/
PT(EggData) parse_egg_data(const std::string &egg_syntax) {
PT(EggData) data = new EggData;
data->set_auto_resolve_externals(false);
std::istringstream in(egg_syntax);
if (!data->read(in)) {
PyErr_Format(PyExc_RuntimeError, "failed to parse egg data");
return nullptr;
}
return data;
}
/**
* Parses a single egg node from the raw egg syntax.
*/
PT(EggNode) parse_egg_node(const std::string &egg_syntax) {
PT(EggData) data = parse_egg_data(egg_syntax);
if (data == nullptr) {
return nullptr;
}
if (data->size() != 1) {
PyErr_Format(PyExc_RuntimeError, "expected exactly one node");
return nullptr;
}
return data->remove_child(data->get_first_child());
}
#endif

View File

@ -0,0 +1,42 @@
/**
* 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."
*
* @file eggNode_ext.h
* @author rdb
* @date 2021-01-01
*/
#ifndef EGGNODE_EXT_H
#define EGGNODE_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "eggNode.h"
#include "py_panda.h"
/**
* This class defines the extension methods for EggNode, which are
* called instead of any C++ methods with the same prototype.
*/
template<>
class Extension<EggNode> : public ExtensionBase<EggNode> {
public:
PyObject *__reduce__() const;
};
BEGIN_PUBLISH
PT(EggData) parse_egg_data(const std::string &egg_syntax);
PT(EggNode) parse_egg_node(const std::string &egg_syntax);
END_PUBLISH
#endif // HAVE_PYTHON
#endif // EGGNODE_EXT_H

View File

@ -0,0 +1,4 @@
#include "eggComment_ext.cxx"
#include "eggCoordinateSystem_ext.cxx"
#include "eggGroupNode_ext.cxx"
#include "eggNode_ext.cxx"