Browse Source

Merge branch 'release/1.9.x'

rdb 10 years ago
parent
commit
677407f586

+ 50 - 2
direct/src/plugin/p3dInstance.cxx

@@ -2769,6 +2769,7 @@ make_splash_window() {
     int r, g, b;
     int r, g, b;
     if (parse_color(r, g, b, _fparams.lookup_token("bgcolor"))) {
     if (parse_color(r, g, b, _fparams.lookup_token("bgcolor"))) {
       _splash_window->set_bgcolor(r, g, b);
       _splash_window->set_bgcolor(r, g, b);
+      _splash_window->set_bar_bgcolor(r, g, b);
     } else {
     } else {
       nout << "parse failure on bgcolor " << _fparams.lookup_token("bgcolor") << "\n";
       nout << "parse failure on bgcolor " << _fparams.lookup_token("bgcolor") << "\n";
     }
     }
@@ -2781,11 +2782,58 @@ make_splash_window() {
       nout << "parse failure on barcolor " << _fparams.lookup_token("barcolor") << "\n";
       nout << "parse failure on barcolor " << _fparams.lookup_token("barcolor") << "\n";
     }
     }
   }
   }
+  if (_fparams.has_token("bar_bgcolor")) {
+    int r, g, b;
+    if (parse_color(r, g, b, _fparams.lookup_token("bar_bgcolor"))) {
+      _splash_window->set_bar_bgcolor(r, g, b);
+    } else {
+      nout << "parse failure on bar_bgcolor " << _fparams.lookup_token("bar_bgcolor") << "\n";
+    }
+  }
+  if (_fparams.has_token("bar_border")) {
+    int border = _fparams.lookup_token_int("bar_border");
+    _splash_window->set_bar_border(border);
+  }
+  if (_fparams.has_token("bar_bottom")) {
+    int bottom = _fparams.lookup_token_int("bar_bottom");
+    _splash_window->set_bar_bottom(bottom);
+  }
+  if (_fparams.has_token("bar_width")) {
+    string bar_width = _fparams.lookup_token("bar_width");
+    char *endptr;
+    long width = strtol(bar_width.c_str(), &endptr, 10);
+    bool percent = false;
+
+    if (*endptr == '%') {
+      percent = true;
+      ++endptr;
+    }
+    if (*endptr == '\0' && width >= 0 && width < 65536) {
+      _splash_window->set_bar_width((int)width, percent);
+    } else {
+      nout << "parse failure on bar_width " << bar_width << "\n";
+    }
+  }
+  if (_fparams.has_token("bar_height")) {
+    string bar_height = _fparams.lookup_token("bar_height");
+    char *endptr;
+    long height = strtol(bar_height.c_str(), &endptr, 10);
+    bool percent = false;
+
+    if (*endptr == '%') {
+      percent = true;
+      ++endptr;
+    }
+    if (*endptr == '\0' && height >= 0 && height < 65536) {
+      _splash_window->set_bar_height((int)height, percent);
+    } else {
+      nout << "parse failure on bar_height " << bar_height << "\n";
+    }
+  }
 
 
   _splash_window->set_wparams(_wparams);
   _splash_window->set_wparams(_wparams);
   _splash_window->set_install_label(_install_label);
   _splash_window->set_install_label(_install_label);
-  
-    
+
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
 
 
   // Go get the required images.
   // Go get the required images.

+ 125 - 6
direct/src/plugin/p3dSplashWindow.cxx

@@ -48,6 +48,15 @@ P3DSplashWindow(P3DInstance *inst, bool make_visible) :
   _barcolor_r = 0x6c;
   _barcolor_r = 0x6c;
   _barcolor_g = 0xa5;
   _barcolor_g = 0xa5;
   _barcolor_b = 0xe0;
   _barcolor_b = 0xe0;
+  _bar_bgcolor_r = _bgcolor_r;
+  _bar_bgcolor_g = _bgcolor_g;
+  _bar_bgcolor_b = _bgcolor_b;
+  _bar_border = 1;
+  _bar_bottom = 24;
+  _bar_width = 398;
+  _bar_height = 22;
+  _bar_width_ratio = 0.6;
+  _bar_height_ratio = 0.1;
   _button_width = 0;
   _button_width = 0;
   _button_height = 0;
   _button_height = 0;
   _button_x = 0;
   _button_x = 0;
@@ -113,7 +122,7 @@ set_image_filename(const string &image_filename, ImagePlacement image_placement)
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::set_fgcolor
 //     Function: P3DSplashWindow::set_fgcolor
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Specifies the color that is used to display the text
 //  Description: Specifies the color that is used to display the text
 //               above the loading bar.
 //               above the loading bar.
 //
 //
@@ -129,7 +138,7 @@ set_fgcolor(int r, int g, int b) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::set_bgcolor
 //     Function: P3DSplashWindow::set_bgcolor
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Specifies the solid color that is displayed behind
 //  Description: Specifies the solid color that is displayed behind
 //               the splash image, if any, or before the splash image
 //               the splash image, if any, or before the splash image
 //               is loaded.
 //               is loaded.
@@ -146,7 +155,7 @@ set_bgcolor(int r, int g, int b) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::set_barcolor
 //     Function: P3DSplashWindow::set_barcolor
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Specifies the color that is used to fill the
 //  Description: Specifies the color that is used to fill the
 //               loading bar.
 //               loading bar.
 //
 //
@@ -160,6 +169,105 @@ set_barcolor(int r, int g, int b) {
   _barcolor_b = b;
   _barcolor_b = b;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_bar_bgcolor
+//       Access: Public
+//  Description: Specifies the solid color that is displayed behind
+//               the loading bar.
+//
+//               This may only be set before wparams is set.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_bar_bgcolor(int r, int g, int b) {
+  nout << "bar_bgcolor " << r << ", " << g << ", " << b << "\n";
+  _bar_bgcolor_r = r;
+  _bar_bgcolor_g = g;
+  _bar_bgcolor_b = b;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_bar_border
+//       Access: Public
+//  Description: Sets the width in pixels of the border around the
+//               loading bar, or 0 not to draw a bar at all.
+//
+//               This may only be set before wparams is set.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_bar_border(int border) {
+  nout << "bar_border " << border << "\n";
+  _bar_border = border;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_bar_bottom
+//       Access: Public
+//  Description: Sets the amount of background pixels between the
+//               bottom edge of the window and the bottom edge of
+//               the loading bar border.
+//
+//               This may only be set before wparams is set.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_bar_bottom(int bottom) {
+  nout << "bar_bottom " << bottom << "\n";
+  _bar_bottom = bottom;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_bar_width
+//       Access: Public
+//  Description: Sets the width of the loading bar.  If percent is
+//               true, it is interpreted as a percentage of the
+//               window width.  If false, it is interpreted as an
+//               absolute width in pixels.
+//
+//               This may only be set before wparams is set.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_bar_width(int width, bool percent) {
+  nout << "bar_width " << width;
+  if (percent) {
+    nout << '%';
+  }
+  nout << '\n';
+
+  if (percent) {
+    _bar_width = -1;
+    _bar_width_ratio = abs(width) / 100.0;
+  } else {
+    _bar_width = abs(width);
+    _bar_width_ratio = 1.0;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::set_bar_height
+//       Access: Public
+//  Description: Sets the height of the loading bar.  If percent is
+//               true, it is interpreted as a percentage of the
+//               window height.  If false, it is interpreted as an
+//               absolute height in pixels.
+//
+//               This may only be set before wparams is set.
+////////////////////////////////////////////////////////////////////
+void P3DSplashWindow::
+set_bar_height(int height, bool percent) {
+  nout << "bar_height " << height;
+  if (percent) {
+    nout << '%';
+  }
+  nout << '\n';
+
+  if (percent) {
+    _bar_height = -1;
+    _bar_height_ratio = abs(height) / 100.0;
+  } else {
+    _bar_height = abs(height);
+    _bar_height_ratio = 1.0;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::set_install_label
 //     Function: P3DSplashWindow::set_install_label
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -271,10 +379,21 @@ read_image_data(ImageData &image, string &data,
 void P3DSplashWindow::
 void P3DSplashWindow::
 get_bar_placement(int &bar_x, int &bar_y,
 get_bar_placement(int &bar_x, int &bar_y,
                   int &bar_width, int &bar_height) {
                   int &bar_width, int &bar_height) {
-  bar_width = min((int)(_win_width * 0.6), 400);
-  bar_height = min((int)(_win_height * 0.1), 24);
+
+  bar_width = (int)(_win_width * _bar_width_ratio);
+  bar_height = (int)(_win_height * _bar_height_ratio);
+
+  if (_bar_width >= 0) {
+    bar_width = min(bar_width, _bar_width);
+  }
+  if (_bar_height >= 0) {
+    bar_height = min(bar_height, _bar_height);
+  }
+
+  // Horizontally center the bar, and set it at a fixed distance
+  // from the bottom edge of the splash window.
   bar_x = (_win_width - bar_width) / 2;
   bar_x = (_win_width - bar_width) / 2;
-  bar_y = (_win_height - bar_height * 2);
+  bar_y = _win_height - _bar_bottom - _bar_border - bar_height;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 16 - 3
direct/src/plugin/p3dSplashWindow.h

@@ -54,9 +54,14 @@ public:
 
 
   virtual void set_image_filename(const string &image_filename,
   virtual void set_image_filename(const string &image_filename,
                                   ImagePlacement image_placement);
                                   ImagePlacement image_placement);
-  virtual void set_fgcolor(int r, int g, int b);
-  virtual void set_bgcolor(int r, int g, int b);
-  virtual void set_barcolor(int r, int g, int b);
+  void set_fgcolor(int r, int g, int b);
+  void set_bgcolor(int r, int g, int b);
+  void set_barcolor(int r, int g, int b);
+  void set_bar_bgcolor(int r, int g, int b);
+  void set_bar_border(int border);
+  void set_bar_bottom(int bottom);
+  void set_bar_width(int width, bool percent=false);
+  void set_bar_height(int height, bool percent=false);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_progress(double install_progress,
   virtual void set_install_progress(double install_progress,
                                     bool is_progress_known, size_t received_data);
                                     bool is_progress_known, size_t received_data);
@@ -105,7 +110,15 @@ protected:
   int _fgcolor_r, _fgcolor_g, _fgcolor_b;
   int _fgcolor_r, _fgcolor_g, _fgcolor_b;
   int _bgcolor_r, _bgcolor_g, _bgcolor_b;
   int _bgcolor_r, _bgcolor_g, _bgcolor_b;
   int _barcolor_r, _barcolor_g, _barcolor_b;
   int _barcolor_r, _barcolor_g, _barcolor_b;
+  int _bar_bgcolor_r, _bar_bgcolor_g, _bar_bgcolor_b;
+  int _bar_border;
 
 
+private:
+  int _bar_bottom;
+  int _bar_width, _bar_height;
+  double _bar_width_ratio, _bar_height_ratio;
+
+protected:
   // The region of the window for accepting button clicks.
   // The region of the window for accepting button clicks.
   int _button_width, _button_height;
   int _button_width, _button_height;
   int _button_x, _button_y;
   int _button_x, _button_y;

+ 80 - 15
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -25,6 +25,8 @@
 #include <signal.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
+static const char *xfont_name = "-*-helvetica-medium-r-normal--12-120-*-*-p-*-iso8859-1";
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DX11SplashWindow::Constructor
 //     Function: P3DX11SplashWindow::Constructor
 //       Access: Public
 //       Access: Public
@@ -47,11 +49,14 @@ P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
   _display = None;
   _display = None;
   _window = None;
   _window = None;
   _screen = 0;
   _screen = 0;
+  _font = NULL;
   _graphics_context = None;
   _graphics_context = None;
   _bar_context = None;
   _bar_context = None;
+  _bar_bg_context = None;
   _fg_pixel = -1;
   _fg_pixel = -1;
   _bg_pixel = -1;
   _bg_pixel = -1;
   _bar_pixel = -1;
   _bar_pixel = -1;
+  _bar_bg_pixel = -1;
   _own_display = false;
   _own_display = false;
   _install_progress = 0.0;
   _install_progress = 0.0;
   _progress_known = true;
   _progress_known = true;
@@ -609,10 +614,15 @@ subprocess_run() {
       get_bar_placement(bar_x, bar_y, bar_width, bar_height);
       get_bar_placement(bar_x, bar_y, bar_width, bar_height);
 
 
       if (needs_draw_label) {
       if (needs_draw_label) {
-        int text_width = _install_label.size() * 6;
-        int text_height = 10;
+        int direction, ascent, descent;
+        XCharStruct extents;
+        XTextExtents(_font, _install_label.c_str(), _install_label.size(),
+                     &direction, &ascent, &descent, &extents);
+
+        int text_width = extents.width;
+        int text_height = extents.ascent + extents.descent;
         int text_x = (_win_width - text_width) / 2;
         int text_x = (_win_width - text_width) / 2;
-        int text_y = bar_y - 4;
+        int text_y = bar_y - descent - _bar_border - 4;
 
 
         XClearArea(_display, _window,
         XClearArea(_display, _window,
                    text_x - 2, text_y - text_height - 2,
                    text_x - 2, text_y - text_height - 2,
@@ -624,25 +634,44 @@ subprocess_run() {
       }
       }
 
 
       if (needs_redraw_progress) {
       if (needs_redraw_progress) {
-        XClearArea(_display, _window,
-                   bar_x, bar_y, bar_width, bar_height, false);
-        XDrawRectangle(_display, _window, _graphics_context,
-                       bar_x, bar_y, bar_width, bar_height);
+        // Draw the bar background.
+        if (_bar_bg_context != None) {
+          XFillRectangle(_display, _window, _bar_bg_context,
+                         bar_x, bar_y, bar_width, bar_height);
+        } else {
+          XClearArea(_display, _window,
+                     bar_x, bar_y, bar_width, bar_height, false);
+        }
+
+        // Draw the border around the bar.
+        int border_x = bar_x - 1;
+        int border_y = bar_y - 1;
+        int border_width = bar_width + 1;
+        int border_height = bar_height + 1;
+
+        for (int i = 0; i < _bar_border; ++i) {
+          XDrawRectangle(_display, _window, _graphics_context,
+                         border_x, border_y, border_width, border_height);
+          border_x -= 1;
+          border_y -= 1;
+          border_width += 2;
+          border_height += 2;
+        }
         needs_update_progress = true;
         needs_update_progress = true;
         needs_redraw_progress = false;
         needs_redraw_progress = false;
       }
       }
 
 
       if (needs_update_progress) {
       if (needs_update_progress) {
         if (_progress_known) {
         if (_progress_known) {
-          int progress_width = (int)((bar_width - 2) * _install_progress + 0.5);
+          int progress_width = (int)((bar_width - 1) * _install_progress + 0.5);
           XFillRectangle(_display, _window, _bar_context,
           XFillRectangle(_display, _window, _bar_context,
-                         bar_x + 1, bar_y + 1,
-                         progress_width + 1, bar_height - 1);
+                         bar_x, bar_y,
+                         progress_width + 1, bar_height);
         } else {
         } else {
           // Progress is unknown.  Draw a moving block, not a progress bar
           // Progress is unknown.  Draw a moving block, not a progress bar
           // filling up.
           // filling up.
           int block_width = (int)(bar_width * 0.1 + 0.5);
           int block_width = (int)(bar_width * 0.1 + 0.5);
-          int block_travel = (bar_width - 2) - block_width;
+          int block_travel = (bar_width - 1) - block_width;
           int progress = (int)(_received_data * _unknown_progress_rate);
           int progress = (int)(_received_data * _unknown_progress_rate);
           progress = progress % (block_travel * 2);
           progress = progress % (block_travel * 2);
           if (progress > block_travel) {
           if (progress > block_travel) {
@@ -650,8 +679,8 @@ subprocess_run() {
           }
           }
 
 
           XFillRectangle(_display, _window, _bar_context,
           XFillRectangle(_display, _window, _bar_context,
-                         bar_x + 1 + progress, bar_y + 1,
-                         block_width + 1, bar_height - 1);
+                         bar_x + progress, bar_y,
+                         block_width + 1, bar_height);
         }
         }
         needs_update_progress = false;
         needs_update_progress = false;
       }
       }
@@ -958,10 +987,17 @@ setup_gc() {
     return;
     return;
   }
   }
 
 
-  XFontStruct* fs = XLoadQueryFont(_display, "6x13");
+  _font = XLoadQueryFont(_display, xfont_name);
+
+  if (_font != NULL) {
+    nout << "Loaded font " << xfont_name << "\n";
+  } else {
+    nout << "Font " << xfont_name << " unavailable.\n";
+    _font = XLoadQueryFont(_display, "6x13");
+  }
 
 
   XGCValues gcval;
   XGCValues gcval;
-  gcval.font = fs->fid;
+  gcval.font = _font->fid;
   gcval.function = GXcopy;
   gcval.function = GXcopy;
   gcval.plane_mask = AllPlanes;
   gcval.plane_mask = AllPlanes;
   gcval.foreground = BlackPixel(_display, _screen);
   gcval.foreground = BlackPixel(_display, _screen);
@@ -991,6 +1027,24 @@ setup_gc() {
 
 
   _bar_context = XCreateGC(_display, _window,
   _bar_context = XCreateGC(_display, _window,
     GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
     GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
+
+  // And another for the background color of the bar.
+  if (_bar_bgcolor_r != _bgcolor_r || _bar_bgcolor_g != _bgcolor_g ||
+      _bar_bgcolor_b != _bgcolor_b) {
+    XColor bar_bg;
+    bar_bg.red = _bar_bgcolor_r * 0x101;
+    bar_bg.green = _bar_bgcolor_g * 0x101;
+    bar_bg.blue = _bar_bgcolor_b * 0x101;
+    bar_bg.flags = DoRed | DoGreen | DoBlue;
+
+    if (XAllocColor(_display, colormap, &bar_bg)) {
+      _bar_bg_pixel = bar_bg.pixel;
+      gcval.foreground = bar_bg.pixel;
+    }
+
+    _bar_bg_context = XCreateGC(_display, _window,
+      GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1016,6 +1070,17 @@ close_window() {
     XFreeColors(_display, colormap, &_bar_pixel, 1, 0);
     XFreeColors(_display, colormap, &_bar_pixel, 1, 0);
   }
   }
 
 
+  if (_bar_bg_context != None) {
+    if (_bar_bg_context != _graphics_context) {
+      XFreeGC(_display, _bar_bg_context);
+    }
+    _bar_bg_context = None;
+
+    // Also free the color we allocated.
+    Colormap colormap = DefaultColormap(_display, _screen);
+    XFreeColors(_display, colormap, &_bar_bg_pixel, 1, 0);
+  }
+
   if (_fg_pixel != -1) {
   if (_fg_pixel != -1) {
     Colormap colormap = DefaultColormap(_display, _screen);
     Colormap colormap = DefaultColormap(_display, _screen);
     XFreeColors(_display, colormap, &_fg_pixel, 1, 0);
     XFreeColors(_display, colormap, &_fg_pixel, 1, 0);

+ 6 - 3
direct/src/plugin/p3dX11SplashWindow.h

@@ -86,7 +86,7 @@ private:
   void setup_gc();
   void setup_gc();
   void close_window();
   void close_window();
 
 
-  void update_image(X11ImageData &image); 
+  void update_image(X11ImageData &image);
   void compose_image();
   void compose_image();
   bool scale_image(vector<unsigned char> &image0, int &image0_width, int &image0_height,
   bool scale_image(vector<unsigned char> &image0, int &image0_width, int &image0_height,
                    X11ImageData &image);
                    X11ImageData &image);
@@ -123,17 +123,20 @@ private:
   double _install_progress;
   double _install_progress;
   bool _progress_known;
   bool _progress_known;
   size_t _received_data;
   size_t _received_data;
-  
+
   string _label_text;
   string _label_text;
 
 
   X11_Display *_display;
   X11_Display *_display;
   int _screen;
   int _screen;
+  XFontStruct *_font;
   GC _graphics_context;
   GC _graphics_context;
   GC _bar_context;
   GC _bar_context;
+  GC _bar_bg_context;
   unsigned long _fg_pixel;
   unsigned long _fg_pixel;
   unsigned long _bg_pixel;
   unsigned long _bg_pixel;
   unsigned long _bar_pixel;
   unsigned long _bar_pixel;
-  
+  unsigned long _bar_bg_pixel;
+
   X11_Window _window;
   X11_Window _window;
 };
 };
 
 

+ 88 - 63
direct/src/plugin_standalone/panda3d.cxx

@@ -356,6 +356,7 @@ bool Panda3D::
 get_plugin() {
 get_plugin() {
   // First, look for the existing contents.xml file.
   // First, look for the existing contents.xml file.
   bool success = false;
   bool success = false;
+  bool is_fresh = false;
 
 
   Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
   Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
   if (_verify_contents != P3D_VC_force) {
   if (_verify_contents != P3D_VC_force) {
@@ -370,75 +371,100 @@ get_plugin() {
   if (!success) {
   if (!success) {
     // Couldn't read it (or it wasn't current enough), so go get a new
     // Couldn't read it (or it wasn't current enough), so go get a new
     // one.
     // one.
-    HTTPClient *http = HTTPClient::get_global_ptr();
-    
-    // Try the super_mirror first.
-    if (!_super_mirror_url_prefix.empty()) {
-      // We don't bother putting a uniquifying query string when we're
-      // downloading this file from the super_mirror.  The super_mirror
-      // is by definition a cache, so it doesn't make sense to bust
-      // caches here.
-      string url = _super_mirror_url_prefix + "contents.xml";
-      PT(HTTPChannel) channel = http->make_channel(false);
-      channel->get_document(url);
-      
-      Filename tempfile = Filename::temporary("", "p3d_");
-      if (!channel->download_to_file(tempfile)) {
-        cerr << "Unable to download " << url << "\n";
-        tempfile.unlink();
-      } else {
-        // Successfully downloaded from the super_mirror; try to read it.
-        success = read_contents_file(tempfile, true);
-        tempfile.unlink();
-      }
+    if (!download_contents_file(contents_filename)) {
+      // We don't have a usable contents.xml file.
+      return false;
     }
     }
+    is_fresh = true;
+  }
 
 
-    if (!success) {
-      // Go download contents.xml from the actual host.
-      ostringstream strm;
-      strm << _host_url_prefix << "contents.xml";
-      // Append a uniquifying query string to the URL to force the
-      // download to go all the way through any caches.  We use the time
-      // in seconds; that's unique enough.
-      strm << "?" << time(NULL);
-      string url = strm.str();
-      
-      // We might as well explicitly request the cache to be disabled too,
-      // since we have an interface for that via HTTPChannel.
-      DocumentSpec request(url);
-      request.set_cache_control(DocumentSpec::CC_no_cache);
-      
-      PT(HTTPChannel) channel = http->make_channel(false);
-      channel->get_document(request);
-      
-      // Since we have to download some of it, might as well ask the core
-      // API to check all of it.
-      if (_verify_contents == P3D_VC_none) {
-        _verify_contents = P3D_VC_normal;
-      }
-      
-      // First, download it to a temporary file.
-      Filename tempfile = Filename::temporary("", "p3d_");
-      if (!channel->download_to_file(tempfile)) {
-        cerr << "Unable to download " << url << "\n";
-        
-        // Couldn't download, but try to read the existing contents.xml
-        // file anyway.  Maybe it's good enough.
-        success = read_contents_file(contents_filename, false);
-        
-      } else {
-        // Successfully downloaded; read it and move it into place.
-        success = read_contents_file(tempfile, true);
-      }
+  // Now that we've downloaded the contents file successfully, start
+  // the Core API.
+  if (!get_core_api()) {
+      // We failed.  Make sure contents.xml is up-to-date and try again.
+    if (!is_fresh && download_contents_file(contents_filename) && get_core_api()) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  return true;
+}
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Panda3D::download_contents_file
+//       Access: Protected
+//  Description: Redownloads the contents.xml file from the named
+//               URL without first checking if it is up to date.
+//               Returns true if we have a contents.xml file that
+//               might be usable, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool Panda3D::
+download_contents_file(const Filename &contents_filename) {
+  bool success = false;
+  HTTPClient *http = HTTPClient::get_global_ptr();
+
+  // Try the super_mirror first.
+  if (!_super_mirror_url_prefix.empty()) {
+    // We don't bother putting a uniquifying query string when we're
+    // downloading this file from the super_mirror.  The super_mirror
+    // is by definition a cache, so it doesn't make sense to bust
+    // caches here.
+    string url = _super_mirror_url_prefix + "contents.xml";
+    PT(HTTPChannel) channel = http->make_channel(false);
+    channel->get_document(url);
+
+    Filename tempfile = Filename::temporary("", "p3d_");
+    if (!channel->download_to_file(tempfile)) {
+      cerr << "Unable to download " << url << "\n";
+      tempfile.unlink();
+    } else {
+      // Successfully downloaded from the super_mirror; try to read it.
+      success = read_contents_file(tempfile, true);
       tempfile.unlink();
       tempfile.unlink();
     }
     }
   }
   }
 
 
-  if (success) {
-    // Now that we've downloaded the contents file successfully, start
-    // the Core API.
-    success = get_core_api();
+  if (!success) {
+    // Go download contents.xml from the actual host.
+    ostringstream strm;
+    strm << _host_url_prefix << "contents.xml";
+    // Append a uniquifying query string to the URL to force the
+    // download to go all the way through any caches.  We use the time
+    // in seconds; that's unique enough.
+    strm << "?" << time(NULL);
+    string url = strm.str();
+
+    // We might as well explicitly request the cache to be disabled too,
+    // since we have an interface for that via HTTPChannel.
+    DocumentSpec request(url);
+    request.set_cache_control(DocumentSpec::CC_no_cache);
+
+    PT(HTTPChannel) channel = http->make_channel(false);
+    channel->get_document(request);
+
+    // Since we have to download some of it, might as well ask the core
+    // API to check all of it.
+    if (_verify_contents == P3D_VC_none) {
+      _verify_contents = P3D_VC_normal;
+    }
+
+    // First, download it to a temporary file.
+    Filename tempfile = Filename::temporary("", "p3d_");
+    if (!channel->download_to_file(tempfile)) {
+      cerr << "Unable to download " << url << "\n";
+
+      // Couldn't download, but try to read the existing contents.xml
+      // file anyway.  Maybe it's good enough.
+      success = read_contents_file(contents_filename, false);
+
+    } else {
+      // Successfully downloaded; read it and move it into place.
+      success = read_contents_file(tempfile, true);
+    }
+
+    tempfile.unlink();
   }
   }
 
 
   return success;
   return success;
@@ -835,7 +861,6 @@ download_core_api() {
   }
   }
 
 
   if (!success) {
   if (!success) {
-    cerr << "Couldn't download core API.\n";
     return false;
     return false;
   }
   }
 
 

+ 1 - 0
direct/src/plugin_standalone/panda3d.h

@@ -42,6 +42,7 @@ public:
 protected:
 protected:
   bool post_arg_processing();
   bool post_arg_processing();
   bool get_plugin();
   bool get_plugin();
+  bool download_contents_file(const Filename &contents_filename);
   bool read_contents_file(const Filename &contents_filename, bool fresh_download);
   bool read_contents_file(const Filename &contents_filename, bool fresh_download);
   void find_host(TiXmlElement *xcontents);
   void find_host(TiXmlElement *xcontents);
   void read_xhost(TiXmlElement *xhost);
   void read_xhost(TiXmlElement *xhost);