Browse Source

outbound scripting

David Rose 16 years ago
parent
commit
25dd6bcc71

+ 2 - 0
direct/src/plugin/Sources.pp

@@ -30,6 +30,7 @@
     p3dInstanceManager.h p3dInstanceManager.I \
     p3dIntObject.h \
     p3dMultifileReader.h p3dMultifileReader.I \
+    p3dNoneObject.h p3dNullObject.h \
     p3dPackage.h p3dPackage.I \
     p3dPythonObject.h \
     p3dSession.h p3dSession.I \
@@ -51,6 +52,7 @@
     p3dInstanceManager.cxx \
     p3dIntObject.cxx \
     p3dMultifileReader.cxx \
+    p3dNoneObject.cxx p3dNullObject.cxx \
     p3dPackage.cxx \
     p3dPythonObject.cxx \
     p3dSession.cxx \

+ 5 - 0
direct/src/plugin/load_plugin.cxx

@@ -42,6 +42,7 @@ P3D_instance_finish_func *P3D_instance_finish;
 P3D_instance_setup_window_func *P3D_instance_setup_window;
 
 P3D_make_class_definition_func *P3D_make_class_definition;
+P3D_new_null_object_func *P3D_new_null_object;
 P3D_new_none_object_func *P3D_new_none_object;
 P3D_new_bool_object_func *P3D_new_bool_object;
 P3D_new_int_object_func *P3D_new_int_object;
@@ -165,6 +166,7 @@ load_plugin(const string &p3d_plugin_filename) {
   P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window");  
 
   P3D_make_class_definition = (P3D_make_class_definition_func *)get_func(module, "P3D_make_class_definition");
+  P3D_new_null_object = (P3D_new_null_object_func *)get_func(module, "P3D_new_null_object");
   P3D_new_none_object = (P3D_new_none_object_func *)get_func(module, "P3D_new_none_object");
   P3D_new_bool_object = (P3D_new_bool_object_func *)get_func(module, "P3D_new_bool_object");
   P3D_new_int_object = (P3D_new_int_object_func *)get_func(module, "P3D_new_int_object");
@@ -189,6 +191,7 @@ load_plugin(const string &p3d_plugin_filename) {
       P3D_instance_setup_window == NULL ||
 
       P3D_make_class_definition == NULL ||
+      P3D_new_null_object == NULL ||
       P3D_new_none_object == NULL ||
       P3D_new_bool_object == NULL ||
       P3D_new_int_object == NULL ||
@@ -212,6 +215,7 @@ load_plugin(const string &p3d_plugin_filename) {
       << "\nP3D_instance_setup_window = " << P3D_instance_setup_window
       
       << "\nP3D_make_class_definition = " << P3D_make_class_definition
+      << "\nP3D_new_null_object = " << P3D_new_null_object
       << "\nP3D_new_none_object = " << P3D_new_none_object
       << "\nP3D_new_bool_object = " << P3D_new_bool_object
       << "\nP3D_new_int_object = " << P3D_new_int_object
@@ -293,6 +297,7 @@ unload_dso() {
   P3D_instance_setup_window = NULL;
 
   P3D_make_class_definition = NULL;
+  P3D_new_null_object = NULL;
   P3D_new_none_object = NULL;
   P3D_new_bool_object = NULL;
   P3D_new_int_object = NULL;

+ 1 - 0
direct/src/plugin/load_plugin.h

@@ -28,6 +28,7 @@ extern P3D_instance_finish_func *P3D_instance_finish;
 extern P3D_instance_setup_window_func *P3D_instance_setup_window;
 
 extern P3D_make_class_definition_func *P3D_make_class_definition;
+extern P3D_new_null_object_func *P3D_new_null_object;
 extern P3D_new_none_object_func *P3D_new_none_object;
 extern P3D_new_bool_object_func *P3D_new_bool_object;
 extern P3D_new_int_object_func *P3D_new_int_object;

+ 65 - 7
direct/src/plugin/p3dInstance.cxx

@@ -514,14 +514,14 @@ handle_script_request(P3D_request *request) {
   switch (request->_request._script._op) {
   case P3D_SO_get_property:
     {
-      P3D_object *value = P3D_OBJECT_GET_PROPERTY(object, request->_request._script._property_name);
+      P3D_object *result = P3D_OBJECT_GET_PROPERTY(object, request->_request._script._property_name);
       nout << "get_property, object = " << object << "\n";
       if (object != NULL) {
         nout << "  *object = " << *object << "\n" << flush;
       }
-      nout << "value = " << value << "\n" << flush;
-      if (value != NULL) {
-        nout << "  *value = " << *value << "\n" << flush;
+      nout << "result = " << result << "\n" << flush;
+      if (result != NULL) {
+        nout << "  *result = " << *result << "\n" << flush;
       }
       // We've got the property value; feed it back down to the
       // subprocess.
@@ -533,14 +533,72 @@ handle_script_request(P3D_request *request) {
       
       doc->LinkEndChild(decl);
       doc->LinkEndChild(xcommand);
-      if (value != NULL) {
-        xcommand->LinkEndChild(_session->p3dobj_to_xml(value));
-        P3D_OBJECT_FINISH(value);
+      if (result != NULL) {
+        xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
+        P3D_OBJECT_FINISH(result);
       }
       
       _session->send_command(doc);
     }
     break;
+
+  case P3D_SO_set_property:
+    {
+      bool result = P3D_OBJECT_SET_PROPERTY(object, request->_request._script._property_name,
+                                            request->_request._script._value);
+      nout << "set_property, object = " << object << "\n";
+      if (object != NULL) {
+        nout << "  *object = " << *object << "\n" << flush;
+      }
+      nout << "result = " << result << "\n" << flush;
+
+      // Feed the result back down to the subprocess.
+      TiXmlDocument *doc = new TiXmlDocument;
+      TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
+      TiXmlElement *xcommand = new TiXmlElement("command");
+      xcommand->SetAttribute("cmd", "script_response");
+      xcommand->SetAttribute("unique_id", unique_id);
+      
+      doc->LinkEndChild(decl);
+      doc->LinkEndChild(xcommand);
+
+      TiXmlElement *xvalue = new TiXmlElement("value");
+      xvalue->SetAttribute("type", "bool");
+      xvalue->SetAttribute("value", (int)result);
+      xcommand->LinkEndChild(xvalue);
+      
+      _session->send_command(doc);
+    }
+    break;
+
+  case P3D_SO_del_property:
+    {
+      bool result = P3D_OBJECT_SET_PROPERTY(object, request->_request._script._property_name,
+                                            NULL);
+      nout << "del_property, object = " << object << "\n";
+      if (object != NULL) {
+        nout << "  *object = " << *object << "\n" << flush;
+      }
+      nout << "result = " << result << "\n" << flush;
+
+      // Feed the result back down to the subprocess.
+      TiXmlDocument *doc = new TiXmlDocument;
+      TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
+      TiXmlElement *xcommand = new TiXmlElement("command");
+      xcommand->SetAttribute("cmd", "script_response");
+      xcommand->SetAttribute("unique_id", unique_id);
+      
+      doc->LinkEndChild(decl);
+      doc->LinkEndChild(xcommand);
+
+      TiXmlElement *xvalue = new TiXmlElement("value");
+      xvalue->SetAttribute("type", "bool");
+      xvalue->SetAttribute("value", (int)result);
+      xcommand->LinkEndChild(xvalue);
+      
+      _session->send_command(doc);
+    }
+    break;
   }
 }
 

+ 1 - 1
direct/src/plugin/p3dNoneObject.h

@@ -21,7 +21,7 @@
 ////////////////////////////////////////////////////////////////////
 //       Class : P3DNoneObject
 // Description : An object type that contains no value, similar to
-//               Python's None type.
+//               Python's None type, or JavaScript's void type.
 ////////////////////////////////////////////////////////////////////
 class P3DNoneObject : public P3DObject {
 public:

+ 56 - 0
direct/src/plugin/p3dNullObject.cxx

@@ -0,0 +1,56 @@
+// Filename: p3dNullObject.cxx
+// Created by:  drose (07Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "p3dNullObject.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DNullObject::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DNullObject::
+P3DNullObject() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DNullObject::get_type
+//       Access: Public, Virtual
+//  Description: Returns the fundamental type of this kind of object.
+////////////////////////////////////////////////////////////////////
+P3D_object_type P3DNullObject::
+get_type() const {
+  return P3D_OT_null;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DNullObject::get_bool
+//       Access: Public, Virtual
+//  Description: Returns the object value coerced to a boolean, if
+//               possible.
+////////////////////////////////////////////////////////////////////
+bool P3DNullObject::
+get_bool() const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DNullObject::make_string
+//       Access: Public, Virtual
+//  Description: Fills the indicated C++ string object with the value
+//               of this object coerced to a string.
+////////////////////////////////////////////////////////////////////
+void P3DNullObject::
+make_string(string &value) const {
+  value = "Null";
+}

+ 39 - 0
direct/src/plugin/p3dNullObject.h

@@ -0,0 +1,39 @@
+// Filename: p3dNullObject.h
+// Created by:  drose (07Jul09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 P3DNULLOBJECT_H
+#define P3DNULLOBJECT_H
+
+#include "p3d_plugin_common.h"
+#include "p3dObject.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DNullObject
+// Description : An object type that represents a NULL pointer.
+//               Python doesn't have such a concept, but C and
+//               JavaScript do, and it is sometimes an important
+//               return value.
+////////////////////////////////////////////////////////////////////
+class P3DNullObject : public P3DObject {
+public:
+  P3DNullObject();
+
+public:
+  virtual P3D_object_type get_type() const;
+  virtual bool get_bool() const;
+  virtual void make_string(string &value) const;
+};
+
+#endif
+

+ 24 - 1
direct/src/plugin/p3dPythonRun.cxx

@@ -126,6 +126,20 @@ run_python() {
   }
   Py_DECREF(app_runner_class);
 
+  // Get the NullObject class.
+  _null_object_class = PyObject_GetAttrString(runp3d, "NullObject");
+  if (_null_object_class == NULL) {
+    PyErr_Print();
+    return false;
+  }
+
+  // And the "Null" instance.
+  _null = PyObject_GetAttrString(runp3d, "Null");
+  if (_null == NULL) {
+    PyErr_Print();
+    return false;
+  }
+
   // Get the BrowserObject class.
   _browser_object_class = PyObject_GetAttrString(runp3d, "BrowserObject");
   if (_browser_object_class == NULL) {
@@ -552,7 +566,8 @@ py_request_func(PyObject *args) {
       nout << "Converting xvalue: " << *xvalue << "\n";
       value = xml_to_pyobj(xvalue);
     } else {
-      value = Py_None;
+      // An absence of a <value> element means a NULL pointer.
+      value = _null;
       Py_INCREF(value);
     }
     nout << "Got script_response " << response_id << ", xvalue = " << xvalue << "\n";
@@ -930,6 +945,10 @@ pyobj_to_xml(PyObject *value) {
       xvalue->SetAttribute("value", str);
     }
 
+  } else if (PyObject_IsInstance(value, _null_object_class)) {
+    // This is a NullObject, our equivalent to a NULL pointer.
+    xvalue->SetAttribute("type", "null");
+
   } else if (PyObject_IsInstance(value, _browser_object_class)) {
     // This is a BrowserObject, a reference to an object that actually
     // exists in the host namespace.  So, pass up the appropriate
@@ -996,6 +1015,10 @@ xml_to_pyobj(TiXmlElement *xvalue) {
       return PyString_FromStringAndSize(value->data(), value->length());
     }
 
+  } else if (strcmp(type, "null") == 0) {
+    Py_INCREF(_null);
+    return _null;
+
   } else if (strcmp(type, "browser") == 0) {
     int object_id;
     if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {

+ 2 - 0
direct/src/plugin/p3dPythonRun.h

@@ -110,6 +110,8 @@ private:
   char **_py_argv;
 
   PyObject *_runner;
+  PyObject *_null_object_class;
+  PyObject *_null;
   PyObject *_browser_object_class;
   PyObject *_taskMgr;
 

+ 25 - 1
direct/src/plugin/p3dSession.cxx

@@ -16,6 +16,7 @@
 #include "p3dInstance.h"
 #include "p3dInstanceManager.h"
 #include "p3d_plugin_config.h"
+#include "p3dNullObject.h"
 #include "p3dNoneObject.h"
 #include "p3dBoolObject.h"
 #include "p3dIntObject.h"
@@ -321,7 +322,10 @@ command_and_response(TiXmlDocument *command) {
 P3D_object *P3DSession::
 xml_to_p3dobj(const TiXmlElement *xvalue) {
   const char *type = xvalue->Attribute("type");
-  if (strcmp(type, "none") == 0) {
+  if (strcmp(type, "null") == 0) {
+    return new P3DNullObject;
+
+  } else if (strcmp(type, "none") == 0) {
     return new P3DNoneObject;
 
   } else if (strcmp(type, "bool") == 0) {
@@ -382,6 +386,10 @@ p3dobj_to_xml(const P3D_object *obj) {
   TiXmlElement *xvalue = new TiXmlElement("value");
 
   switch (P3D_OBJECT_GET_TYPE(obj)) {
+  case P3D_OT_null:
+    xvalue->SetAttribute("type", "null");
+    break;
+
   case P3D_OT_none:
     xvalue->SetAttribute("type", "none");
     break;
@@ -704,6 +712,22 @@ rt_make_p3d_request(TiXmlElement *xrequest) {
           request->_request._script._property_name = strdup(property_name);
           request->_request._script._value = NULL;
           request->_request._script._unique_id = unique_id;
+        } else if (strcmp(operation, "set_property") == 0 && property_name != NULL && xvalue != NULL) {
+          request = new P3D_request;
+          request->_request_type = P3D_RT_script;
+          request->_request._script._object = object;
+          request->_request._script._op = P3D_SO_set_property;
+          request->_request._script._property_name = strdup(property_name);
+          request->_request._script._value = xml_to_p3dobj(xvalue);
+          request->_request._script._unique_id = unique_id;
+        } else if (strcmp(operation, "del_property") == 0 && property_name != NULL) {
+          request = new P3D_request;
+          request->_request_type = P3D_RT_script;
+          request->_request._script._object = object;
+          request->_request._script._op = P3D_SO_del_property;
+          request->_request._script._property_name = strdup(property_name);
+          request->_request._script._value = NULL;
+          request->_request._script._unique_id = unique_id;
         }
         if (request == NULL) {
           // If we haven't dispatched a request yet, we didn't use the

+ 12 - 0
direct/src/plugin/p3d_plugin.cxx

@@ -16,6 +16,7 @@
 #include "p3dInstanceManager.h"
 #include "p3dInstance.h"
 #include "p3dWindowParams.h"
+#include "p3dNullObject.h"
 #include "p3dNoneObject.h"
 #include "p3dBoolObject.h"
 #include "p3dIntObject.h"
@@ -132,6 +133,17 @@ P3D_make_class_definition() {
   return result;
 }
 
+P3D_object *
+P3D_new_null_object() {
+  assert(P3DInstanceManager::get_global_ptr()->is_initialized());
+  ACQUIRE_LOCK(_api_lock);
+
+  P3D_object *result = new P3DNullObject();
+  
+  RELEASE_LOCK(_api_lock);
+  return result;
+}
+
 P3D_object *
 P3D_new_none_object() {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());

+ 10 - 0
direct/src/plugin/p3d_plugin.h

@@ -294,6 +294,7 @@ typedef struct _P3D_object P3D_object;
 
 /* A list of fundamental object types. */
 typedef enum {
+  P3D_OT_null,
   P3D_OT_none,
   P3D_OT_bool,
   P3D_OT_int,
@@ -449,6 +450,13 @@ struct _P3D_object {
 typedef P3D_class_definition *
 P3D_make_class_definition_func();
 
+/* Allocates a new P3D_object of type null.  This value has no
+   particular value and corresponds a NULL pointer in C or JavaScript.
+   It has no Python equivalent (but we map it to an explicit Null
+   instance in runp3d.py). */
+typedef P3D_object *
+P3D_new_null_object_func();
+
 /* Allocates a new P3D_object of type none.  This value has no
    particular value and corresponds to Python's None type or C's void
    type. */
@@ -594,6 +602,7 @@ typedef struct {
 typedef enum {
   P3D_SO_get_property,
   P3D_SO_set_property,
+  P3D_SO_del_property,
   P3D_SO_call,
 } P3D_script_operation;
 typedef struct {
@@ -729,6 +738,7 @@ EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish;
 EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window;
 
 EXPCL_P3D_PLUGIN P3D_make_class_definition_func P3D_make_class_definition;
+EXPCL_P3D_PLUGIN P3D_new_null_object_func P3D_new_null_object;
 EXPCL_P3D_PLUGIN P3D_new_none_object_func P3D_new_none_object;
 EXPCL_P3D_PLUGIN P3D_new_bool_object_func P3D_new_bool_object;
 EXPCL_P3D_PLUGIN P3D_new_int_object_func P3D_new_int_object;

+ 1 - 0
direct/src/plugin/p3d_plugin_composite1.cxx

@@ -11,6 +11,7 @@
 #include "p3dMultifileReader.cxx"
 #include "p3dPythonObject.cxx"
 #include "p3dNoneObject.cxx"
+#include "p3dNullObject.cxx"
 #include "p3dObject.cxx"
 #include "p3dPackage.cxx"
 #include "p3dSession.cxx"