diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index e493900a5e..a80e85ad04 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -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') diff --git a/panda/src/egg/eggComment.h b/panda/src/egg/eggComment.h index 17611ed5d5..5e02595d3c 100644 --- a/panda/src/egg/eggComment.h +++ b/panda/src/egg/eggComment.h @@ -41,6 +41,8 @@ PUBLISHED: virtual void write(std::ostream &out, int indent_level) const; + EXTENSION(PyObject *__reduce__() const); + private: std::string _comment; diff --git a/panda/src/egg/eggComment_ext.cxx b/panda/src/egg/eggComment_ext.cxx new file mode 100644 index 0000000000..f058964066 --- /dev/null +++ b/panda/src/egg/eggComment_ext.cxx @@ -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:: +__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 diff --git a/panda/src/egg/eggComment_ext.h b/panda/src/egg/eggComment_ext.h new file mode 100644 index 0000000000..2f13498d43 --- /dev/null +++ b/panda/src/egg/eggComment_ext.h @@ -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 : public ExtensionBase { +public: + PyObject *__reduce__() const; +}; + +#endif // HAVE_PYTHON + +#endif // EGGCOMMENT_EXT_H diff --git a/panda/src/egg/eggCoordinateSystem.h b/panda/src/egg/eggCoordinateSystem.h index 54a76e6f78..a3e105827c 100644 --- a/panda/src/egg/eggCoordinateSystem.h +++ b/panda/src/egg/eggCoordinateSystem.h @@ -36,6 +36,8 @@ PUBLISHED: virtual void write(std::ostream &out, int indent_level) const; + EXTENSION(PyObject *__reduce__() const); + private: CoordinateSystem _value; diff --git a/panda/src/egg/eggCoordinateSystem_ext.cxx b/panda/src/egg/eggCoordinateSystem_ext.cxx new file mode 100644 index 0000000000..2b26b0abec --- /dev/null +++ b/panda/src/egg/eggCoordinateSystem_ext.cxx @@ -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:: +__reduce__() const { + extern struct Dtool_PyTypedObject Dtool_EggCoordinateSystem; + + // We can't use the regular EggNode handling for EggCoordinateSystem, because + // the 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 diff --git a/panda/src/egg/eggCoordinateSystem_ext.h b/panda/src/egg/eggCoordinateSystem_ext.h new file mode 100644 index 0000000000..c5dc3794c6 --- /dev/null +++ b/panda/src/egg/eggCoordinateSystem_ext.h @@ -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 : public ExtensionBase { +public: + PyObject *__reduce__() const; +}; + +#endif // HAVE_PYTHON + +#endif // EGGCOORDINATESYSTEM_EXT_H diff --git a/panda/src/egg/eggNode.h b/panda/src/egg/eggNode.h index 950ae5e257..48f4443ed4 100644 --- a/panda/src/egg/eggNode.h +++ b/panda/src/egg/eggNode.h @@ -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 { diff --git a/panda/src/egg/eggNode_ext.cxx b/panda/src/egg/eggNode_ext.cxx new file mode 100644 index 0000000000..3056e40d6d --- /dev/null +++ b/panda/src/egg/eggNode_ext.cxx @@ -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:: +__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 diff --git a/panda/src/egg/eggNode_ext.h b/panda/src/egg/eggNode_ext.h new file mode 100644 index 0000000000..aa94aa41cd --- /dev/null +++ b/panda/src/egg/eggNode_ext.h @@ -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 : public ExtensionBase { +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 diff --git a/panda/src/egg/p3egg_ext_composite.cxx b/panda/src/egg/p3egg_ext_composite.cxx new file mode 100644 index 0000000000..f94bca9c30 --- /dev/null +++ b/panda/src/egg/p3egg_ext_composite.cxx @@ -0,0 +1,4 @@ +#include "eggComment_ext.cxx" +#include "eggCoordinateSystem_ext.cxx" +#include "eggGroupNode_ext.cxx" +#include "eggNode_ext.cxx"