From 6f2591c642302e1dfbc4424aa46e3cd143b9e016 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 3 Jul 2009 20:27:50 +0000 Subject: [PATCH] P3DPythonObject et al --- direct/src/plugin/Sources.pp | 2 + direct/src/plugin/p3dBoolObject.cxx | 15 +- direct/src/plugin/p3dBoolObject.h | 2 +- direct/src/plugin/p3dFloatObject.cxx | 15 +- direct/src/plugin/p3dFloatObject.h | 2 +- direct/src/plugin/p3dInstance.cxx | 74 +++-- direct/src/plugin/p3dInstance.h | 6 +- direct/src/plugin/p3dIntObject.cxx | 15 +- direct/src/plugin/p3dIntObject.h | 2 +- direct/src/plugin/p3dListObject.cxx | 28 +- direct/src/plugin/p3dListObject.h | 3 + direct/src/plugin/p3dNoneObject.cxx | 12 +- direct/src/plugin/p3dNoneObject.h | 2 +- direct/src/plugin/p3dObject.I | 46 ++- direct/src/plugin/p3dObject.cxx | 52 ++-- direct/src/plugin/p3dObject.h | 17 +- direct/src/plugin/p3dPythonObject.cxx | 302 ++++++++++++++++++++ direct/src/plugin/p3dPythonObject.h | 63 ++++ direct/src/plugin/p3dPythonRun.cxx | 152 ++++++++-- direct/src/plugin/p3dPythonRun.h | 4 +- direct/src/plugin/p3dSession.cxx | 136 +++++---- direct/src/plugin/p3dSession.h | 2 +- direct/src/plugin/p3dStringObject.cxx | 15 +- direct/src/plugin/p3dStringObject.h | 2 +- direct/src/plugin/p3d_plugin.cxx | 3 +- direct/src/plugin/p3d_plugin.h | 29 +- direct/src/plugin/p3d_plugin_composite1.cxx | 1 + direct/src/plugin_standalone/panda3d.cxx | 22 ++ direct/src/showutil/runp3d.py | 9 + 29 files changed, 782 insertions(+), 251 deletions(-) create mode 100644 direct/src/plugin/p3dPythonObject.cxx create mode 100644 direct/src/plugin/p3dPythonObject.h diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index aec2419412..03bc7496cc 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -32,6 +32,7 @@ p3dListObject.h \ p3dMultifileReader.h p3dMultifileReader.I \ p3dPackage.h p3dPackage.I \ + p3dPythonObject.h \ p3dSession.h p3dSession.I \ p3dSplashWindow.h p3dSplashWindow.I \ p3dStringObject.h \ @@ -53,6 +54,7 @@ p3dListObject.cxx \ p3dMultifileReader.cxx \ p3dPackage.cxx \ + p3dPythonObject.cxx \ p3dSession.cxx \ p3dSplashWindow.cxx \ p3dStringObject.cxx \ diff --git a/direct/src/plugin/p3dBoolObject.cxx b/direct/src/plugin/p3dBoolObject.cxx index 9c6dbb6d3b..ebc40a5bb0 100644 --- a/direct/src/plugin/p3dBoolObject.cxx +++ b/direct/src/plugin/p3dBoolObject.cxx @@ -20,10 +20,7 @@ // Description: //////////////////////////////////////////////////////////////////// P3DBoolObject:: -P3DBoolObject(bool value) : - P3DObject(P3D_OT_bool), - _value(value) -{ +P3DBoolObject(bool value) : _value(value) { } //////////////////////////////////////////////////////////////////// @@ -39,13 +36,13 @@ P3DBoolObject(const P3DBoolObject ©) : } //////////////////////////////////////////////////////////////////// -// Function: P3DBoolObject::make_copy +// Function: P3DBoolObject::get_type // Access: Public, Virtual -// Description: +// Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// -P3DObject *P3DBoolObject:: -make_copy() const { - return new P3DBoolObject(*this); +P3D_object_type P3DBoolObject:: +get_type() const { + return P3D_OT_bool; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dBoolObject.h b/direct/src/plugin/p3dBoolObject.h index 0c332d6904..aae4980b0d 100644 --- a/direct/src/plugin/p3dBoolObject.h +++ b/direct/src/plugin/p3dBoolObject.h @@ -28,7 +28,7 @@ public: P3DBoolObject(const P3DBoolObject ©); public: - virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual int get_int() const; virtual void make_string(string &value) const; diff --git a/direct/src/plugin/p3dFloatObject.cxx b/direct/src/plugin/p3dFloatObject.cxx index f6c4e4d47e..5ff1f7eb82 100644 --- a/direct/src/plugin/p3dFloatObject.cxx +++ b/direct/src/plugin/p3dFloatObject.cxx @@ -20,10 +20,7 @@ // Description: //////////////////////////////////////////////////////////////////// P3DFloatObject:: -P3DFloatObject(double value) : - P3DObject(P3D_OT_float), - _value(value) -{ +P3DFloatObject(double value) : _value(value) { } //////////////////////////////////////////////////////////////////// @@ -39,13 +36,13 @@ P3DFloatObject(const P3DFloatObject ©) : } //////////////////////////////////////////////////////////////////// -// Function: P3DFloatObject::make_copy +// Function: P3DFloatObject::get_type // Access: Public, Virtual -// Description: +// Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// -P3DObject *P3DFloatObject:: -make_copy() const { - return new P3DFloatObject(*this); +P3D_object_type P3DFloatObject:: +get_type() const { + return P3D_OT_float; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dFloatObject.h b/direct/src/plugin/p3dFloatObject.h index a38716b4b9..5660f97a5e 100644 --- a/direct/src/plugin/p3dFloatObject.h +++ b/direct/src/plugin/p3dFloatObject.h @@ -28,7 +28,7 @@ public: P3DFloatObject(const P3DFloatObject ©); public: - virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual int get_int() const; virtual double get_float() const; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 65e7d34352..4bd11930ab 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -21,6 +21,7 @@ #include "p3dWinSplashWindow.h" #include "p3dObject.h" #include "p3dNoneObject.h" +#include "p3dPythonObject.h" #include #include @@ -159,54 +160,43 @@ set_wparams(const P3DWindowParams &wparams) { } //////////////////////////////////////////////////////////////////// -// Function: P3DInstance::get_property +// Function: P3DInstance::get_script_object // Access: Public -// Description: Returns the value of the named property, or NULL -// if there is no such property. Properties are created -// by the script run within the instance; they are used -// for communicating between scripting languages (for -// instance, communication between the Python-based -// Panda application, and the Javascript on the -// containing web page). +// Description: Returns a pointer to the top-level scriptable object +// of the instance, to be used by JavaScript code in the +// browser to control this program. //////////////////////////////////////////////////////////////////// P3DObject *P3DInstance:: -get_property(const string &property_name) const { - return NULL; -} +get_script_object() const { + assert(_session != NULL); -//////////////////////////////////////////////////////////////////// -// Function: P3DInstance::get_property_list -// Access: Public -// Description: Returns a list of subordinate properties below the -// named property. -//////////////////////////////////////////////////////////////////// -P3DObject *P3DInstance:: -get_property_list(const string &property_name) const { - return NULL; -} + TiXmlDocument *doc = new TiXmlDocument; + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement *xcommand = new TiXmlElement("command"); + xcommand->SetAttribute("cmd", "pyobj"); + xcommand->SetAttribute("op", "get_script_object"); + doc->LinkEndChild(decl); + doc->LinkEndChild(xcommand); + TiXmlDocument *response = _session->command_and_response(doc); + nout << "response pointer: " << response << "\n" << flush; -//////////////////////////////////////////////////////////////////// -// Function: P3DInstance::set_property -// Access: Public -// Description: Changes the value of the named property, or deletes -// it if value is NULL. If the named property does not -// already exist, creates it. Returns true on success, -// false on failure. -//////////////////////////////////////////////////////////////////// -bool P3DInstance:: -set_property(const string &property_name, const P3DObject *value) { - return false; -} + P3DObject *result = NULL; + if (response != NULL) { + TiXmlElement *xresponse = response->FirstChildElement("response"); + if (xresponse != NULL) { + TiXmlElement *xvalue = xresponse->FirstChildElement("value"); + if (xvalue != NULL) { + result = _session->xml_to_object(xvalue); + } + } + delete response; + } -//////////////////////////////////////////////////////////////////// -// Function: P3DInstance::call -// Access: Public -// Description: Calls the named property as a method, supplying the -// indicated parameters. -//////////////////////////////////////////////////////////////////// -P3DObject *P3DInstance:: -call(const string &property_name, const P3DObject *params) { - return new P3DNoneObject; + nout << "Returning " << result << "\n" << flush; + if (result != NULL) { + nout << "result = " << *result << "\n" << flush; + } + return result; } diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index fdf5e1bf14..aecd5068a4 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -46,11 +46,7 @@ public: void set_wparams(const P3DWindowParams &wparams); inline const P3DWindowParams &get_wparams() const; - P3DObject *get_property(const string &property_name) const; - P3DObject *get_property_list(const string &property_name) const; - bool set_property(const string &property_name, - const P3DObject *value); - P3DObject *call(const string &property_name, const P3DObject *params); + P3DObject *get_script_object() const; bool has_request(); P3D_request *get_request(); diff --git a/direct/src/plugin/p3dIntObject.cxx b/direct/src/plugin/p3dIntObject.cxx index dcbe1bfeda..b20b6f6a50 100644 --- a/direct/src/plugin/p3dIntObject.cxx +++ b/direct/src/plugin/p3dIntObject.cxx @@ -20,10 +20,7 @@ // Description: //////////////////////////////////////////////////////////////////// P3DIntObject:: -P3DIntObject(int value) : - P3DObject(P3D_OT_int), - _value(value) -{ +P3DIntObject(int value) : _value(value) { } //////////////////////////////////////////////////////////////////// @@ -39,13 +36,13 @@ P3DIntObject(const P3DIntObject ©) : } //////////////////////////////////////////////////////////////////// -// Function: P3DIntObject::make_copy +// Function: P3DIntObject::get_type // Access: Public, Virtual -// Description: +// Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// -P3DObject *P3DIntObject:: -make_copy() const { - return new P3DIntObject(*this); +P3D_object_type P3DIntObject:: +get_type() const { + return P3D_OT_int; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dIntObject.h b/direct/src/plugin/p3dIntObject.h index a9151584db..37b6a52ead 100644 --- a/direct/src/plugin/p3dIntObject.h +++ b/direct/src/plugin/p3dIntObject.h @@ -28,7 +28,7 @@ public: P3DIntObject(const P3DIntObject ©); public: - virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual int get_int() const; virtual void make_string(string &value) const; diff --git a/direct/src/plugin/p3dListObject.cxx b/direct/src/plugin/p3dListObject.cxx index 2aa595b360..4a654ff69b 100644 --- a/direct/src/plugin/p3dListObject.cxx +++ b/direct/src/plugin/p3dListObject.cxx @@ -21,7 +21,7 @@ // Description: //////////////////////////////////////////////////////////////////// P3DListObject:: -P3DListObject() : P3DObject(P3D_OT_list) { +P3DListObject() { } //////////////////////////////////////////////////////////////////// @@ -56,13 +56,26 @@ P3DListObject:: //////////////////////////////////////////////////////////////////// // Function: P3DListObject::make_copy // Access: Public, Virtual -// Description: +// Description: Returns a new copy of the object, if necessary. If +// the object type is static and all instances are +// identical, this actually simply ups the reference +// count and returns the same object. //////////////////////////////////////////////////////////////////// P3DObject *P3DListObject:: make_copy() const { return new P3DListObject(*this); } +//////////////////////////////////////////////////////////////////// +// Function: P3DListObject::get_type +// Access: Public, Virtual +// Description: Returns the fundamental type of this kind of object. +//////////////////////////////////////////////////////////////////// +P3D_object_type P3DListObject:: +get_type() const { + return P3D_OT_list; +} + //////////////////////////////////////////////////////////////////// // Function: P3DListObject::get_bool // Access: Public, Virtual @@ -153,6 +166,17 @@ set_element(int n, P3D_object *value) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: P3DListObject::append +// Access: Public, Virtual +// Description: Adds a new element to the end of the list. Ownership +// is transferred to the list. +//////////////////////////////////////////////////////////////////// +void P3DListObject:: +append(P3D_object *value) { + _elements.push_back(value); +} + //////////////////////////////////////////////////////////////////// // Function: P3DListObject::make_xml // Access: Public, Virtual diff --git a/direct/src/plugin/p3dListObject.h b/direct/src/plugin/p3dListObject.h index 5ef0825739..e52f5c7a95 100644 --- a/direct/src/plugin/p3dListObject.h +++ b/direct/src/plugin/p3dListObject.h @@ -31,12 +31,15 @@ public: virtual ~P3DListObject(); virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual void make_string(string &value) const; virtual int get_list_length() const; virtual P3D_object *get_element(int n) const; virtual bool set_element(int n, P3D_object *value); + void append(P3D_object *value); + virtual TiXmlElement *make_xml() const; private: diff --git a/direct/src/plugin/p3dNoneObject.cxx b/direct/src/plugin/p3dNoneObject.cxx index 3fa91a70d6..56340d0418 100644 --- a/direct/src/plugin/p3dNoneObject.cxx +++ b/direct/src/plugin/p3dNoneObject.cxx @@ -20,17 +20,17 @@ // Description: //////////////////////////////////////////////////////////////////// P3DNoneObject:: -P3DNoneObject() : P3DObject(P3D_OT_none) { +P3DNoneObject() { } //////////////////////////////////////////////////////////////////// -// Function: P3DNoneObject::make_copy +// Function: P3DNoneObject::get_type // Access: Public, Virtual -// Description: +// Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// -P3DObject *P3DNoneObject:: -make_copy() const { - return new P3DNoneObject(*this); +P3D_object_type P3DNoneObject:: +get_type() const { + return P3D_OT_none; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dNoneObject.h b/direct/src/plugin/p3dNoneObject.h index 0c9d3a02bb..9f08662f53 100644 --- a/direct/src/plugin/p3dNoneObject.h +++ b/direct/src/plugin/p3dNoneObject.h @@ -28,7 +28,7 @@ public: P3DNoneObject(); public: - virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual void make_string(string &value) const; diff --git a/direct/src/plugin/p3dObject.I b/direct/src/plugin/p3dObject.I index d531b8fa3e..6e6ec72a74 100644 --- a/direct/src/plugin/p3dObject.I +++ b/direct/src/plugin/p3dObject.I @@ -19,9 +19,11 @@ // Description: //////////////////////////////////////////////////////////////////// inline P3DObject:: -P3DObject(P3D_object_type type) { +P3DObject() { _class = &_object_class; - _type = type; + + // The reference count is initially 1. + _ref_count = 1; } //////////////////////////////////////////////////////////////////// @@ -31,15 +33,43 @@ P3DObject(P3D_object_type type) { //////////////////////////////////////////////////////////////////// inline P3DObject:: P3DObject(const P3DObject ©) { - _type = copy._type; + assert(copy._class == &_object_class); + _class = copy._class; + _ref_count = 1; } //////////////////////////////////////////////////////////////////// -// Function: P3DObject::get_type +// Function: P3DObject::ref // Access: Public -// Description: Returns the fundamental type of this kind of object. +// Description: Increments the reference count. //////////////////////////////////////////////////////////////////// -inline P3D_object_type P3DObject:: -get_type() const { - return _type; +inline void P3DObject:: +ref() const { + ++(((P3DObject *)this)->_ref_count); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::unref +// Access: Public +// Description: Decrements the reference count, and returns the new +// count. +//////////////////////////////////////////////////////////////////// +inline int P3DObject:: +unref() const { + --(((P3DObject *)this)->_ref_count); + return _ref_count; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::unref_delete +// Access: Public, Static +// Description: Decrements the reference count on the indicated +// object, and deletes it if the reference count reaches +// zero. +//////////////////////////////////////////////////////////////////// +inline void P3DObject:: +unref_delete(P3DObject *obj) { + if (obj->unref() <= 0) { + delete obj; + } } diff --git a/direct/src/plugin/p3dObject.cxx b/direct/src/plugin/p3dObject.cxx index 6d0bb792de..3cafb53647 100644 --- a/direct/src/plugin/p3dObject.cxx +++ b/direct/src/plugin/p3dObject.cxx @@ -21,7 +21,7 @@ // P3D_object structure. static void object_finish(P3D_object *object) { - delete ((P3DObject *)object); + P3DObject::unref_delete(((P3DObject *)object)); } static P3D_object * @@ -85,13 +85,12 @@ static int object_get_list_length(const P3D_object *object) { } static P3D_object * -object_call(const P3D_object *object, P3D_object *params) { - return ((const P3DObject *)object)->call(params); -} - -static P3D_object * -object_evaluate(const P3D_object *object, const char *expression) { - return ((const P3DObject *)object)->evaluate(expression); +object_call(const P3D_object *object, const char *method_name, + P3D_object *params) { + if (method_name == NULL) { + method_name = ""; + } + return ((const P3DObject *)object)->call(method_name, params); } P3D_class_definition P3DObject::_object_class = { @@ -109,7 +108,6 @@ P3D_class_definition P3DObject::_object_class = { &object_set_element, &object_get_list_length, &object_call, - &object_evaluate, }; //////////////////////////////////////////////////////////////////// @@ -119,7 +117,20 @@ P3D_class_definition P3DObject::_object_class = { //////////////////////////////////////////////////////////////////// P3DObject:: ~P3DObject() { - _type = P3D_OT_none; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::make_copy +// Access: Public, Virtual +// Description: Returns a new copy of the object, if necessary. If +// the object type is static and all instances are +// identical, this actually simply ups the reference +// count and returns the same object. +//////////////////////////////////////////////////////////////////// +P3DObject *P3DObject:: +make_copy() const { + ref(); + return (P3DObject *)this; } //////////////////////////////////////////////////////////////////// @@ -244,30 +255,19 @@ set_element(int n, P3D_object *value) { //////////////////////////////////////////////////////////////////// // Function: P3DObject::call // Access: Public, Virtual -// Description: Invokes the object as a method, passing the indicated -// parameters. Returns the return value on success, -// NULL on error. +// Description: Invokes the named method on the object, passing the +// indicated parameters. If the method name is empty, +// invokes the object itself. Returns the return value +// on success, NULL on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DObject:: -call(P3D_object *params) const { +call(const string &method_name, P3D_object *params) const { if (params != NULL) { P3D_OBJECT_FINISH(params); } return NULL; } -//////////////////////////////////////////////////////////////////// -// Function: P3DObject::evaluate -// Access: Public, Virtual -// Description: Evaluates an arbitrary script expression within the -// context of this object. Returns the return value on -// success, NULL on error. -//////////////////////////////////////////////////////////////////// -P3D_object *P3DObject:: -evaluate(const string &expression) const { - return NULL; -} - //////////////////////////////////////////////////////////////////// // Function: P3DObject::output // Access: Public, Virtual diff --git a/direct/src/plugin/p3dObject.h b/direct/src/plugin/p3dObject.h index a7b252eb36..d5c82c8620 100644 --- a/direct/src/plugin/p3dObject.h +++ b/direct/src/plugin/p3dObject.h @@ -27,14 +27,14 @@ //////////////////////////////////////////////////////////////////// class P3DObject : public P3D_object { protected: - inline P3DObject(P3D_object_type type); + inline P3DObject(); inline P3DObject(const P3DObject ©); public: virtual ~P3DObject(); - virtual P3DObject *make_copy() const=0; - inline P3D_object_type get_type() const; + virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const=0; virtual bool get_bool() const=0; virtual int get_int() const; virtual double get_float() const; @@ -50,15 +50,18 @@ public: virtual P3D_object *get_element(int n) const; virtual bool set_element(int n, P3D_object *value); - virtual P3D_object *call(P3D_object *params) const; - virtual P3D_object *evaluate(const string &expression) const; + virtual P3D_object *call(const string &method_name, P3D_object *params) const; virtual TiXmlElement *make_xml() const=0; virtual void output(ostream &out) const; -protected: - P3D_object_type _type; + inline void ref() const; + inline int unref() const; + static inline void unref_delete(P3DObject *obj); + +private: + int _ref_count; public: static P3D_class_definition _object_class; diff --git a/direct/src/plugin/p3dPythonObject.cxx b/direct/src/plugin/p3dPythonObject.cxx new file mode 100644 index 0000000000..777bcf0008 --- /dev/null +++ b/direct/src/plugin/p3dPythonObject.cxx @@ -0,0 +1,302 @@ +// Filename: p3dPythonObject.cxx +// Created by: drose (03Jul09) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "p3dPythonObject.h" + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +P3DPythonObject:: +P3DPythonObject(P3DSession *session, int object_id) : + _session(session), + _object_id(object_id) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +P3DPythonObject:: +~P3DPythonObject() { + // TODO. +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_type +// Access: Public, Virtual +// Description: Returns the fundamental type of this kind of object. +//////////////////////////////////////////////////////////////////// +P3D_object_type P3DPythonObject:: +get_type() const { + return P3D_OT_object; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_bool +// Access: Public, Virtual +// Description: Returns the object value coerced to a boolean, if +// possible. +//////////////////////////////////////////////////////////////////// +bool P3DPythonObject:: +get_bool() const { + bool bresult = 0; + + P3D_object *result = call("__bool__", NULL); + if (result != NULL) { + bresult = P3D_OBJECT_GET_BOOL(result); + P3D_OBJECT_FINISH(result); + } + + return bresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_int +// Access: Public, Virtual +// Description: Returns the object value coerced to an integer, if +// possible. +//////////////////////////////////////////////////////////////////// +int P3DPythonObject:: +get_int() const { + int iresult = 0; + + P3D_object *result = call("__int__", NULL); + if (result != NULL) { + iresult = P3D_OBJECT_GET_INT(result); + P3D_OBJECT_FINISH(result); + } + + return iresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_float +// Access: Public, Virtual +// Description: Returns the object value coerced to a floating-point +// value, if possible. +//////////////////////////////////////////////////////////////////// +double P3DPythonObject:: +get_float() const { + double fresult = 0.0; + + P3D_object *result = call("__float__", NULL); + if (result != NULL) { + fresult = P3D_OBJECT_GET_FLOAT(result); + P3D_OBJECT_FINISH(result); + } + + return fresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::make_string +// Access: Public, Virtual +// Description: Fills the indicated C++ string object with the value +// of this object coerced to a string. +//////////////////////////////////////////////////////////////////// +void P3DPythonObject:: +make_string(string &value) const { + P3D_object *result = call("__str__", NULL); + if (result != NULL) { + int size = P3D_OBJECT_GET_STRING(result, NULL, 0); + char *buffer = new char[size]; + P3D_OBJECT_GET_STRING(result, buffer, size); + value = string(buffer, size); + delete[] buffer; + + P3D_OBJECT_FINISH(result); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_property +// Access: Public, Virtual +// Description: Returns the named property element in the object. The +// return value is a freshly-allocated P3DPythonObject object +// that must be deleted by the caller, or NULL on error. +//////////////////////////////////////////////////////////////////// +P3D_object *P3DPythonObject:: +get_property(const string &property) const { + P3DListObject *params = new P3DListObject; + params->append(new P3DStringObject(property)); + + P3D_object *result = call("__getattr__", params); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::set_property +// Access: Public, Virtual +// Description: Modifies (or deletes, if value is NULL) the named +// property element in the object. Returns true on +// success, false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DPythonObject:: +set_property(const string &property, P3D_object *value) { + bool bresult = false; + + P3DListObject *params = new P3DListObject; + params->append(new P3DStringObject(property)); + + P3D_object *result = NULL; + + if (value == NULL) { + // Delete an attribute. + result = call("__delattr__", params); + + } else { + // Set a new attribute. + params->append(value); + + result = call("__setattr__", params); + } + + if (result != NULL) { + bresult = P3D_OBJECT_GET_BOOL(result); + P3D_OBJECT_FINISH(result); + } + + return bresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_list_length +// Access: Public, Virtual +// Description: Returns the length of the object as a list. +//////////////////////////////////////////////////////////////////// +int P3DPythonObject:: +get_list_length() const { + // TODO. + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::get_element +// Access: Public, Virtual +// Description: Returns the nth item in the value as a list. The +// return value is a freshly-allocated P3DPythonObject object +// that must be deleted by the caller, or NULL on error. +//////////////////////////////////////////////////////////////////// +P3D_object *P3DPythonObject:: +get_element(int n) const { + // TODO. + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::set_element +// Access: Public, Virtual +// Description: Modifies (or deletes, if value is NULL) the nth item +// in the value as a list. Returns true on success, +// false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DPythonObject:: +set_element(int n, P3D_object *value) { + // TODO. + if (value != NULL) { + P3D_OBJECT_FINISH(value); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::call +// Access: Public, Virtual +// Description: Invokes the named method on the object, passing the +// indicated parameters. If the method name is empty, +// invokes the object itself. Returns the return value +// on success, NULL on error. +//////////////////////////////////////////////////////////////////// +P3D_object *P3DPythonObject:: +call(const string &method_name, P3D_object *params) const { + TiXmlDocument *doc = new TiXmlDocument; + TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement *xcommand = new TiXmlElement("command"); + xcommand->SetAttribute("cmd", "pyobj"); + xcommand->SetAttribute("op", "call"); + xcommand->SetAttribute("object_id", _object_id); + if (!method_name.empty()) { + xcommand->SetAttribute("method_name", method_name); + } + + if (params != NULL) { + assert(params->_class == &P3DObject::_object_class); + TiXmlElement *xparams = ((P3DObject *)params)->make_xml(); + xcommand->LinkEndChild(xparams); + + // Now we're done with the params object passed in, we can delete + // it as promised. + P3D_OBJECT_FINISH(params); + } + + doc->LinkEndChild(decl); + doc->LinkEndChild(xcommand); + TiXmlDocument *response = _session->command_and_response(doc); + nout << "call response pointer: " << response << "\n" << flush; + + P3DObject *result = NULL; + if (response != NULL) { + TiXmlElement *xresponse = response->FirstChildElement("response"); + if (xresponse != NULL) { + TiXmlElement *xvalue = xresponse->FirstChildElement("value"); + if (xvalue != NULL) { + result = _session->xml_to_object(xvalue); + } + } + delete response; + } + + nout << "call result = " << result << "\n" << flush; + if (result != NULL) { + nout << " result = " << *result << "\n" << flush; + } + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::output +// Access: Public, Virtual +// Description: Writes a formatted representation of the value to the +// indicated string. This is intended for developer +// assistance. +//////////////////////////////////////////////////////////////////// +void P3DPythonObject:: +output(ostream &out) const { + P3D_object *result = call("__repr__", NULL); + out << "Python " << _object_id; + if (result != NULL) { + out << ": " << *result; + P3D_OBJECT_FINISH(result); + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: P3DPythonObject::make_xml +// Access: Public, Virtual +// Description: Allocates and returns a new XML structure +// corresponding to this value. +//////////////////////////////////////////////////////////////////// +TiXmlElement *P3DPythonObject:: +make_xml() const { + TiXmlElement *xvalue = new TiXmlElement("value"); + xvalue->SetAttribute("type", "python"); + xvalue->SetAttribute("object_id", _object_id); + + return xvalue; +} diff --git a/direct/src/plugin/p3dPythonObject.h b/direct/src/plugin/p3dPythonObject.h new file mode 100644 index 0000000000..0270152fc7 --- /dev/null +++ b/direct/src/plugin/p3dPythonObject.h @@ -0,0 +1,63 @@ +// Filename: p3dPythonObject.h +// Created by: drose (02Jul09) +// +//////////////////////////////////////////////////////////////////// +// +// 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 P3DPYTHONOBJECT_H +#define P3DPYTHONOBJECT_H + +#include "p3d_plugin_common.h" +#include "p3dObject.h" + +class P3DSession; + +//////////////////////////////////////////////////////////////////// +// Class : P3DPythonObject +// Description : An object type that references a PyObject in the +// subordinate process. It allows querying and/or +// modifying the state of the referenced PyObject, via +// clever XML communication in +// P3DSession::command_and_response(). +//////////////////////////////////////////////////////////////////// +class P3DPythonObject : public P3DObject { +public: + P3DPythonObject(P3DSession *session, int object_id); + virtual ~P3DPythonObject(); + +public: + virtual P3D_object_type get_type() const; + virtual bool get_bool() const; + virtual int get_int() const; + virtual double get_float() const; + + virtual void make_string(string &value) const; + + virtual P3D_object *get_property(const string &property) const; + virtual bool set_property(const string &property, P3D_object *value); + + virtual int get_list_length() const; + virtual P3D_object *get_element(int n) const; + virtual bool set_element(int n, P3D_object *value); + + virtual P3D_object *call(const string &method_name, P3D_object *params) const; + + virtual TiXmlElement *make_xml() const; + + virtual void output(ostream &out) const; + +private: + P3DSession *_session; + int _object_id; +}; + +#endif + diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index f6de86904e..a964bf7054 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -273,7 +273,104 @@ handle_pyobj_command(TiXmlElement *xcommand, int want_response_id) { if (op != NULL) { if (strcmp(op, "get_script_object") == 0) { // Get the toplevel Python object. - xresponse->SetAttribute("object", "fooby"); + PyObject *obj = PyObject_GetAttrString(_runner, "scriptRoot"); + if (obj != NULL) { + xresponse->LinkEndChild(pyobj_to_xml(obj)); + Py_DECREF(obj); + } + } else if (strcmp(op, "call") == 0) { + // Call the named method on the indicated object, or the object + // itself if method_name isn't given. + int object_id; + if (xcommand->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) { + PyObject *obj = (PyObject *)(void *)object_id; + const char *method_name = xcommand->Attribute("method_name"); + PyObject *params = NULL; + TiXmlElement *xvalue = xcommand->FirstChildElement("value"); + if (xvalue != NULL) { + params = xml_to_pyobj(xvalue); + if (!PySequence_Check(params)) { + // Wrap it in a tuple to pass it to the method. + PyObject *tuple = PyTuple_New(1); + PyTuple_SetItem(tuple, 0, params); + params = tuple; + } + } + + if (params == NULL) { + params = PyTuple_New(0); + } + + // Now call the method. + PyObject *result = NULL; + if (method_name == NULL) { + // No method name; call the object directly. + result = PyObject_CallObject(obj, params); + + // Several special-case "method" names. + } else if (strcmp(method_name, "__bool__") == 0) { + result = PyBool_FromLong(PyObject_IsTrue(obj)); + + } else if (strcmp(method_name, "__int__") == 0) { + result = PyNumber_Int(obj); + + } else if (strcmp(method_name, "__float__") == 0) { + result = PyNumber_Float(obj); + + } else if (strcmp(method_name, "__repr__") == 0) { + result = PyObject_Repr(obj); + + } else if (strcmp(method_name, "__str__") == 0) { + result = PyObject_Str(obj); + + } else if (strcmp(method_name, "__setattr__") == 0) { + const char *property_name; + PyObject *value; + if (PyArg_ParseTuple(params, "sO", &property_name, &value)) { + PyObject_SetAttrString(obj, property_name, value); + result = Py_True; + Py_INCREF(result); + } + + } else if (strcmp(method_name, "__delattr__") == 0) { + const char *property_name; + if (PyArg_ParseTuple(params, "s", &property_name)) { + if (PyObject_HasAttrString(obj, property_name)) { + PyObject_DelAttrString(obj, property_name); + result = Py_True; + } else { + result = Py_False; + } + Py_INCREF(result); + } + + } else if (strcmp(method_name, "__getattr__") == 0) { + const char *property_name; + if (PyArg_ParseTuple(params, "s", &property_name)) { + if (PyObject_HasAttrString(obj, property_name)) { + result = PyObject_GetAttrString(obj, property_name); + } else { + result = NULL; + } + } + + } else { + // Not a special-case name. Call the named method. + PyObject *method = PyObject_GetAttrString(obj, method_name); + if (method != NULL) { + result = PyObject_CallObject(method, params); + Py_DECREF(method); + } + } + Py_DECREF(params); + + // Feed the return value back through the XML pipe to the + // caller. + if (result != NULL) { + xresponse->LinkEndChild(pyobj_to_xml(result)); + Py_DECREF(result); + } + } } } @@ -622,14 +719,14 @@ terminate_session() { } //////////////////////////////////////////////////////////////////// -// Function: P3DPythonRun::make_xml_value +// Function: P3DPythonRun::pyobj_to_xml // Access: Private // Description: Converts the indicated PyObject to the appropriate // XML representation of a P3D_value type, and returns a // freshly-allocated TiXmlElement. //////////////////////////////////////////////////////////////////// TiXmlElement *P3DPythonRun:: -make_xml_value(PyObject *value) { +pyobj_to_xml(PyObject *value) { TiXmlElement *xvalue = new TiXmlElement("value"); if (value == Py_None) { // None. @@ -690,42 +787,43 @@ make_xml_value(PyObject *value) { xvalue->SetAttribute("value", str); } - } else if (PySequence_Check(value)) { - // A sequence or list value. + } else if (PyTuple_CheckExact(value)) { + // A tuple. We check for this class type specifically; other + // objects that provide a sequence interface should be treated as + // generic Python objects, below, so we don't lose other useful + // functionality in these objects. Even a Python list, since we + // want to allow the caller to modify the list object on the + // Python side. xvalue->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); - xvalue->LinkEndChild(make_xml_value(obj)); + xvalue->LinkEndChild(pyobj_to_xml(obj)); } } else { - // Some other kind of object. Don't know what else to do with it; - // we'll make it a string. - xvalue->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); - xvalue->SetAttribute("value", str); - } - Py_DECREF(as_str); - } + // Some other kind of object. Make it a generic Python object. + // This is more expensive for the caller to deal with--it requires + // a back-and-forth across the XML pipe--but it's much more + // general. + xvalue->SetAttribute("type", "python"); + xvalue->SetAttribute("object_id", (long)value); + + // Temporary hack. + Py_INCREF(value); } return xvalue; } //////////////////////////////////////////////////////////////////// -// Function: P3DPythonRun::from_xml_value +// Function: P3DPythonRun::xml_to_pyobj // Access: Private // Description: Converts the XML representation of a P3D_value type // into the equivalent Python object and returns it. //////////////////////////////////////////////////////////////////// PyObject *P3DPythonRun:: -from_xml_value(TiXmlElement *xvalue) { +xml_to_pyobj(TiXmlElement *xvalue) { const char *type = xvalue->Attribute("type"); if (strcmp(type, "none") == 0) { return Py_BuildValue(""); @@ -761,12 +859,20 @@ from_xml_value(TiXmlElement *xvalue) { TiXmlElement *xchild = xvalue->FirstChildElement("value"); while (xchild != NULL) { - PyObject *child = from_xml_value(xchild); + PyObject *child = xml_to_pyobj(xchild); PyList_Append(list, child); Py_DECREF(child); xchild = xchild->NextSiblingElement("value"); } - return list; + PyObject *tuple = PyList_AsTuple(list); + Py_DECREF(list); + return tuple; + + } else if (strcmp(type, "python") == 0) { + int object_id; + if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) { + return (PyObject *)(void *)object_id; + } } // Something went wrong in decoding. diff --git a/direct/src/plugin/p3dPythonRun.h b/direct/src/plugin/p3dPythonRun.h index a47d48d90c..c02cd8ddf5 100755 --- a/direct/src/plugin/p3dPythonRun.h +++ b/direct/src/plugin/p3dPythonRun.h @@ -90,8 +90,8 @@ private: void terminate_session(); private: - TiXmlElement *make_xml_value(PyObject *value); - PyObject *from_xml_value(TiXmlElement *xvalue); + TiXmlElement *pyobj_to_xml(PyObject *value); + PyObject *xml_to_pyobj(TiXmlElement *xvalue); private: // This method runs only within the read thread. diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index a0763947e0..0551c0dd00 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -16,6 +16,12 @@ #include "p3dInstance.h" #include "p3dInstanceManager.h" #include "p3d_plugin_config.h" +#include "p3dNoneObject.h" +#include "p3dBoolObject.h" +#include "p3dIntObject.h" +#include "p3dFloatObject.h" +#include "p3dListObject.h" +#include "p3dPythonObject.h" #ifndef _WIN32 #include @@ -286,6 +292,66 @@ command_and_response(TiXmlDocument *command) { return response; } +//////////////////////////////////////////////////////////////////// +// Function: P3DSession::xml_to_object +// Access: Public +// Description: Converts the XML representation of the particular +// object value into a corresponding P3DObject object. +// Returns the newly-allocated object. +//////////////////////////////////////////////////////////////////// +P3DObject *P3DSession:: +xml_to_object(TiXmlElement *xvalue) { + const char *type = xvalue->Attribute("type"); + if (strcmp(type, "none") == 0) { + return new P3DNoneObject; + + } else if (strcmp(type, "bool") == 0) { + int value; + if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DBoolObject(value != 0); + } + + } else if (strcmp(type, "int") == 0) { + int value; + if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DIntObject(value); + } + + } else if (strcmp(type, "float") == 0) { + double value; + if (xvalue->QueryDoubleAttribute("value", &value) == TIXML_SUCCESS) { + return new P3DFloatObject(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 = xvalue->Attribute(string("value")); + if (value != NULL) { + return new P3DStringObject(*value); + } + + } else if (strcmp(type, "list") == 0) { + P3DListObject *list = new P3DListObject; + + TiXmlElement *xchild = xvalue->FirstChildElement("value"); + while (xchild != NULL) { + list->set_element(list->get_list_length(), xml_to_object(xchild)); + xchild = xchild->NextSiblingElement("value"); + } + return list; + + } else if (strcmp(type, "python") == 0) { + int object_id; + if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) { + return new P3DPythonObject(this, object_id); + } + } + + // Something went wrong in decoding. + return new P3DNoneObject; +} + //////////////////////////////////////////////////////////////////// // Function: P3DSession::install_progress // Access: Private @@ -392,22 +458,6 @@ start_p3dpython() { } _pipe_write << flush; _commands.clear(); - - // Temp testing code. - { - TiXmlDocument *doc = new TiXmlDocument; - TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", ""); - TiXmlElement *xcommand = new TiXmlElement("command"); - xcommand->SetAttribute("cmd", "pyobj"); - xcommand->SetAttribute("op", "get"); - doc->LinkEndChild(decl); - doc->LinkEndChild(xcommand); - TiXmlDocument *response = command_and_response(doc); - nout << "response pointer: " << response << "\n"; - if (response != NULL) { - delete response; - } - } } //////////////////////////////////////////////////////////////////// @@ -573,60 +623,6 @@ rt_make_p3d_request(TiXmlElement *xrequest) { return request; } -//////////////////////////////////////////////////////////////////// -// Function: P3DSession::rt_from_xml_value -// Access: Private -// Description: Converts the XML representation of the particular -// value value into a corresponding P3DObject object. -// Returns the newly-allocated object. -//////////////////////////////////////////////////////////////////// -P3DObject *P3DSession:: -rt_from_xml_value(TiXmlElement *xvalue) { - const char *type = xvalue->Attribute("type"); - if (strcmp(type, "none") == 0) { - return new P3DNoneObject; - - } else if (strcmp(type, "bool") == 0) { - int value; - if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { - return new P3DBoolObject(value != 0); - } - - } else if (strcmp(type, "int") == 0) { - int value; - if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) { - return new P3DIntObject(value); - } - - } else if (strcmp(type, "float") == 0) { - double value; - if (xvalue->QueryDoubleAttribute("value", &value) == TIXML_SUCCESS) { - return new P3DFloatObject(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 = xvalue->Attribute(string("value")); - if (value != NULL) { - return new P3DStringObject(*value); - } - - } else if (strcmp(type, "list") == 0) { - P3DListObject *list = new P3DListObject; - - TiXmlElement *xchild = xvalue->FirstChildElement("value"); - while (xchild != NULL) { - list->set_element(list->get_list_length(), rt_from_xml_value(xchild)); - xchild = xchild->NextSiblingElement("value"); - } - return list; - } - - // Something went wrong in decoding. - return new P3DNoneObject; -} - //////////////////////////////////////////////////////////////////// // Function: P3DSession::rt_terminate // Access: Private diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index 86270cd5f8..a2e05f22c7 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -49,6 +49,7 @@ public: void send_command(TiXmlDocument *command); TiXmlDocument *command_and_response(TiXmlDocument *command); + P3DObject *xml_to_object(TiXmlElement *xvalue); private: void install_progress(P3DPackage *package, double progress); @@ -63,7 +64,6 @@ private: void rt_terminate(); void rt_handle_request(TiXmlDocument *doc); P3D_request *rt_make_p3d_request(TiXmlElement *xrequest); - P3DObject *rt_from_xml_value(TiXmlElement *xvalue); #ifdef _WIN32 static DWORD WINAPI win_rt_thread_run(LPVOID data); diff --git a/direct/src/plugin/p3dStringObject.cxx b/direct/src/plugin/p3dStringObject.cxx index 986f4b892e..de35e1552c 100644 --- a/direct/src/plugin/p3dStringObject.cxx +++ b/direct/src/plugin/p3dStringObject.cxx @@ -20,10 +20,7 @@ // Description: //////////////////////////////////////////////////////////////////// P3DStringObject:: -P3DStringObject(const string &value) : - P3DObject(P3D_OT_string), - _value(value) -{ +P3DStringObject(const string &value) : _value(value) { } //////////////////////////////////////////////////////////////////// @@ -48,13 +45,13 @@ P3DStringObject:: } //////////////////////////////////////////////////////////////////// -// Function: P3DStringObject::make_copy +// Function: P3DStringObject::get_type // Access: Public, Virtual -// Description: +// Description: Returns the fundamental type of this kind of object. //////////////////////////////////////////////////////////////////// -P3DObject *P3DStringObject:: -make_copy() const { - return new P3DStringObject(*this); +P3D_object_type P3DStringObject:: +get_type() const { + return P3D_OT_string; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dStringObject.h b/direct/src/plugin/p3dStringObject.h index 498ff73aa6..41582ae6d8 100644 --- a/direct/src/plugin/p3dStringObject.h +++ b/direct/src/plugin/p3dStringObject.h @@ -30,7 +30,7 @@ public: public: virtual ~P3DStringObject(); - virtual P3DObject *make_copy() const; + virtual P3D_object_type get_type() const; virtual bool get_bool() const; virtual void make_string(string &value) const; diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 8c55d8e82c..6ecd6ee688 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -203,8 +203,7 @@ P3D_instance_get_script_object(P3D_instance *instance) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); ACQUIRE_LOCK(_lock); - // TODO. - P3D_object *result = NULL; + P3D_object *result = ((P3DInstance *)instance)->get_script_object(); RELEASE_LOCK(_lock); return result; diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 5765d54a57..425535f307 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -388,21 +388,20 @@ P3D_object_set_element_method(P3D_object *object, int n, P3D_object *value); typedef int P3D_object_get_list_length_method(const P3D_object *object); -/* Invokes the object as a function. The params object should be a - list object containing the individual parameters; ownership of this - list object is transferred in this call, and it will automatically - be deleted. The return value is a newly-allocated P3D_object on - success, or NULL on failure. Ownership of the return value is - transferred to the caller. */ -typedef P3D_object * -P3D_object_call_method(const P3D_object *object, P3D_object *params); +/* Invokes a named method on the object. If method_name is empty or + NULL, invokes the object itself as a function. The params object + should be a list object containing the individual parameters; + ownership of this list object is transferred in this call, and it + will automatically be deleted. It may also be NULL if no + parameters are required, or a single non-list parameter if only one + parameter is required. -/* Evaluates an arbitrary script expression, if possible, within the - context of the object. The return value is the return value of the - expression, or NULL on error. As above, ownership of the return - value is transferred to the caller. */ + The return value is a newly-allocated P3D_object on success, or + NULL on failure. Ownership of the return value is transferred to + the caller. */ typedef P3D_object * -P3D_object_evaluate_method(const P3D_object *object, const char *expression); +P3D_object_call_method(const P3D_object *object, const char *method_name, + P3D_object *params); /* This defines the class structure that implements all of the above methods. */ @@ -424,7 +423,6 @@ typedef struct _P3D_class_definition { P3D_object_get_list_length_method *_get_list_length; P3D_object_call_method *_call; - P3D_object_evaluate_method *_evaluate; } P3D_class_definition; @@ -455,8 +453,7 @@ struct _P3D_object { #define P3D_OBJECT_SET_ELEMENT(object, n, value) ((object)->_class->_set_element((object), (n), (value))) #define P3D_OBJECT_GET_LIST_LENGTH(object, n, value) ((object)->_class->_get_list_length((object), (n), (value))) -#define P3D_OBJECT_CALL(object, params) ((object)->_class->_call((object), (params))) -#define P3D_OBJECT_EVALUATE(object, expression) ((object)->_class->_evaluate((object), (expression))) +#define P3D_OBJECT_CALL(object, method_name, params) ((object)->_class->_call((object), (method_name), (params))) /* The following function types are once again meant to define diff --git a/direct/src/plugin/p3d_plugin_composite1.cxx b/direct/src/plugin/p3d_plugin_composite1.cxx index f17e2f16e9..5ae73983b1 100644 --- a/direct/src/plugin/p3d_plugin_composite1.cxx +++ b/direct/src/plugin/p3d_plugin_composite1.cxx @@ -10,6 +10,7 @@ #include "p3dIntObject.cxx" #include "p3dListObject.cxx" #include "p3dMultifileReader.cxx" +#include "p3dPythonObject.cxx" #include "p3dNoneObject.cxx" #include "p3dObject.cxx" #include "p3dPackage.cxx" diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 8d1a362959..4d6fdcc930 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -404,6 +404,28 @@ handle_request(P3D_request *request) { cerr << "Got P3D_RT_notify: " << request->_request._notify._message << "\n"; // Ignore notifications. + + // Temporary. + P3D_object *obj = P3D_instance_get_script_object(request->_instance); + cerr << "script_object is " << obj << "\n"; + if (obj != NULL) { + if (P3D_OBJECT_SET_PROPERTY(obj, "foo", P3D_new_int_object(1))) { + cerr << "set_property succeeded\n"; + P3D_object *prop = P3D_OBJECT_GET_PROPERTY(obj, "foo"); + cerr << "get_property returned " << prop << "\n"; + if (prop != NULL) { + int size = P3D_OBJECT_GET_STRING(prop, NULL, 0); + char *buffer = new char[size]; + P3D_OBJECT_GET_STRING(prop, buffer, size); + cerr << " property is " << buffer << "\n"; + delete buffer; + P3D_OBJECT_FINISH(prop); + } + } else { + cerr << "set_property failed\n"; + } + P3D_OBJECT_FINISH(obj); + } break; default: diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index 14d2eb138c..a64101b7c2 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -41,6 +41,12 @@ default-model-extension .bam class ArgumentError(AttributeError): pass +class ScriptRoot: + """ This dummy class serves as the root object for the scripting + interface. The Python code can store objects and functions here + for direct meddling by the browser's JavaScript code. """ + pass + class AppRunner(DirectObject): def __init__(self): DirectObject.__init__(self) @@ -50,7 +56,10 @@ class AppRunner(DirectObject): self.gotP3DFilename = False self.started = False self.windowPrc = None + + # TODO: we need one of these per instance, not per session. self.instanceId = None + self.scriptRoot = ScriptRoot() # This is the default requestFunc that is installed if we # never call setRequestFunc().