Selaa lähdekoodia

egg: add pickle support to most EggData classes

rdb 5 vuotta sitten
vanhempi
sitoutus
c77593f3f0

+ 2 - 2
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')

+ 2 - 0
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;
 

+ 32 - 0
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<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

+ 37 - 0
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<EggComment> : public ExtensionBase<EggComment> {
+public:
+  PyObject *__reduce__() const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // EGGCOMMENT_EXT_H

+ 2 - 0
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;
 

+ 32 - 0
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<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

+ 37 - 0
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<EggCoordinateSystem> : public ExtensionBase<EggCoordinateSystem> {
+public:
+  PyObject *__reduce__() const;
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // EGGCOORDINATESYSTEM_EXT_H

+ 2 - 0
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 {

+ 93 - 0
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<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

+ 42 - 0
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<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

+ 4 - 0
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"