From 19e6ffd5ee1d181f7f310d2cc130e61dffe27fb6 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 10 Jul 2009 20:05:14 +0000 Subject: [PATCH] support pre-python properties --- direct/src/plugin/Sources.pp | 2 + direct/src/plugin/p3dFileParams.cxx | 8 +- direct/src/plugin/p3dInstance.cxx | 108 ++++---- direct/src/plugin/p3dInstance.h | 2 + direct/src/plugin/p3dObject.cxx | 139 ++++++++++- direct/src/plugin/p3dObject.h | 13 + direct/src/plugin/p3dPythonObject.cxx | 4 +- direct/src/plugin/p3dToplevelObject.cxx | 258 ++++++++++++++++++++ direct/src/plugin/p3dToplevelObject.h | 75 ++++++ direct/src/plugin/p3d_plugin_composite1.cxx | 1 + direct/src/plugin_npapi/ppInstance.cxx | 40 +-- 11 files changed, 581 insertions(+), 69 deletions(-) create mode 100644 direct/src/plugin/p3dToplevelObject.cxx create mode 100644 direct/src/plugin/p3dToplevelObject.h diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 62c4ac107a..dbb30259d2 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -44,6 +44,7 @@ p3dSession.h p3dSession.I \ p3dSplashWindow.h p3dSplashWindow.I \ p3dStringObject.h \ + p3dToplevelObject.h \ p3dUndefinedObject.h \ p3dWinSplashWindow.h p3dWinSplashWindow.I \ p3dX11SplashWindow.h \ @@ -69,6 +70,7 @@ p3dSession.cxx \ p3dSplashWindow.cxx \ p3dStringObject.cxx \ + p3dToplevelObject.cxx \ p3dUndefinedObject.cxx \ p3dWinSplashWindow.cxx \ p3dX11SplashWindow.cxx \ diff --git a/direct/src/plugin/p3dFileParams.cxx b/direct/src/plugin/p3dFileParams.cxx index df1cb1ed48..7f953fafe0 100644 --- a/direct/src/plugin/p3dFileParams.cxx +++ b/direct/src/plugin/p3dFileParams.cxx @@ -12,8 +12,8 @@ // //////////////////////////////////////////////////////////////////// - #include "p3dFileParams.h" +#include //////////////////////////////////////////////////////////////////// // Function: P3DFileParams::Default Constructor @@ -37,7 +37,11 @@ P3DFileParams(const string &p3d_filename, for (size_t i = 0; i < num_tokens; ++i) { Token token; if (tokens[i]._keyword != NULL) { - token._keyword = tokens[i]._keyword; + // Make the token lowercase, since HTML is case-insensitive but + // we're not. + for (const char *p = tokens[i]._keyword; *p; ++p) { + token._keyword += tolower(*p); + } } if (tokens[i]._value != NULL) { token._value = tokens[i]._value; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index a3c2f38541..a4e84eff2e 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -21,6 +21,7 @@ #include "p3dWinSplashWindow.h" #include "p3dX11SplashWindow.h" #include "p3dObject.h" +#include "p3dToplevelObject.h" #include "p3dUndefinedObject.h" #include @@ -48,6 +49,7 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) : _func(func) { _browser_script_object = NULL; + _panda_script_object = new P3DToplevelObject; _user_data = user_data; _request_pending = false; _got_fparams = false; @@ -62,6 +64,9 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) : _splash_window = NULL; _instance_window_opened = false; _requested_stop = false; + + // Set some initial properties. + _panda_script_object->set_float_property("downloadProgress", 0.0); } //////////////////////////////////////////////////////////////////// @@ -71,14 +76,13 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) : //////////////////////////////////////////////////////////////////// P3DInstance:: ~P3DInstance() { - // TODO: maybe this should be a reference-counted object, so we - // don't delete it too soon. - assert(_session == NULL); P3D_OBJECT_XDECREF(_browser_script_object); - DESTROY_LOCK(_request_lock); + nout << "panda_script_object ref = " + << _panda_script_object->_ref_count << "\n" << flush; + P3D_OBJECT_DECREF(_panda_script_object); // Tell all of the packages that we're no longer in business for // them. @@ -93,6 +97,8 @@ P3DInstance:: _splash_window = NULL; } + DESTROY_LOCK(_request_lock); + // TODO: empty _raw_requests and _baked_requests queues, and // _downloads map. @@ -123,6 +129,25 @@ set_fparams(const P3DFileParams &fparams) { // TODO. _python_version = "python24"; + // Generate a special notification: onpluginload, indicating the + // plugin has read its parameters and is ready to be queried (even + // if Python has not yet started). This notification is special + // because it is the only one generated at this level; the rest of + // them are generated by the Python code, once that is running. + P3D_request *request = new P3D_request; + request->_request_type = P3D_RT_notify; + request->_request._notify._message = strdup("onpluginload"); + add_baked_request(request); + + // Also eval the HTML associated token. + string expression = _fparams.lookup_token("onpluginload"); + if (!expression.empty() && _browser_script_object != NULL) { + P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str()); + if (result != NULL) { + nout << "onpluginload returned: " << *result << "\n"; + } + P3D_OBJECT_XDECREF(result); + } // Maybe create the splash window. if (!_instance_window_opened && _got_wparams) { @@ -179,35 +204,7 @@ set_wparams(const P3DWindowParams &wparams) { //////////////////////////////////////////////////////////////////// P3D_object *P3DInstance:: get_panda_script_object() const { - assert(_session != 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_panda_script_object"); - doc->LinkEndChild(decl); - doc->LinkEndChild(xcommand); - TiXmlDocument *response = _session->command_and_response(doc); - - P3D_object *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_p3dobj(xvalue); - } - } - delete response; - } - - if (result == NULL) { - P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); - result = inst_mgr->new_undefined_object(); - } - - return result; + return _panda_script_object; } //////////////////////////////////////////////////////////////////// @@ -557,6 +554,7 @@ make_p3d_request(TiXmlElement *xrequest) { request = new P3D_request; request->_request_type = P3D_RT_notify; request->_request._notify._message = strdup(message); + handle_notify_request(message); } } else if (strcmp(rtype, "script") == 0) { @@ -599,15 +597,6 @@ make_p3d_request(TiXmlElement *xrequest) { P3D_OBJECT_DECREF(values[i]); } - } else if (strcmp(rtype, "notify") == 0) { - const char *message = xrequest->Attribute("message"); - if (message != NULL) { - request = new P3D_request; - request->_request_type = P3D_RT_notify; - request->_request._notify._message = strdup(message); - handle_notify_request(message); - } - } else if (strcmp(rtype, "drop_p3dobj") == 0) { int object_id; if (xrequest->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) { @@ -636,7 +625,39 @@ void P3DInstance:: handle_notify_request(const string &message) { // We look for certain notify events that have particular meaning // to this instance. - if (message == "onwindowopen") { + nout << "handle_notify: " << message << "\n"; + + if (message == "onpythonload") { + // Once Python is up and running, we can get the actual toplevel + // object from the Python side, and merge it with our own. + + 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_panda_script_object"); + doc->LinkEndChild(decl); + doc->LinkEndChild(xcommand); + TiXmlDocument *response = _session->command_and_response(doc); + + P3D_object *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_p3dobj(xvalue); + } + } + delete response; + } + + if (result != NULL) { + _panda_script_object->set_pyobj(result); + P3D_OBJECT_DECREF(result); + } + + } else if (message == "onwindowopen") { // The process told us that it just succesfully opened its // window. Tear down the splash window. _instance_window_opened = true; @@ -789,6 +810,7 @@ install_progress(P3DPackage *package, double progress) { _splash_window->set_install_label("Installing Panda3D"); _splash_window->set_install_progress(progress); } + _panda_script_object->set_float_property("downloadProgress", progress); } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index e2dc0d8bee..230aa568ab 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -30,6 +30,7 @@ class P3DSplashWindow; class P3DDownload; class P3DPackage; class P3DObject; +class P3DToplevelObject; //////////////////////////////////////////////////////////////////// // Class : P3DInstance @@ -102,6 +103,7 @@ private: P3D_request_ready_func *_func; P3D_object *_browser_script_object; + P3DToplevelObject *_panda_script_object; bool _got_fparams; P3DFileParams _fparams; diff --git a/direct/src/plugin/p3dObject.cxx b/direct/src/plugin/p3dObject.cxx index 8b362d8457..07ab878f92 100644 --- a/direct/src/plugin/p3dObject.cxx +++ b/direct/src/plugin/p3dObject.cxx @@ -13,6 +13,10 @@ //////////////////////////////////////////////////////////////////// #include "p3dObject.h" +#include "p3dBoolObject.h" +#include "p3dIntObject.h" +#include "p3dFloatObject.h" +#include "p3dStringObject.h" #include // strncpy // The following functions are C-style wrappers around the below @@ -254,8 +258,8 @@ get_repr(char *buffer, int buffer_length) { // Function: P3DObject::get_property // Access: Public, Virtual // Description: Returns the named property element in the object. The -// return value is a freshly-allocated P3DObject object -// that must be deleted by the caller, or NULL on error. +// return value is a new-reference P3D_object, or NULL +// on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DObject:: get_property(const string &property) { @@ -323,3 +327,134 @@ output(ostream &out) { out << value; } +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::get_bool_property +// Access: Public +// Description: Returns the value of the named property, as a +// boolean. Returns 0 if the property does not exist. +//////////////////////////////////////////////////////////////////// +bool P3DObject:: +get_bool_property(const string &property) { + P3D_object *result = get_property(property); + if (result == NULL) { + return 0; + } + bool bresult = P3D_OBJECT_GET_BOOL(result); + P3D_OBJECT_DECREF(result); + return bresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::set_bool_property +// Access: Public +// Description: Changes the value of the named property to the +// indicated boolean value. +//////////////////////////////////////////////////////////////////// +bool P3DObject:: +set_bool_property(const string &property, bool value) { + P3D_object *bvalue = new P3DBoolObject(value); + bool result = set_property(property, bvalue); + P3D_OBJECT_DECREF(bvalue); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::get_int_property +// Access: Public +// Description: Returns the value of the named property, as an +// integer. Returns 0 if the property does not exist. +//////////////////////////////////////////////////////////////////// +int P3DObject:: +get_int_property(const string &property) { + P3D_object *result = get_property(property); + if (result == NULL) { + return 0; + } + int iresult = P3D_OBJECT_GET_INT(result); + P3D_OBJECT_DECREF(result); + return iresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::set_int_property +// Access: Public +// Description: Changes the value of the named property to the +// indicated integer value. +//////////////////////////////////////////////////////////////////// +bool P3DObject:: +set_int_property(const string &property, int value) { + P3D_object *ivalue = new P3DIntObject(value); + bool result = set_property(property, ivalue); + P3D_OBJECT_DECREF(ivalue); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::get_float_property +// Access: Public +// Description: Returns the value of the named property, as a +// floating-point number. Returns 0.0 if the property +// does not exist. +//////////////////////////////////////////////////////////////////// +double P3DObject:: +get_float_property(const string &property) { + P3D_object *result = get_property(property); + if (result == NULL) { + return 0.0; + } + double fresult = P3D_OBJECT_GET_FLOAT(result); + P3D_OBJECT_DECREF(result); + return fresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::set_float_property +// Access: Public +// Description: Changes the value of the named property to the +// indicated floating-point value. +//////////////////////////////////////////////////////////////////// +bool P3DObject:: +set_float_property(const string &property, double value) { + P3D_object *fvalue = new P3DFloatObject(value); + bool result = set_property(property, fvalue); + P3D_OBJECT_DECREF(fvalue); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::get_string_property +// Access: Public +// Description: Returns the value of the named property, as a +// string. Returns empty string if the property does +// not exist. +//////////////////////////////////////////////////////////////////// +string P3DObject:: +get_string_property(const string &property) { + P3D_object *result = get_property(property); + if (result == NULL) { + return string(); + } + + int size = P3D_OBJECT_GET_STRING(result, NULL, 0); + char *buffer = new char[size]; + P3D_OBJECT_GET_STRING(result, buffer, size); + string sresult(buffer, size); + delete[] buffer; + + P3D_OBJECT_DECREF(result); + return sresult; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DObject::set_string_property +// Access: Public +// Description: Changes the value of the named property to the +// indicated string value. +//////////////////////////////////////////////////////////////////// +bool P3DObject:: +set_string_property(const string &property, const string &value) { + P3D_object *svalue = new P3DStringObject(value); + bool result = set_property(property, svalue); + P3D_OBJECT_DECREF(svalue); + return result; +} diff --git a/direct/src/plugin/p3dObject.h b/direct/src/plugin/p3dObject.h index 8118e003e7..3977012a56 100644 --- a/direct/src/plugin/p3dObject.h +++ b/direct/src/plugin/p3dObject.h @@ -52,6 +52,19 @@ public: virtual void output(ostream &out); + // Convenience functions. + bool get_bool_property(const string &property); + bool set_bool_property(const string &property, bool value); + + int get_int_property(const string &property); + bool set_int_property(const string &property, int value); + + double get_float_property(const string &property); + bool set_float_property(const string &property, double value); + + string get_string_property(const string &property); + bool set_string_property(const string &property, const string &value); + public: static P3D_class_definition _object_class; static P3D_class_definition _generic_class; diff --git a/direct/src/plugin/p3dPythonObject.cxx b/direct/src/plugin/p3dPythonObject.cxx index e3a041dfc6..7d3b641fa1 100644 --- a/direct/src/plugin/p3dPythonObject.cxx +++ b/direct/src/plugin/p3dPythonObject.cxx @@ -134,8 +134,8 @@ make_string(string &value) { // 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. +// return value is a new-reference P3D_object, or NULL +// on error. //////////////////////////////////////////////////////////////////// P3D_object *P3DPythonObject:: get_property(const string &property) { diff --git a/direct/src/plugin/p3dToplevelObject.cxx b/direct/src/plugin/p3dToplevelObject.cxx new file mode 100644 index 0000000000..b064078875 --- /dev/null +++ b/direct/src/plugin/p3dToplevelObject.cxx @@ -0,0 +1,258 @@ +// Filename: p3dToplevelObject.cxx +// Created by: drose (10Jul09) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "p3dToplevelObject.h" + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +P3DToplevelObject:: +P3DToplevelObject() : + _pyobj(NULL) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +P3DToplevelObject:: +~P3DToplevelObject() { + set_pyobj(NULL); + + // Just in case there are properties we haven't cleared yet. + Properties::const_iterator pi; + for (pi = _properties.begin(); pi != _properties.end(); ++pi) { + P3D_object *value = (*pi).second; + P3D_OBJECT_DECREF(value); + } + _properties.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_type +// Access: Public, Virtual +// Description: Returns the fundamental type of this kind of object. +//////////////////////////////////////////////////////////////////// +P3D_object_type P3DToplevelObject:: +get_type() { + return P3D_OT_object; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_bool +// Access: Public, Virtual +// Description: Returns the object value coerced to a boolean, if +// possible. +//////////////////////////////////////////////////////////////////// +bool P3DToplevelObject:: +get_bool() { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_int +// Access: Public, Virtual +// Description: Returns the object value coerced to an integer, if +// possible. +//////////////////////////////////////////////////////////////////// +int P3DToplevelObject:: +get_int() { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_float +// Access: Public, Virtual +// Description: Returns the object value coerced to a floating-point +// value, if possible. +//////////////////////////////////////////////////////////////////// +double P3DToplevelObject:: +get_float() { + return 0.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::make_string +// Access: Public, Virtual +// Description: Fills the indicated C++ string object with the value +// of this object coerced to a string. +//////////////////////////////////////////////////////////////////// +void P3DToplevelObject:: +make_string(string &value) { + if (_pyobj == NULL) { + value = "P3DToplevelObject"; + } else { + int size = P3D_OBJECT_GET_STRING(_pyobj, NULL, 0); + char *buffer = new char[size]; + P3D_OBJECT_GET_STRING(_pyobj, buffer, size); + value = string(buffer, size); + delete[] buffer; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_property +// Access: Public, Virtual +// Description: Returns the named property element in the object. The +// return value is a new-reference P3D_object, or NULL +// on error. +//////////////////////////////////////////////////////////////////// +P3D_object *P3DToplevelObject:: +get_property(const string &property) { + if (_pyobj == NULL) { + // Without a pyobj, we just report whatever's been stored locally. + Properties::const_iterator pi; + pi = _properties.find(property); + if (pi != _properties.end()) { + P3D_object *result = (*pi).second; + P3D_OBJECT_INCREF(result); + return result; + } + return NULL; + } + + // With a pyobj, we pass the query down to it. + return P3D_OBJECT_GET_PROPERTY(_pyobj, property.c_str()); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::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 P3DToplevelObject:: +set_property(const string &property, P3D_object *value) { + if (_pyobj == NULL) { + // Without a pyobj, we just store the value locally. + if (value != NULL) { + Properties::iterator pi; + pi = _properties.insert(Properties::value_type(property, NULL)).first; + assert(pi != _properties.end()); + P3D_object *orig_value = (*pi).second; + if (orig_value != value) { + P3D_OBJECT_XDECREF(orig_value); + (*pi).second = value; + P3D_OBJECT_INCREF(value); + } + } else { + // Or delete the property locally. + Properties::iterator pi; + pi = _properties.find(property); + if (pi != _properties.end()) { + P3D_object *orig_value = (*pi).second; + P3D_OBJECT_DECREF(orig_value); + _properties.erase(pi); + } + } + return true; + } + + // With a pyobj, we pass this request down. + return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::has_method +// Access: Public, Virtual +// Description: Returns true if the named method exists on this +// object, false otherwise. +//////////////////////////////////////////////////////////////////// +bool P3DToplevelObject:: +has_method(const string &method_name) { + if (_pyobj == NULL) { + // No methods until we get our pyobj. + return false; + } + + return P3D_OBJECT_HAS_METHOD(_pyobj, method_name.c_str()); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::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 *P3DToplevelObject:: +call(const string &method_name, P3D_object *params[], int num_params) { + if (_pyobj == NULL) { + // No methods until we get our pyobj. + return NULL; + } + + return P3D_OBJECT_CALL(_pyobj, method_name.c_str(), params, num_params); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::output +// Access: Public, Virtual +// Description: Writes a formatted representation of the value to the +// indicated string. This is intended for developer +// assistance. +//////////////////////////////////////////////////////////////////// +void P3DToplevelObject:: +output(ostream &out) { + out << "P3DToplevelObject"; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::set_pyobj +// Access: Public +// Description: Changes the internal pyobj pointer. This is the +// P3D_object that references the actual PyObject held +// within the child process, corresponding to the true +// toplevel object there. The new object's reference +// count is incremented, and the previous object's is +// decremented. +//////////////////////////////////////////////////////////////////// +void P3DToplevelObject:: +set_pyobj(P3D_object *pyobj) { + if (_pyobj != pyobj) { + P3D_OBJECT_XDECREF(_pyobj); + _pyobj = pyobj; + if (_pyobj != NULL) { + P3D_OBJECT_INCREF(_pyobj); + + // Now that we have a pyobj, we have to transfer down all of the + // properties we'd set locally. + Properties::const_iterator pi; + for (pi = _properties.begin(); pi != _properties.end(); ++pi) { + const string &property_name = (*pi).first; + P3D_object *value = (*pi).second; + P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value); + P3D_OBJECT_DECREF(value); + } + _properties.clear(); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DToplevelObject::get_pyobj +// Access: Public +// Description: Returns the internal pyobj pointer, or NULL if it has +// not yet been set. +//////////////////////////////////////////////////////////////////// +P3D_object *P3DToplevelObject:: +get_pyobj() const { + return _pyobj; +} diff --git a/direct/src/plugin/p3dToplevelObject.h b/direct/src/plugin/p3dToplevelObject.h new file mode 100644 index 0000000000..d188a1dcc6 --- /dev/null +++ b/direct/src/plugin/p3dToplevelObject.h @@ -0,0 +1,75 @@ +// Filename: p3dToplevelObject.h +// Created by: drose (10Jul09) +// +//////////////////////////////////////////////////////////////////// +// +// 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 P3DTOPLEVELOBJECT_H +#define P3DTOPLEVELOBJECT_H + +#include "p3d_plugin_common.h" +#include "p3dObject.h" +#include + +class P3DSession; + +//////////////////////////////////////////////////////////////////// +// Class : P3DToplevelObject +// Description : This corresponds to the toplevel "Python" object +// owned by a particular instance, as returned by +// P3DInstance::get_panda_script_object(). +// +// This is mostly a wrapper around a P3DPythonObject +// pointer, and therefore functions like any other +// P3DPythonObject; but it also handles the special case +// of being available before Python has been started; +// and it furthermore reports properties that are +// generated directly by the core API (like +// downloadProgress and such). +//////////////////////////////////////////////////////////////////// +class P3DToplevelObject : public P3DObject { +public: + P3DToplevelObject(); + virtual ~P3DToplevelObject(); + +public: + virtual P3D_object_type get_type(); + virtual bool get_bool(); + virtual int get_int(); + virtual double get_float(); + + virtual void make_string(string &value); + + virtual P3D_object *get_property(const string &property); + virtual bool set_property(const string &property, P3D_object *value); + + virtual bool has_method(const string &method_name); + virtual P3D_object *call(const string &method_name, + P3D_object *params[], int num_params); + + virtual void output(ostream &out); + + void set_pyobj(P3D_object *pyobj); + P3D_object *get_pyobj() const; + +private: + P3D_object *_pyobj; + + // This map is used to store properties and retrieve until + // set_pyobj() is called for the firs ttime. At that point, the + // properties stored here are transferred down to the internal + // PyObject. + typedef map Properties; + Properties _properties; +}; + +#endif + diff --git a/direct/src/plugin/p3d_plugin_composite1.cxx b/direct/src/plugin/p3d_plugin_composite1.cxx index 2b30539ca2..4d7cda875d 100644 --- a/direct/src/plugin/p3d_plugin_composite1.cxx +++ b/direct/src/plugin/p3d_plugin_composite1.cxx @@ -17,6 +17,7 @@ #include "p3dSession.cxx" #include "p3dSplashWindow.cxx" #include "p3dStringObject.cxx" +#include "p3dToplevelObject.cxx" #include "p3dUndefinedObject.cxx" #include "p3dWinSplashWindow.cxx" #include "p3dX11SplashWindow.cxx" diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index fecafbadad..5cdfdd41b4 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -423,15 +423,8 @@ handle_request(P3D_request *request) { break; case P3D_RT_notify: - { - if (_script_object != NULL && - strcmp(request->_request._notify._message, "onpythonload") == 0) { - // Now that Python is running, initialize our script_object - // with the proper P3D object pointer. - P3D_object *obj = P3D_instance_get_panda_script_object(_p3d_inst); - _script_object->set_p3d_object(obj); - } - } + // We can ignore notifies, since these are handled by the core + // API. break; default: @@ -922,11 +915,6 @@ create_instance() { return; } - if (!_got_window) { - // No window yet. - return; - } - _p3d_inst = P3D_new_instance(request_ready, this); if (_p3d_inst != NULL) { @@ -940,13 +928,25 @@ create_instance() { } else { logfile << "Couldn't get window_object\n" << flush; } - - P3D_token *tokens = NULL; - if (!_tokens.empty()) { - tokens = &_tokens[0]; + + if (_script_object != NULL) { + // Now that we have a true instance, initialize our + // script_object with the proper P3D_object pointer. + P3D_object *obj = P3D_instance_get_panda_script_object(_p3d_inst); + _script_object->set_p3d_object(obj); + } + + if (_got_instance_data) { + P3D_token *tokens = NULL; + if (!_tokens.empty()) { + tokens = &_tokens[0]; + } + P3D_instance_start(_p3d_inst, _p3d_filename.c_str(), tokens, _tokens.size()); + } + + if (_got_window) { + send_window(); } - P3D_instance_start(_p3d_inst, _p3d_filename.c_str(), tokens, _tokens.size()); - send_window(); } }