diff --git a/direct/src/plugin/p3dBoolVariant.cxx b/direct/src/plugin/p3dBoolVariant.cxx index 6672d7eeab..0217e2b7a0 100755 --- a/direct/src/plugin/p3dBoolVariant.cxx +++ b/direct/src/plugin/p3dBoolVariant.cxx @@ -79,9 +79,22 @@ get_int() const { void P3DBoolVariant:: make_string(string &value) const { if (_value) { - value = "1"; + value = "True"; } else { - value = "0"; + value = "False"; } } +//////////////////////////////////////////////////////////////////// +// Function: P3DBoolVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DBoolVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "bool"); + xvariant->SetAttribute("value", (int)_value); + return xvariant; +} diff --git a/direct/src/plugin/p3dBoolVariant.h b/direct/src/plugin/p3dBoolVariant.h index 318c97055f..cb7eaf8fee 100755 --- a/direct/src/plugin/p3dBoolVariant.h +++ b/direct/src/plugin/p3dBoolVariant.h @@ -33,6 +33,8 @@ public: virtual int get_int() const; virtual void make_string(string &value) const; + virtual TiXmlElement *make_xml() const; + private: bool _value; }; diff --git a/direct/src/plugin/p3dCInstance.cxx b/direct/src/plugin/p3dCInstance.cxx index 9fd9ebbd24..70f6d458ec 100755 --- a/direct/src/plugin/p3dCInstance.cxx +++ b/direct/src/plugin/p3dCInstance.cxx @@ -24,7 +24,7 @@ P3DCInstance:: P3DCInstance(TiXmlElement *xinstance) : _func(NULL) { - xinstance->Attribute("id", &_instance_id); + xinstance->Attribute("instance_id", &_instance_id); } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dFloatVariant.cxx b/direct/src/plugin/p3dFloatVariant.cxx index 163b03a91b..d6b106c0cf 100755 --- a/direct/src/plugin/p3dFloatVariant.cxx +++ b/direct/src/plugin/p3dFloatVariant.cxx @@ -94,3 +94,17 @@ make_string(string &value) const { value = strm.str(); } + +//////////////////////////////////////////////////////////////////// +// Function: P3DFloatVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DFloatVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "float"); + xvariant->SetDoubleAttribute("value", _value); + return xvariant; +} diff --git a/direct/src/plugin/p3dFloatVariant.h b/direct/src/plugin/p3dFloatVariant.h index 37411d3301..2abd46e004 100755 --- a/direct/src/plugin/p3dFloatVariant.h +++ b/direct/src/plugin/p3dFloatVariant.h @@ -34,6 +34,8 @@ public: virtual double get_float() const; virtual void make_string(string &value) const; + virtual TiXmlElement *make_xml() const; + private: double _value; }; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index e226471add..0ed3537243 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -144,10 +144,10 @@ set_wparams(const P3DWindowParams &wparams) { // Update the instance in the sub-process. if (_session != NULL) { TiXmlDocument *doc = new TiXmlDocument; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", ""); + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xcommand = new TiXmlElement("command"); xcommand->SetAttribute("cmd", "setup_window"); - xcommand->SetAttribute("id", get_instance_id()); + xcommand->SetAttribute("instance_id", get_instance_id()); TiXmlElement *xwparams = _wparams.make_xml(); doc->LinkEndChild(decl); @@ -354,6 +354,24 @@ feed_url_stream(int unique_id, //////////////////////////////////////////////////////////////////// void P3DInstance:: feed_value(int unique_id, P3DVariant *variant) { + if (_session != NULL) { + TiXmlDocument *doc = new TiXmlDocument; + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement *xcommand = new TiXmlElement("command"); + xcommand->SetAttribute("cmd", "feed_value"); + xcommand->SetAttribute("instance_id", get_instance_id()); + xcommand->SetAttribute("unique_id", unique_id); + if (variant != NULL) { + TiXmlElement *xvariant = variant->make_xml(); + xcommand->LinkEndChild(xvariant); + } + + doc->LinkEndChild(decl); + doc->LinkEndChild(xcommand); + + _session->send_command(doc); + } + if (variant != NULL) { delete variant; } @@ -435,7 +453,7 @@ make_xml() { assert(_got_fparams); TiXmlElement *xinstance = new TiXmlElement("instance"); - xinstance->SetAttribute("id", _instance_id); + xinstance->SetAttribute("instance_id", _instance_id); TiXmlElement *xfparams = _fparams.make_xml(); xinstance->LinkEndChild(xfparams); diff --git a/direct/src/plugin/p3dIntVariant.cxx b/direct/src/plugin/p3dIntVariant.cxx index 2fcb89b330..ad5231cd6d 100755 --- a/direct/src/plugin/p3dIntVariant.cxx +++ b/direct/src/plugin/p3dIntVariant.cxx @@ -83,3 +83,17 @@ make_string(string &value) const { value = strm.str(); } + +//////////////////////////////////////////////////////////////////// +// Function: P3DIntVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DIntVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "int"); + xvariant->SetAttribute("value", _value); + return xvariant; +} diff --git a/direct/src/plugin/p3dIntVariant.h b/direct/src/plugin/p3dIntVariant.h index cee6e54936..6598f82cfd 100755 --- a/direct/src/plugin/p3dIntVariant.h +++ b/direct/src/plugin/p3dIntVariant.h @@ -33,6 +33,8 @@ public: virtual int get_int() const; virtual void make_string(string &value) const; + virtual TiXmlElement *make_xml() const; + private: int _value; }; diff --git a/direct/src/plugin/p3dListVariant.cxx b/direct/src/plugin/p3dListVariant.cxx index 40e4c2a2c6..565a930206 100755 --- a/direct/src/plugin/p3dListVariant.cxx +++ b/direct/src/plugin/p3dListVariant.cxx @@ -14,10 +14,22 @@ #include "p3dListVariant.h" + +//////////////////////////////////////////////////////////////////// +// Function: P3DListVariant::Default Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +P3DListVariant:: +P3DListVariant() : P3DVariant(P3D_VT_list) { +} + //////////////////////////////////////////////////////////////////// // Function: P3DListVariant::Constructor // Access: Public -// Description: +// Description: Note that the ownership of the elements in the array +// (but not the array itself) is transferred to the +// list. //////////////////////////////////////////////////////////////////// P3DListVariant:: P3DListVariant(P3DVariant * const elements[], int num_elements) : @@ -90,12 +102,9 @@ make_string(string &value) const { ostringstream strm; strm << "["; if (!_elements.empty()) { - string es; - _elements[0]->make_string(es); - strm << es; + strm << *_elements[0]; for (size_t i = 1; i < _elements.size(); ++i) { - _elements[0]->make_string(es); - strm << ", " << es; + strm << ", " << *_elements[i]; } } strm << "]"; @@ -128,3 +137,33 @@ get_list_item(int n) const { return NULL; } + +//////////////////////////////////////////////////////////////////// +// Function: P3DListVariant::append_item +// Access: Public, Virtual +// Description: Appends a new item to the end of the list. Ownership +// of the item is transferred to the list. +//////////////////////////////////////////////////////////////////// +void P3DListVariant:: +append_item(P3DVariant *item) { + _elements.push_back(item); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DListVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DListVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "list"); + Elements::const_iterator ei; + for (ei = _elements.begin(); ei != _elements.end(); ++ei) { + TiXmlElement *xchild = (*ei)->make_xml(); + xvariant->LinkEndChild(xchild); + } + + return xvariant; +} diff --git a/direct/src/plugin/p3dListVariant.h b/direct/src/plugin/p3dListVariant.h index 3cc732443b..ff44af0436 100755 --- a/direct/src/plugin/p3dListVariant.h +++ b/direct/src/plugin/p3dListVariant.h @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////// class P3DListVariant : public P3DVariant { public: + P3DListVariant(); P3DListVariant(P3DVariant * const elements[], int num_elements); P3DListVariant(const P3DListVariant ©); @@ -36,6 +37,10 @@ public: virtual int get_list_length() const; virtual P3DVariant *get_list_item(int n) const; + void append_item(P3DVariant *item); + + virtual TiXmlElement *make_xml() const; + private: typedef vector Elements; Elements _elements; diff --git a/direct/src/plugin/p3dNoneVariant.cxx b/direct/src/plugin/p3dNoneVariant.cxx index b07161d014..4fdc33807f 100755 --- a/direct/src/plugin/p3dNoneVariant.cxx +++ b/direct/src/plugin/p3dNoneVariant.cxx @@ -54,3 +54,16 @@ void P3DNoneVariant:: make_string(string &value) const { value = "None"; } + +//////////////////////////////////////////////////////////////////// +// Function: P3DNoneVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DNoneVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "none"); + return xvariant; +} diff --git a/direct/src/plugin/p3dNoneVariant.h b/direct/src/plugin/p3dNoneVariant.h index 0d8d4d15f7..b6d11aef2e 100755 --- a/direct/src/plugin/p3dNoneVariant.h +++ b/direct/src/plugin/p3dNoneVariant.h @@ -31,6 +31,8 @@ public: virtual P3DVariant *make_copy(); virtual bool get_bool() const; virtual void make_string(string &value) const; + + virtual TiXmlElement *make_xml() const; }; #endif diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 44470080e3..e81c7b13d7 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -200,20 +200,26 @@ handle_command(TiXmlDocument *doc) { P3DCInstance *inst = new P3DCInstance(xinstance); start_instance(inst, xinstance); } + } else if (strcmp(cmd, "terminate_instance") == 0) { int id; - if (xcommand->Attribute("id", &id)) { + if (xcommand->Attribute("instance_id", &id)) { terminate_instance(id); } + } else if (strcmp(cmd, "setup_window") == 0) { int id; TiXmlElement *xwparams = xcommand->FirstChildElement("wparams"); if (xwparams != (TiXmlElement *)NULL && - xcommand->Attribute("id", &id)) { + xcommand->Attribute("instance_id", &id)) { setup_window(id, xwparams); } + } else if (strcmp(cmd, "exit") == 0) { terminate_session(); + + } else if (strcmp(cmd, "feed_value") == 0) { + } else { nout << "Unhandled command " << cmd << "\n"; @@ -284,10 +290,12 @@ py_request_func(PyObject *args) { } TiXmlDocument doc; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", ""); + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xrequest = new TiXmlElement("request"); - xrequest->SetAttribute("id", instance_id); + xrequest->SetAttribute("instance_id", instance_id); xrequest->SetAttribute("rtype", request_type); + doc.LinkEndChild(decl); + doc.LinkEndChild(xrequest); if (strcmp(request_type, "notify") == 0) { // A general notification to be sent directly to the instance. @@ -297,8 +305,47 @@ py_request_func(PyObject *args) { } xrequest->SetAttribute("message", message); - doc.LinkEndChild(decl); - doc.LinkEndChild(xrequest); + nout << "sending " << doc << "\n" << flush; + _pipe_write << doc << flush; + + } else if (strcmp(request_type, "get_property") == 0) { + // A get-property request. + const char *property_name; + int unique_id; + if (!PyArg_ParseTuple(extra_args, "si", &property_name, &unique_id)) { + return NULL; + } + + xrequest->SetAttribute("property_name", property_name); + xrequest->SetAttribute("unique_id", unique_id); + nout << "sending " << doc << "\n" << flush; + _pipe_write << doc << flush; + + } else if (strcmp(request_type, "set_property") == 0) { + // A set-property request. + const char *property_name; + PyObject *value; + if (!PyArg_ParseTuple(extra_args, "sO", &property_name, &value)) { + return NULL; + } + + xrequest->SetAttribute("property_name", property_name); + append_xml_variant(xrequest, value); + nout << "sending " << doc << "\n" << flush; + _pipe_write << doc << flush; + + } else if (strcmp(request_type, "call") == 0) { + // A call-method request. + const char *property_name; + PyObject *params; + int unique_id; + if (!PyArg_ParseTuple(extra_args, "sOi", &property_name, ¶ms, &unique_id)) { + return NULL; + } + + xrequest->SetAttribute("property_name", property_name); + xrequest->SetAttribute("unique_id", unique_id); + append_xml_variant(xrequest, params); nout << "sending " << doc << "\n" << flush; _pipe_write << doc << flush; @@ -549,6 +596,103 @@ terminate_session() { nout << "done calling stop()\n"; } +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonRun::append_xml_variant +// Access: Private +// Description: Converts the indicated PyObject to the appropriate +// XML representation of a P3D_variant type, and appends +// it to the child list of the indicated element. +//////////////////////////////////////////////////////////////////// +void P3DPythonRun:: +append_xml_variant(TiXmlElement *xelement, PyObject *value) { + TiXmlElement *xvariant = new TiXmlElement("variant"); + if (value == Py_None) { + // None. + xvariant->SetAttribute("type", "none"); + + } else if (PyBool_Check(value)) { + // A bool value. + xvariant->SetAttribute("type", "bool"); + xvariant->SetAttribute("value", PyObject_IsTrue(value)); + + } else if (PyInt_Check(value)) { + // A plain integer value. + xvariant->SetAttribute("type", "int"); + xvariant->SetAttribute("value", PyInt_AsLong(value)); + + } else if (PyLong_Check(value)) { + // A long integer value. This gets converted either as an integer + // or as a floating-point type, whichever fits. + long lvalue = PyLong_AsLong(value); + if (PyErr_Occurred()) { + // It won't fit as an integer; make it a double. + PyErr_Clear(); + xvariant->SetAttribute("type", "float"); + xvariant->SetDoubleAttribute("value", PyLong_AsDouble(value)); + } else { + // It fits as an integer. + xvariant->SetAttribute("type", "int"); + xvariant->SetAttribute("value", lvalue); + } + + } else if (PyFloat_Check(value)) { + // A floating-point value. + xvariant->SetAttribute("type", "float"); + xvariant->SetDoubleAttribute("value", PyFloat_AsDouble(value)); + + } else if (PyUnicode_Check(value)) { + // A unicode value. Convert to utf-8 for the XML encoding. + xvariant->SetAttribute("type", "string"); + PyObject *as_str = PyUnicode_AsUTF8String(value); + if (as_str != NULL) { + char *buffer; + Py_ssize_t length; + if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) { + string str(buffer, length); + xvariant->SetAttribute("value", str); + } + Py_DECREF(as_str); + } + + } else if (PyString_Check(value)) { + // A string value. + xvariant->SetAttribute("type", "string"); + + char *buffer; + Py_ssize_t length; + if (PyString_AsStringAndSize(value, &buffer, &length) != -1) { + string str(buffer, length); + xvariant->SetAttribute("value", str); + } + + } else if (PySequence_Check(value)) { + // A sequence or list value. + xvariant->SetAttribute("type", "list"); + Py_ssize_t length = PySequence_Length(value); + for (Py_ssize_t i = 0; i < length; ++i) { + PyObject *obj = PySequence_GetItem(value, i); + append_xml_variant(xvariant, obj); + } + + } else { + // Some other kind of object. Don't know what else to do with it; + // we'll make it a string. + xvariant->SetAttribute("type", "string"); + PyObject *as_str = PyObject_Str(value); + if (as_str != NULL) { + char *buffer; + Py_ssize_t length; + if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) { + string str(buffer, length); + xvariant->SetAttribute("value", str); + } + Py_DECREF(as_str); + } + } + + xelement->LinkEndChild(xvariant); +} + //////////////////////////////////////////////////////////////////// // Function: P3DPythonRun::rt_thread_run // Access: Private diff --git a/direct/src/plugin/p3dPythonRun.h b/direct/src/plugin/p3dPythonRun.h index 4a4b4472f2..b980b29468 100755 --- a/direct/src/plugin/p3dPythonRun.h +++ b/direct/src/plugin/p3dPythonRun.h @@ -80,6 +80,9 @@ private: void terminate_session(); +private: + void append_xml_variant(TiXmlElement *xelement, PyObject *value); + private: // This method runs only within the read thread. diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index 6e6166f3b4..8e672022f8 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -69,7 +69,7 @@ P3DSession:: if (_p3dpython_running) { // Tell the process we're going away. TiXmlDocument doc; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", ""); + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xcommand = new TiXmlElement("command"); xcommand->SetAttribute("cmd", "exit"); doc.LinkEndChild(decl); @@ -136,7 +136,7 @@ start_instance(P3DInstance *inst) { assert(inserted); TiXmlDocument *doc = new TiXmlDocument; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", ""); + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xcommand = new TiXmlElement("command"); xcommand->SetAttribute("cmd", "start_instance"); TiXmlElement *xinstance = inst->make_xml(); @@ -169,10 +169,10 @@ start_instance(P3DInstance *inst) { void P3DSession:: terminate_instance(P3DInstance *inst) { TiXmlDocument *doc = new TiXmlDocument; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", ""); + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); TiXmlElement *xcommand = new TiXmlElement("command"); xcommand->SetAttribute("cmd", "terminate_instance"); - xcommand->SetAttribute("id", inst->get_instance_id()); + xcommand->SetAttribute("instance_id", inst->get_instance_id()); doc->LinkEndChild(decl); doc->LinkEndChild(xcommand); @@ -412,7 +412,7 @@ rt_handle_request(TiXmlDocument *doc) { TiXmlElement *xrequest = doc->FirstChildElement("request"); if (xrequest != (TiXmlElement *)NULL) { int instance_id ; - if (xrequest->Attribute("id", &instance_id)) { + if (xrequest->Attribute("instance_id", &instance_id)) { // Look up the particular instance this is related to. ACQUIRE_LOCK(_instances_lock); Instances::const_iterator ii; @@ -449,12 +449,102 @@ rt_make_p3d_request(TiXmlElement *xrequest) { request->_request_type = P3D_RT_notify; request->_request._notify._message = strdup(message); } + + } else if (strcmp(rtype, "get_property") == 0) { + const char *property_name = xrequest->Attribute("property_name"); + int unique_id; + if (property_name != NULL && xrequest->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) { + request = new P3D_request; + request->_request_type = P3D_RT_get_property; + request->_request._get_property._property_name = strdup(property_name); + request->_request._get_property._unique_id = unique_id; + } + + } else if (strcmp(rtype, "set_property") == 0) { + const char *property_name = xrequest->Attribute("property_name"); + TiXmlElement *xvariant = xrequest->FirstChildElement("variant"); + if (property_name != NULL && xvariant != NULL) { + request = new P3D_request; + request->_request_type = P3D_RT_set_property; + request->_request._set_property._property_name = strdup(property_name); + request->_request._set_property._value = rt_from_xml_variant(xvariant); + } + + } else if (strcmp(rtype, "call") == 0) { + const char *property_name = xrequest->Attribute("property_name"); + TiXmlElement *xvariant = xrequest->FirstChildElement("variant"); + int unique_id; + if (property_name != NULL && xvariant != NULL && + xrequest->QueryIntAttribute("unique_id", &unique_id) == TIXML_SUCCESS) { + request = new P3D_request; + request->_request_type = P3D_RT_call; + request->_request._call._property_name = strdup(property_name); + request->_request._call._params = rt_from_xml_variant(xvariant); + request->_request._call._unique_id = unique_id; + } + + } else { + nout << "ignoring request of type " << rtype << "\n"; } } return request; } +//////////////////////////////////////////////////////////////////// +// Function: P3DSession::rt_from_xml_variant +// Access: Private +// Description: Converts the XML representation of the particular +// variant value into a corresponding P3DVariant object. +// Returns the newly-allocated object. +//////////////////////////////////////////////////////////////////// +P3DVariant *P3DSession:: +rt_from_xml_variant(TiXmlElement *xvariant) { + const char *type = xvariant->Attribute("type"); + if (strcmp(type, "none") == 0) { + return new P3DNoneVariant; + + } else if (strcmp(type, "bool") == 0) { + int value; + if (xvariant->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DBoolVariant(value != 0); + } + + } else if (strcmp(type, "int") == 0) { + int value; + if (xvariant->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DIntVariant(value); + } + + } else if (strcmp(type, "float") == 0) { + double value; + if (xvariant->QueryDoubleAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DFloatVariant(value); + } + + } else if (strcmp(type, "string") == 0) { + // Using the string form here instead of the char * form, so we + // don't get tripped up on embedded null characters. + const string *value = xvariant->Attribute(string("value")); + if (value != NULL) { + return new P3DStringVariant(*value); + } + + } else if (strcmp(type, "list") == 0) { + P3DListVariant *list = new P3DListVariant; + + TiXmlElement *xchild = xvariant->FirstChildElement("variant"); + while (xchild != NULL) { + list->append_item(rt_from_xml_variant(xchild)); + xchild = xchild->NextSiblingElement("variant"); + } + return list; + } + + // Something went wrong in decoding. + return new P3DNoneVariant; +} + //////////////////////////////////////////////////////////////////// // Function: P3DSession::rt_terminate // Access: Private diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index abbc3c833c..50bfe0dbe4 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -61,6 +61,7 @@ private: void rt_terminate(); void rt_handle_request(TiXmlDocument *doc); P3D_request *rt_make_p3d_request(TiXmlElement *xrequest); + P3DVariant *rt_from_xml_variant(TiXmlElement *xvariant); #ifdef _WIN32 static DWORD WINAPI win_rt_thread_run(LPVOID data); diff --git a/direct/src/plugin/p3dStringVariant.cxx b/direct/src/plugin/p3dStringVariant.cxx index c38d000de3..56acc47d57 100755 --- a/direct/src/plugin/p3dStringVariant.cxx +++ b/direct/src/plugin/p3dStringVariant.cxx @@ -20,9 +20,9 @@ // Description: //////////////////////////////////////////////////////////////////// P3DStringVariant:: -P3DStringVariant(const char *value, int length) : +P3DStringVariant(const string &value) : P3DVariant(P3D_VT_string), - _value(value, length) + _value(value) { } @@ -79,3 +79,58 @@ make_string(string &value) const { value = _value; } +//////////////////////////////////////////////////////////////////// +// Function: P3DStringVariant::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this variant. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DStringVariant:: +make_xml() const { + TiXmlElement *xvariant = new TiXmlElement("variant"); + xvariant->SetAttribute("type", "string"); + xvariant->SetAttribute("value", _value); + return xvariant; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DStringVariant::output +// Access: Public, Virtual +// Description: Writes a formatted representation of the value to the +// indicated string. This is intended for developer +// assistance. +//////////////////////////////////////////////////////////////////// +void P3DStringVariant:: +output(ostream &out) const { + out << '"'; + for (string::const_iterator si = _value.begin(); si != _value.end(); ++si) { + if (isprint(*si)) { + switch (*si) { + case '"': + out << "\\\x22"; + break; + + default: + out << *si; + } + } else { + switch (*si) { + case '\n': + out << "\\n"; + break; + + case '\t': + out << "\\t"; + break; + + default: + { + char buffer[128]; + sprintf(buffer, "%02x", (unsigned char)(*si)); + out << "\\x" << buffer; + } + } + } + } + out << '"'; +} diff --git a/direct/src/plugin/p3dStringVariant.h b/direct/src/plugin/p3dStringVariant.h index f6474aed24..25e201ccc9 100755 --- a/direct/src/plugin/p3dStringVariant.h +++ b/direct/src/plugin/p3dStringVariant.h @@ -24,7 +24,7 @@ //////////////////////////////////////////////////////////////////// class P3DStringVariant : public P3DVariant { public: - P3DStringVariant(const char *value, int length); + P3DStringVariant(const string &value); P3DStringVariant(const P3DStringVariant ©); public: @@ -34,6 +34,10 @@ public: virtual bool get_bool() const; virtual void make_string(string &value) const; + virtual TiXmlElement *make_xml() const; + + virtual void output(ostream &out) const; + private: string _value; }; diff --git a/direct/src/plugin/p3dVariant.cxx b/direct/src/plugin/p3dVariant.cxx index 5e31bc096d..d9388ed565 100755 --- a/direct/src/plugin/p3dVariant.cxx +++ b/direct/src/plugin/p3dVariant.cxx @@ -100,3 +100,17 @@ P3DVariant *P3DVariant:: get_list_item(int n) const { return NULL; } + +//////////////////////////////////////////////////////////////////// +// Function: P3DVariant::output +// Access: Public, Virtual +// Description: Writes a formatted representation of the value to the +// indicated string. This is intended for developer +// assistance. +//////////////////////////////////////////////////////////////////// +void P3DVariant:: +output(ostream &out) const { + string value; + make_string(value); + out << value; +} diff --git a/direct/src/plugin/p3dVariant.h b/direct/src/plugin/p3dVariant.h index c22a5c36b0..49940c8e0a 100755 --- a/direct/src/plugin/p3dVariant.h +++ b/direct/src/plugin/p3dVariant.h @@ -44,9 +44,18 @@ public: virtual int get_list_length() const; virtual P3DVariant *get_list_item(int n) const; + + virtual TiXmlElement *make_xml() const=0; + + virtual void output(ostream &out) const; }; #include "p3dVariant.I" +inline ostream &operator << (ostream &out, const P3DVariant &variant) { + variant.output(out); + return out; +} + #endif diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index fa3277350b..f8f631cb1a 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -120,7 +120,9 @@ void P3D_variant_finish(P3D_variant *variant) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_lock); - delete (P3DVariant *)variant; + if (variant != NULL) { + delete (P3DVariant *)variant; + } RELEASE_LOCK(_lock); } @@ -200,7 +202,7 @@ P3D_variant * P3D_new_string_variant(const char *value, int length) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_lock); - P3D_variant *result = new P3DStringVariant(value, length); + P3D_variant *result = new P3DStringVariant(string(value, length)); RELEASE_LOCK(_lock); return result; } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 06a7451144..8202ed974e 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -302,30 +302,102 @@ handle_request(P3D_request *request) { break; case P3D_RT_get_url: - cerr << "Got P3D_RT_get_url\n"; + cerr << "Got P3D_RT_get_url: " << request->_request._get_url._url + << "\n"; { URLGetter *getter = new URLGetter (request->_instance, request->_request._get_url._unique_id, URLSpec(request->_request._get_url._url), ""); _url_getters.insert(getter); + handled = true; } break; case P3D_RT_post_url: - cerr << "Got P3D_RT_post_url\n"; + cerr << "Got P3D_RT_post_url: " << request->_request._post_url._url + << "\n"; { URLGetter *getter = new URLGetter (request->_instance, request->_request._post_url._unique_id, URLSpec(request->_request._post_url._url), string(request->_request._post_url._post_data, request->_request._post_url._post_data_size)); _url_getters.insert(getter); + handled = true; } break; case P3D_RT_notify: + cerr << "Got P3D_RT_notify: " << request->_request._notify._message + << "\n"; // Ignore notifications. break; + case P3D_RT_get_property: + cerr << "Got P3D_RT_get_property: " + << request->_request._get_property._property_name << "\n"; + { + Properties::iterator pi = + _properties.find(request->_request._get_property._property_name); + if (pi != _properties.end()) { + // The named property has been set. + P3D_variant *dup_value = P3D_variant_copy((*pi).second); + P3D_instance_feed_value(request->_instance, + request->_request._get_property._unique_id, + dup_value); + } else { + // No such property set. + P3D_instance_feed_value(request->_instance, + request->_request._get_property._unique_id, + NULL); + } + handled = true; + } + break; + + case P3D_RT_set_property: + cerr << "Got P3D_RT_set_property: " + << request->_request._set_property._property_name << "\n"; + { + // Also output the new value. + int buffer_size = + P3D_variant_get_string_length(request->_request._set_property._value); + char *buffer = (char *)alloca(buffer_size); + P3D_variant_extract_string(request->_request._set_property._value, buffer, buffer_size); + cerr.write(buffer, buffer_size); + cerr << "\n"; + + Properties::iterator pi = + _properties.insert(Properties::value_type(request->_request._set_property._property_name, NULL)).first; + if ((*pi).second != NULL) { + // Delete the original property. + P3D_variant_finish((*pi).second); + } + (*pi).second = + P3D_variant_copy(request->_request._set_property._value); + handled = true; + } + break; + + case P3D_RT_call: + cerr << "Got P3D_RT_call: " + << request->_request._call._property_name << "\n"; + { + // Also output the parameter list. + int buffer_size = + P3D_variant_get_string_length(request->_request._call._params); + char *buffer = (char *)alloca(buffer_size); + P3D_variant_extract_string(request->_request._call._params, buffer, buffer_size); + cerr.write(buffer, buffer_size); + cerr << "\n"; + + // We don't have a mechanism for actually calling anything, though. + P3D_instance_feed_value(request->_instance, + request->_request._call._unique_id, + NULL); + handled = true; + } + break; + default: // Some request types are not handled. cerr << "Unhandled request: " << request->_request_type << "\n"; diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 1b9adc3766..5b5c1a304e 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -60,6 +60,11 @@ private: typedef pset Instances; Instances _instances; + // We maintain a table of properties in the "browser", mainly so we + // can test this feature of the core plugin API. + typedef pmap Properties; + Properties _properties; + // This nested class keeps track of active URL requests. class URLGetter { public: diff --git a/direct/src/showbase/AppRunnerGlobal.py b/direct/src/showbase/AppRunnerGlobal.py new file mode 100644 index 0000000000..9e4b083f25 --- /dev/null +++ b/direct/src/showbase/AppRunnerGlobal.py @@ -0,0 +1,9 @@ +""" This module serves as a placeholder for the global AppRunner +object, which only exists when we are running a .p3d file via +runp3d.py or via the Panda3D plugin or standalone executable. + +This is needed for apps that start themselves by importing +DirectStart; it provides a place for these apps to look for +the AppRunner at startup. """ + +appRunner = None diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 74a9cbb6ae..aa876f91f0 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -41,6 +41,7 @@ import SfxPlayer if __debug__: from direct.directutil import DeltaProfiler import OnScreenDebug +import AppRunnerGlobal __builtin__.FADE_SORT_INDEX = 1000 __builtin__.NO_FADE_SORT_INDEX = 2000 @@ -63,6 +64,9 @@ class ShowBase(DirectObject.DirectObject): self.mainDir = Filename.fromOsSpecific(maindir).getFullpath() ExecutionEnvironment.setEnvironmentVariable("MAIN_DIR", self.mainDir) + # The appRunner should have been created by the time ShowBase + # has been. + self.appRunner = AppRunnerGlobal.appRunner #debug running multiplier self.debugRunningMultiplier = 4 diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index 87ff680fe0..14d2eb138c 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -25,6 +25,7 @@ from direct.showbase.DirectObject import DirectObject from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, getModelPath, HTTPClient from direct.stdpy import file from direct.task.TaskManagerGlobal import taskMgr +from direct.showbase import AppRunnerGlobal import os import __builtin__ @@ -54,9 +55,13 @@ class AppRunner(DirectObject): # This is the default requestFunc that is installed if we # never call setRequestFunc(). def defaultRequestFunc(*args): - print "Ignoring request func: %s" % (args,) + print "Ignoring request: %s" % (args,) self.requestFunc = defaultRequestFunc + # Store our pointer so DirectStart-based apps can find us. + if AppRunnerGlobal.appRunner is None: + AppRunnerGlobal.appRunner = self + def initPackedAppEnvironment(self): """ This function sets up the Python environment suitably for running a packed app. It should only run once in any given