Browse Source

share main object, don't just copy properties

David Rose 15 years ago
parent
commit
d8df46beed

+ 8 - 2
direct/src/p3d/AppRunner.py

@@ -178,7 +178,9 @@ class AppRunner(DirectObject):
 
 
         # The "main" object will be exposed to the DOM as a property
         # The "main" object will be exposed to the DOM as a property
         # of the plugin object; that is, document.pluginobject.main in
         # of the plugin object; that is, document.pluginobject.main in
-        # JavaScript will be appRunner.main here.
+        # JavaScript will be appRunner.main here.  This may be
+        # replaced with a direct reference to the JavaScript object
+        # later, in setInstanceInfo().
         self.main = ScriptAttributes()
         self.main = ScriptAttributes()
 
 
         # By default, we publish a stop() method so the browser can
         # By default, we publish a stop() method so the browser can
@@ -770,7 +772,7 @@ class AppRunner(DirectObject):
         self.deferredEvals = []
         self.deferredEvals = []
 
 
     def setInstanceInfo(self, rootDir, logDirectory, superMirrorUrl,
     def setInstanceInfo(self, rootDir, logDirectory, superMirrorUrl,
-                        verifyContents):
+                        verifyContents, main):
         """ Called by the browser to set some global information about
         """ Called by the browser to set some global information about
         the instance. """
         the instance. """
 
 
@@ -792,6 +794,10 @@ class AppRunner(DirectObject):
         # the latest code?
         # the latest code?
         self.verifyContents = verifyContents
         self.verifyContents = verifyContents
 
 
+        # The initial "main" object, if specified.
+        if main is not None:
+            self.main = main
+
         # Now that we have rootDir, we can read the config file.
         # Now that we have rootDir, we can read the config file.
         self.readConfigXml()
         self.readConfigXml()
         
         

+ 80 - 76
direct/src/plugin/p3dInstance.cxx

@@ -101,9 +101,9 @@ P3DInstance(P3D_request_ready_func *func,
             int argc, const char *argv[], void *user_data) :
             int argc, const char *argv[], void *user_data) :
   _func(func)
   _func(func)
 {
 {
-  _browser_script_object = NULL;
-  _panda_script_object = new P3DMainObject;
-  _panda_script_object->set_instance(this);
+  _dom_object = NULL;
+  _main_object = new P3DMainObject;
+  _main_object->set_instance(this);
   _user_data = user_data;
   _user_data = user_data;
   _request_pending = false;
   _request_pending = false;
   _total_time_reports = 0;
   _total_time_reports = 0;
@@ -180,16 +180,16 @@ P3DInstance(P3D_request_ready_func *func,
 #endif  // __APPLE__
 #endif  // __APPLE__
 
 
   // Set some initial properties.
   // Set some initial properties.
-  _panda_script_object->set_float_property("instanceDownloadProgress", 0.0);
-  _panda_script_object->set_float_property("downloadProgress", 0.0);
-  _panda_script_object->set_undefined_property("downloadElapsedSeconds");
-  _panda_script_object->set_undefined_property("downloadElapsedFormatted");
-  _panda_script_object->set_undefined_property("downloadRemainingSeconds");
-  _panda_script_object->set_undefined_property("downloadRemainingFormatted");
-  _panda_script_object->set_string_property("downloadPackageName", "");
-  _panda_script_object->set_string_property("downloadPackageDisplayName", "");
-  _panda_script_object->set_bool_property("downloadComplete", false);
-  _panda_script_object->set_string_property("status", "initial");
+  _main_object->set_float_property("instanceDownloadProgress", 0.0);
+  _main_object->set_float_property("downloadProgress", 0.0);
+  _main_object->set_undefined_property("downloadElapsedSeconds");
+  _main_object->set_undefined_property("downloadElapsedFormatted");
+  _main_object->set_undefined_property("downloadRemainingSeconds");
+  _main_object->set_undefined_property("downloadRemainingFormatted");
+  _main_object->set_string_property("downloadPackageName", "");
+  _main_object->set_string_property("downloadPackageDisplayName", "");
+  _main_object->set_bool_property("downloadComplete", false);
+  _main_object->set_string_property("status", "initial");
 
 
   ostringstream stream;
   ostringstream stream;
   stream << inst_mgr->get_plugin_major_version() << "."
   stream << inst_mgr->get_plugin_major_version() << "."
@@ -210,22 +210,22 @@ P3DInstance(P3D_request_ready_func *func,
     --numeric_version;
     --numeric_version;
   }
   }
 
 
-  _panda_script_object->set_string_property("pluginVersionString", stream.str());
-  _panda_script_object->set_int_property("pluginMajorVersion", inst_mgr->get_plugin_major_version());
-  _panda_script_object->set_int_property("pluginMinorVersion", inst_mgr->get_plugin_minor_version());
-  _panda_script_object->set_int_property("pluginSequenceVersion", inst_mgr->get_plugin_sequence_version());
-  _panda_script_object->set_bool_property("pluginOfficialVersion", inst_mgr->get_plugin_official_version());
-  _panda_script_object->set_int_property("pluginNumericVersion", numeric_version);
-  _panda_script_object->set_string_property("pluginDistributor", inst_mgr->get_plugin_distributor());
-  _panda_script_object->set_string_property("coreapiHostUrl", inst_mgr->get_coreapi_host_url());
+  _main_object->set_string_property("pluginVersionString", stream.str());
+  _main_object->set_int_property("pluginMajorVersion", inst_mgr->get_plugin_major_version());
+  _main_object->set_int_property("pluginMinorVersion", inst_mgr->get_plugin_minor_version());
+  _main_object->set_int_property("pluginSequenceVersion", inst_mgr->get_plugin_sequence_version());
+  _main_object->set_bool_property("pluginOfficialVersion", inst_mgr->get_plugin_official_version());
+  _main_object->set_int_property("pluginNumericVersion", numeric_version);
+  _main_object->set_string_property("pluginDistributor", inst_mgr->get_plugin_distributor());
+  _main_object->set_string_property("coreapiHostUrl", inst_mgr->get_coreapi_host_url());
   time_t timestamp = inst_mgr->get_coreapi_timestamp();
   time_t timestamp = inst_mgr->get_coreapi_timestamp();
-  _panda_script_object->set_int_property("coreapiTimestamp", (int)timestamp);
+  _main_object->set_int_property("coreapiTimestamp", (int)timestamp);
   const char *timestamp_string = ctime(&timestamp);
   const char *timestamp_string = ctime(&timestamp);
   if (timestamp_string == NULL) {
   if (timestamp_string == NULL) {
     timestamp_string = "";
     timestamp_string = "";
   }
   }
-  _panda_script_object->set_string_property("coreapiTimestampString", timestamp_string);
-  _panda_script_object->set_string_property("coreapiVersionString", inst_mgr->get_coreapi_set_ver());
+  _main_object->set_string_property("coreapiTimestampString", timestamp_string);
+  _main_object->set_string_property("coreapiVersionString", inst_mgr->get_coreapi_set_ver());
 
 
 
 
   // We'll start off with the "download" image displayed in the splash
   // We'll start off with the "download" image displayed in the splash
@@ -266,17 +266,17 @@ P3DInstance::
   assert(_session == NULL);
   assert(_session == NULL);
   cleanup();
   cleanup();
 
 
-  if (_browser_script_object != NULL) {
-    P3D_OBJECT_DECREF(_browser_script_object);
-    _browser_script_object = NULL;
+  if (_dom_object != NULL) {
+    P3D_OBJECT_DECREF(_dom_object);
+    _dom_object = NULL;
   }
   }
 
 
-  if (_panda_script_object != NULL) {
+  if (_main_object != NULL) {
     nout << "panda_script_object ref = "
     nout << "panda_script_object ref = "
-         << _panda_script_object->_ref_count << "\n";
-    _panda_script_object->set_instance(NULL);
-    P3D_OBJECT_DECREF(_panda_script_object);
-    _panda_script_object = NULL;
+         << _main_object->_ref_count << "\n";
+    _main_object->set_instance(NULL);
+    P3D_OBJECT_DECREF(_main_object);
+    _main_object = NULL;
   }
   }
 
 
   Downloads::iterator di;
   Downloads::iterator di;
@@ -438,7 +438,7 @@ set_p3d_url(const string &p3d_url) {
     download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
     download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
   }
   }
 
 
-  _panda_script_object->set_string_property("status", "downloading_instance");
+  _main_object->set_string_property("status", "downloading_instance");
   start_download(download);
   start_download(download);
 }
 }
 
 
@@ -480,7 +480,7 @@ make_p3d_stream(const string &p3d_url) {
     download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
     download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
   }
   }
 
 
-  _panda_script_object->set_string_property("status", "downloading_instance");
+  _main_object->set_string_property("status", "downloading_instance");
   return start_download(download, false);
   return start_download(download, false);
 }
 }
 
 
@@ -584,7 +584,7 @@ set_wparams(const P3DWindowParams &wparams) {
 P3D_object *P3DInstance::
 P3D_object *P3DInstance::
 get_panda_script_object() const {
 get_panda_script_object() const {
   nout << "get_panda_script_object\n";
   nout << "get_panda_script_object\n";
-  return _panda_script_object;
+  return _main_object;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -599,11 +599,11 @@ get_panda_script_object() const {
 void P3DInstance::
 void P3DInstance::
 set_browser_script_object(P3D_object *browser_script_object) {
 set_browser_script_object(P3D_object *browser_script_object) {
   nout << "set_browser_script_object\n";
   nout << "set_browser_script_object\n";
-  if (browser_script_object != _browser_script_object) {
-    P3D_OBJECT_XDECREF(_browser_script_object);
-    _browser_script_object = browser_script_object;
-    if (_browser_script_object != NULL) {
-      P3D_OBJECT_INCREF(_browser_script_object);
+  if (browser_script_object != _dom_object) {
+    P3D_OBJECT_XDECREF(_dom_object);
+    _dom_object = browser_script_object;
+    if (_dom_object != NULL) {
+      P3D_OBJECT_INCREF(_dom_object);
     }
     }
 
 
     if (_session != NULL) {
     if (_session != NULL) {
@@ -617,8 +617,8 @@ set_browser_script_object(P3D_object *browser_script_object) {
   _origin_protocol.clear();
   _origin_protocol.clear();
   _origin_hostname.clear();
   _origin_hostname.clear();
   _origin_port.clear();
   _origin_port.clear();
-  if (_browser_script_object != NULL) {
-    P3D_object *location = P3D_OBJECT_GET_PROPERTY(_browser_script_object, "location");
+  if (_dom_object != NULL) {
+    P3D_object *location = P3D_OBJECT_GET_PROPERTY(_dom_object, "location");
     if (location != NULL) {
     if (location != NULL) {
       P3D_object *protocol = P3D_OBJECT_GET_PROPERTY(location, "protocol");
       P3D_object *protocol = P3D_OBJECT_GET_PROPERTY(location, "protocol");
       if (protocol != NULL) {
       if (protocol != NULL) {
@@ -717,8 +717,8 @@ get_request() {
         string message = request->_request._notify._message;
         string message = request->_request._notify._message;
         string expression = _fparams.lookup_token(message);
         string expression = _fparams.lookup_token(message);
         nout << "notify: " << message << " " << expression << "\n";
         nout << "notify: " << message << " " << expression << "\n";
-        if (!expression.empty() && _browser_script_object != NULL) {
-          P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
+        if (!expression.empty() && _dom_object != NULL) {
+          P3D_object *result = P3D_OBJECT_EVAL(_dom_object, expression.c_str());
           P3D_OBJECT_XDECREF(result);
           P3D_OBJECT_XDECREF(result);
         }
         }
       }
       }
@@ -728,14 +728,14 @@ get_request() {
       {
       {
         // We also send an implicit message when Python requests itself
         // We also send an implicit message when Python requests itself
         // to shutdown.
         // to shutdown.
-        _panda_script_object->set_pyobj(NULL);
-        _panda_script_object->set_string_property("status", "stopped");
+        _main_object->set_pyobj(NULL);
+        _main_object->set_string_property("status", "stopped");
         
         
         string message = "onpythonstop";
         string message = "onpythonstop";
         string expression = _fparams.lookup_token(message);
         string expression = _fparams.lookup_token(message);
         nout << "notify: " << message << " " << expression << "\n";
         nout << "notify: " << message << " " << expression << "\n";
-        if (!expression.empty() && _browser_script_object != NULL) {
-          P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
+        if (!expression.empty() && _dom_object != NULL) {
+          P3D_object *result = P3D_OBJECT_EVAL(_dom_object, expression.c_str());
           P3D_OBJECT_XDECREF(result);
           P3D_OBJECT_XDECREF(result);
         }
         }
       }
       }
@@ -1370,6 +1370,10 @@ make_xml() {
     xinstance->LinkEndChild(xpackage);
     xinstance->LinkEndChild(xpackage);
   }
   }
 
 
+  TiXmlElement *xmain = _session->p3dobj_to_xml(_main_object);
+  xmain->SetValue("main");
+  xinstance->LinkEndChild(xmain);
+
   return xinstance;
   return xinstance;
 }
 }
 
 
@@ -1607,7 +1611,7 @@ priv_set_p3d_filename(const string &p3d_filename, const int &p3d_offset) {
   }
   }
   _got_fparams = true;
   _got_fparams = true;
 
 
-  _panda_script_object->set_float_property("instanceDownloadProgress", 1.0);
+  _main_object->set_float_property("instanceDownloadProgress", 1.0);
 
 
   // Generate a special notification: onpluginload, indicating the
   // Generate a special notification: onpluginload, indicating the
   // plugin has read its parameters and is ready to be queried (even
   // plugin has read its parameters and is ready to be queried (even
@@ -1938,7 +1942,7 @@ mark_p3d_untrusted() {
   // button now.
   // button now.
 
 
   // Notify JS that we've got no trust of the p3d file.
   // Notify JS that we've got no trust of the p3d file.
-  _panda_script_object->set_bool_property("trusted", false);
+  _main_object->set_bool_property("trusted", false);
   send_notify("onunauth");
   send_notify("onunauth");
   set_background_image(IT_unauth);
   set_background_image(IT_unauth);
   set_button_image(IT_auth_ready);
   set_button_image(IT_auth_ready);
@@ -1989,7 +1993,7 @@ mark_p3d_trusted() {
   _session_key = strm.str();
   _session_key = strm.str();
 
 
   // Notify JS that we've accepted the trust of the p3d file.
   // Notify JS that we've accepted the trust of the p3d file.
-  _panda_script_object->set_bool_property("trusted", true);
+  _main_object->set_bool_property("trusted", true);
   send_notify("onauth");
   send_notify("onauth");
 
 
   // Now that we're all set up, start downloading the required
   // Now that we're all set up, start downloading the required
@@ -2268,8 +2272,8 @@ send_browser_script_object() {
   TiXmlElement *xcommand = new TiXmlElement("command");
   TiXmlElement *xcommand = new TiXmlElement("command");
   xcommand->SetAttribute("cmd", "pyobj");
   xcommand->SetAttribute("cmd", "pyobj");
   xcommand->SetAttribute("op", "set_browser_script_object");
   xcommand->SetAttribute("op", "set_browser_script_object");
-  if (_browser_script_object != NULL) {
-    xcommand->LinkEndChild(_session->p3dobj_to_xml(_browser_script_object));
+  if (_dom_object != NULL) {
+    xcommand->LinkEndChild(_session->p3dobj_to_xml(_dom_object));
   }
   }
   
   
   doc->LinkEndChild(xcommand);
   doc->LinkEndChild(xcommand);
@@ -2418,16 +2422,16 @@ handle_notify_request(const string &message) {
       if (_matches_script_origin) {
       if (_matches_script_origin) {
         // We only actually merge the objects if this web page is
         // We only actually merge the objects if this web page is
         // allowed to call our scripting functions.
         // allowed to call our scripting functions.
-        _panda_script_object->set_pyobj(result);
+        _main_object->set_pyobj(result);
       } else {
       } else {
         // Otherwise, we just do a one-time application of the
         // Otherwise, we just do a one-time application of the
         // toplevel properties down to Python.
         // toplevel properties down to Python.
-        _panda_script_object->apply_properties(result);
+        _main_object->apply_properties(result);
       }
       }
       P3D_OBJECT_DECREF(result);
       P3D_OBJECT_DECREF(result);
     }
     }
 
 
-    _panda_script_object->set_string_property("status", "starting");
+    _main_object->set_string_property("status", "starting");
 
 
   } else if (message == "onwindowopen") {
   } else if (message == "onwindowopen") {
     // The process told us that it just succesfully opened its
     // The process told us that it just succesfully opened its
@@ -2444,7 +2448,7 @@ handle_notify_request(const string &message) {
       }
       }
     }
     }
 
 
-    _panda_script_object->set_string_property("status", "open");
+    _main_object->set_string_property("status", "open");
 
 
   } else if (message == "onwindowattach") {
   } else if (message == "onwindowattach") {
     // The graphics window has been attached to the browser frame
     // The graphics window has been attached to the browser frame
@@ -2961,11 +2965,11 @@ ready_to_install() {
       make_splash_window();
       make_splash_window();
     }
     }
     
     
-    _panda_script_object->set_string_property("status", "downloading");
-    _panda_script_object->set_int_property("numDownloadingPackages", _downloading_packages.size());
-    _panda_script_object->set_int_property("totalDownloadSize", _total_download_size);
-    _panda_script_object->set_int_property("downloadElapsedSeconds", 0);
-    _panda_script_object->set_undefined_property("downloadRemainingSeconds");
+    _main_object->set_string_property("status", "downloading");
+    _main_object->set_int_property("numDownloadingPackages", _downloading_packages.size());
+    _main_object->set_int_property("totalDownloadSize", _total_download_size);
+    _main_object->set_int_property("downloadElapsedSeconds", 0);
+    _main_object->set_undefined_property("downloadRemainingSeconds");
 
 
     double progress = 0.0;
     double progress = 0.0;
     if (_prev_downloaded != 0) {
     if (_prev_downloaded != 0) {
@@ -2974,7 +2978,7 @@ ready_to_install() {
       progress = (_prev_downloaded) / (_total_download_size + _prev_downloaded);
       progress = (_prev_downloaded) / (_total_download_size + _prev_downloaded);
       progress = min(progress, 1.0);
       progress = min(progress, 1.0);
 
 
-      _panda_script_object->set_float_property("downloadProgress", progress);
+      _main_object->set_float_property("downloadProgress", progress);
     }
     }
     if (_splash_window != NULL) {
     if (_splash_window != NULL) {
       _splash_window->set_install_progress(progress, true, 0);
       _splash_window->set_install_progress(progress, true, 0);
@@ -3005,10 +3009,10 @@ start_next_download() {
     if (!package->get_ready()) {
     if (!package->get_ready()) {
       // This package is ready to download.  Begin.
       // This package is ready to download.  Begin.
       string name = package->get_formatted_name();
       string name = package->get_formatted_name();
-      _panda_script_object->set_string_property("downloadPackageName", package->get_package_name());
-      _panda_script_object->set_string_property("downloadPackageDisplayName", name);
-      _panda_script_object->set_int_property("downloadPackageNumber", _download_package_index + 1);
-      _panda_script_object->set_int_property("downloadPackageSize", package->get_download_size());
+      _main_object->set_string_property("downloadPackageName", package->get_package_name());
+      _main_object->set_string_property("downloadPackageDisplayName", name);
+      _main_object->set_int_property("downloadPackageNumber", _download_package_index + 1);
+      _main_object->set_int_property("downloadPackageSize", package->get_download_size());
       set_install_label("Installing " + name);
       set_install_label("Installing " + name);
 
 
       nout << "Installing " << package->get_package_name()
       nout << "Installing " << package->get_package_name()
@@ -3049,8 +3053,8 @@ mark_download_complete() {
 
 
   if (!_download_complete) {
   if (!_download_complete) {
     _download_complete = true;
     _download_complete = true;
-    _panda_script_object->set_bool_property("downloadComplete", true);
-    _panda_script_object->set_string_property("status", "downloadcomplete");
+    _main_object->set_bool_property("downloadComplete", true);
+    _main_object->set_string_property("status", "downloadcomplete");
     send_notify("ondownloadcomplete");
     send_notify("ondownloadcomplete");
   }
   }
   
   
@@ -3079,7 +3083,7 @@ ready_to_start() {
     return;
     return;
   }
   }
 
 
-  _panda_script_object->set_string_property("status", "ready");
+  _main_object->set_string_property("status", "ready");
   send_notify("onready");
   send_notify("onready");
 
 
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
@@ -3141,7 +3145,7 @@ report_instance_progress(double progress, bool is_progress_known,
   if (_splash_window != NULL && _show_dl_instance_progress) {
   if (_splash_window != NULL && _show_dl_instance_progress) {
     _splash_window->set_install_progress(progress, is_progress_known, received_data);
     _splash_window->set_install_progress(progress, is_progress_known, received_data);
   }
   }
-  _panda_script_object->set_float_property("instanceDownloadProgress", progress);
+  _main_object->set_float_property("instanceDownloadProgress", progress);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -3178,7 +3182,7 @@ report_package_progress(P3DPackage *package, double progress) {
   if (_splash_window != NULL) {
   if (_splash_window != NULL) {
     _splash_window->set_install_progress(progress, true, 0);
     _splash_window->set_install_progress(progress, true, 0);
   }
   }
-  _panda_script_object->set_float_property("downloadProgress", progress);
+  _main_object->set_float_property("downloadProgress", progress);
 
 
   static const size_t buffer_size = 256;
   static const size_t buffer_size = 256;
   char buffer[buffer_size];
   char buffer[buffer_size];
@@ -3195,10 +3199,10 @@ report_package_progress(P3DPackage *package, double progress) {
 #endif
 #endif
 
 
   int ielapsed = (int)elapsed;
   int ielapsed = (int)elapsed;
-  _panda_script_object->set_int_property("downloadElapsedSeconds", ielapsed);
+  _main_object->set_int_property("downloadElapsedSeconds", ielapsed);
 
 
   sprintf(buffer, "%d:%02d", ielapsed / 60, ielapsed % 60);
   sprintf(buffer, "%d:%02d", ielapsed / 60, ielapsed % 60);
-  _panda_script_object->set_string_property("downloadElapsedFormatted", buffer);
+  _main_object->set_string_property("downloadElapsedFormatted", buffer);
 
 
   if (progress > 0 && (elapsed > 5.0 || progress > 0.2)) {
   if (progress > 0 && (elapsed > 5.0 || progress > 0.2)) {
     double this_total = elapsed / progress;
     double this_total = elapsed / progress;
@@ -3227,9 +3231,9 @@ report_package_progress(P3DPackage *package, double progress) {
       double total = _total_time_reports / (double)_time_reports.size();
       double total = _total_time_reports / (double)_time_reports.size();
       double remaining = max(total - elapsed, 0.0);
       double remaining = max(total - elapsed, 0.0);
       int iremaining = (int)(remaining + 0.5);
       int iremaining = (int)(remaining + 0.5);
-      _panda_script_object->set_int_property("downloadRemainingSeconds", iremaining);
+      _main_object->set_int_property("downloadRemainingSeconds", iremaining);
       sprintf(buffer, "%d:%02d", iremaining / 60, iremaining % 60);
       sprintf(buffer, "%d:%02d", iremaining / 60, iremaining % 60);
-      _panda_script_object->set_string_property("downloadRemainingFormatted", buffer);
+      _main_object->set_string_property("downloadRemainingFormatted", buffer);
     }
     }
   }
   }
 }
 }

+ 2 - 2
direct/src/plugin/p3dInstance.h

@@ -230,8 +230,8 @@ private:
 #endif  // __APPLE__
 #endif  // __APPLE__
 
 
   P3D_request_ready_func *_func;
   P3D_request_ready_func *_func;
-  P3D_object *_browser_script_object;
-  P3DMainObject *_panda_script_object;
+  P3D_object *_dom_object;
+  P3DMainObject *_main_object;
   string _p3d_basename;
   string _p3d_basename;
   string _origin_protocol;
   string _origin_protocol;
   string _origin_hostname;
   string _origin_hostname;

+ 16 - 0
direct/src/plugin/p3dMainObject.cxx

@@ -281,6 +281,22 @@ output(ostream &out) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DMainObject::
 void P3DMainObject::
 set_pyobj(P3D_object *pyobj) {
 set_pyobj(P3D_object *pyobj) {
+  if (pyobj == this) {
+    // We are setting a reference directly to ourselves.  This happens
+    // when the application has accepted the main object we gave it in
+    // set_instance_info().  This means the application is directly
+    // manipulating this object as its appRunner.main.  In this case,
+    // we don't actually need to set the reference; instead, we clear
+    // anything we had set.
+    nout << "application shares main object\n";
+    pyobj = NULL;
+
+  } else if (pyobj != NULL) {
+    // In the alternate case, the application has its own, separate
+    // appRunner.main object.  Thus, we do need to set the pointer.
+    nout << "application has its own main object\n";
+  }
+    
   if (_pyobj != pyobj) {
   if (_pyobj != pyobj) {
     P3D_OBJECT_XDECREF(_pyobj);
     P3D_OBJECT_XDECREF(_pyobj);
     _pyobj = pyobj;
     _pyobj = pyobj;

+ 13 - 2
direct/src/plugin/p3dPythonRun.cxx

@@ -1227,9 +1227,20 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
     super_mirror = "";
     super_mirror = "";
   }
   }
 
 
+  // Get the initial "main" object, if specified.
+  PyObject *main;
+  TiXmlElement *xmain = xinstance->FirstChildElement("main");
+  if (xmain != NULL) {
+    main = xml_to_pyobj(xmain);
+  } else {
+    main = Py_None;
+    Py_INCREF(main);
+  }
+
   PyObject *result = PyObject_CallMethod
   PyObject *result = PyObject_CallMethod
-    (_runner, (char *)"setInstanceInfo", (char *)"sssi", root_dir, 
-     log_directory, super_mirror, verify_contents);
+    (_runner, (char *)"setInstanceInfo", (char *)"sssiO", root_dir, 
+     log_directory, super_mirror, verify_contents, main);
+  Py_DECREF(main);
 
 
   if (result == NULL) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();