splash window
This commit is contained in:
parent
8ae0185678
commit
f38724aa92
|
|
@ -77,7 +77,7 @@ receive_data(const unsigned char *this_data, size_t this_data_size) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DDownload::download_finished
|
||||
// Function: P3DFileDownload::download_finished
|
||||
// Access: Protected, Virtual
|
||||
// Description: Intended to be overloaded to generate a callback
|
||||
// when the download finishes, either successfully or
|
||||
|
|
|
|||
|
|
@ -76,6 +76,24 @@ lookup_token(const string &keyword) const {
|
|||
return string();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DFileParams::has_token
|
||||
// Access: Public
|
||||
// Description: Returns true if the named token appears in the list,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DFileParams::
|
||||
has_token(const string &keyword) const {
|
||||
Tokens::const_iterator ti;
|
||||
for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
|
||||
if ((*ti)._keyword == keyword) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DFileParams::make_xml
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public:
|
|||
|
||||
inline const string &get_p3d_filename() const;
|
||||
string lookup_token(const string &keyword) const;
|
||||
bool has_token(const string &keyword) const;
|
||||
|
||||
TiXmlElement *make_xml();
|
||||
|
||||
|
|
|
|||
|
|
@ -113,16 +113,9 @@ set_fparams(const P3DFileParams &fparams) {
|
|||
// Maybe create the splash window.
|
||||
if (!_instance_window_opened && _got_wparams) {
|
||||
if (_splash_window == NULL) {
|
||||
_splash_window = new SplashWindowType(this);
|
||||
// _splash_window->set_image_filename("c:/Documents and Settings/drose/Desktop/pandalogo.jpg");
|
||||
make_splash_window();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
string splash_image_url = _fparams.lookup_token("splash_img");
|
||||
if (!splash_image_url.is_empty()) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -140,8 +133,7 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
// Update or create the splash window.
|
||||
if (!_instance_window_opened && _got_fparams) {
|
||||
if (_splash_window == NULL) {
|
||||
_splash_window = new SplashWindowType(this);
|
||||
// _splash_window->set_image_filename("c:/Documents and Settings/drose/Desktop/pandalogo.jpg");
|
||||
make_splash_window();
|
||||
} else {
|
||||
_splash_window->set_wparams(_wparams);
|
||||
}
|
||||
|
|
@ -427,6 +419,48 @@ make_xml() {
|
|||
return xinstance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::make_splash_window
|
||||
// Access: Private
|
||||
// Description: Creates the splash window to be displayed at startup.
|
||||
// This method is called as soon as we have received
|
||||
// both _fparams and _wparams.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
make_splash_window() {
|
||||
assert(_splash_window == NULL);
|
||||
|
||||
_splash_window = new SplashWindowType(this);
|
||||
|
||||
string splash_image_url = _fparams.lookup_token("splash_img");
|
||||
if (!_fparams.has_token("splash_img")) {
|
||||
// No specific splash image is specified; get the default splash
|
||||
// image.
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
splash_image_url = inst_mgr->get_download_url();
|
||||
splash_image_url += "coreapi/splash.jpg";
|
||||
}
|
||||
|
||||
if (splash_image_url.empty()) {
|
||||
// No splash image. Never mind.
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a temporary file to receive the splash image.
|
||||
char *name = tempnam(NULL, "p3d_");
|
||||
string filename = name;
|
||||
free(name);
|
||||
|
||||
nout << "Downloading splash image into " << filename << "\n";
|
||||
|
||||
// Start downloading the requested splash image.
|
||||
SplashDownload *download = new SplashDownload(this);
|
||||
download->set_url(splash_image_url);
|
||||
download->set_filename(filename);
|
||||
|
||||
start_download(download);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::install_progress
|
||||
// Access: Private
|
||||
|
|
@ -439,3 +473,34 @@ install_progress(P3DPackage *package, double progress) {
|
|||
_splash_window->set_install_progress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::SplashDownload::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DInstance::SplashDownload::
|
||||
SplashDownload(P3DInstance *inst) :
|
||||
_inst(inst)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::SplashDownload::download_finished
|
||||
// Access: Protected, Virtual
|
||||
// Description: Intended to be overloaded to generate a callback
|
||||
// when the download finishes, either successfully or
|
||||
// otherwise. The bool parameter is true if the
|
||||
// download was successful.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::SplashDownload::
|
||||
download_finished(bool success) {
|
||||
P3DFileDownload::download_finished(success);
|
||||
if (success) {
|
||||
// We've successfully downloaded the splash image. Put it
|
||||
// onscreen if our splash window still exists.
|
||||
if (_inst->_splash_window != NULL) {
|
||||
_inst->_splash_window->set_image_filename(get_filename(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,18 @@ public:
|
|||
TiXmlElement *make_xml();
|
||||
|
||||
private:
|
||||
class SplashDownload : public P3DFileDownload {
|
||||
public:
|
||||
SplashDownload(P3DInstance *inst);
|
||||
|
||||
protected:
|
||||
virtual void download_finished(bool success);
|
||||
|
||||
private:
|
||||
P3DInstance *_inst;
|
||||
};
|
||||
|
||||
void make_splash_window();
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
||||
P3D_request_ready_func *_func;
|
||||
|
|
@ -105,6 +117,7 @@ private:
|
|||
static int _next_instance_id;
|
||||
|
||||
friend class P3DSession;
|
||||
friend class SplashDownload;
|
||||
};
|
||||
|
||||
#include "p3dInstance.I"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
//#include <fcntl.h>
|
||||
|
||||
// The relative breakdown of the full install process. Each phase is
|
||||
// worth this fraction of the total movement of the progress bar.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,31 @@
|
|||
|
||||
#include "p3dSplashWindow.h"
|
||||
|
||||
|
||||
// Stuff to use libjpeg.
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub;
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr *my_error_ptr;
|
||||
|
||||
METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
|
||||
// cinfo->err really points to a my_error_mgr struct, so coerce pointer
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
// Return control to the setjmp point
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -54,10 +79,16 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
// Function: P3DSplashWindow::set_image_filename
|
||||
// Access: Public, Virtual
|
||||
// Description: Specifies the name of a JPEG image file that is
|
||||
// displayed in the center of the splash window.
|
||||
// displayed in the center of the splash window. If
|
||||
// image_filename_temp is true, the file is immediately
|
||||
// deleted after it has been read.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_image_filename(const string &image_filename) {
|
||||
set_image_filename(const string &image_filename,
|
||||
bool image_filename_temp) {
|
||||
if (image_filename_temp) {
|
||||
unlink(image_filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -79,3 +110,107 @@ void P3DSplashWindow::
|
|||
set_install_progress(double install_progress) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::read_image
|
||||
// Access: Protected
|
||||
// Description: Reads the image filename and sets image parameters
|
||||
// height, width, num_channels, row_stride, and data.
|
||||
// Returns true on success, false on failure. If
|
||||
// image_filename_temp is true, the file will be deleted
|
||||
// after reading.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DSplashWindow::
|
||||
read_image(const string &image_filename, bool image_filename_temp,
|
||||
int &height, int &width, int &num_channels, int &row_stride,
|
||||
string &data) {
|
||||
height = 0;
|
||||
width = 0;
|
||||
num_channels = 0;
|
||||
row_stride = 0;
|
||||
data.clear();
|
||||
|
||||
// We currently only support JPEG images. Maybe that's all we'll
|
||||
// ever support.
|
||||
FILE *fp = fopen(image_filename.c_str(), "rb");
|
||||
if (fp == NULL) {
|
||||
nout << "Couldn't open splash file image: " << image_filename << "\n"
|
||||
<< flush;
|
||||
if (image_filename_temp) {
|
||||
unlink(image_filename.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// We set up the normal JPEG error routines, then override error_exit.
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
struct my_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
|
||||
JSAMPLE *buffer = NULL;
|
||||
|
||||
// Establish the setjmp return context for my_error_exit to use
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
// If we get here, the JPEG code has signaled an error.
|
||||
nout << "JPEG error decoding " << image_filename << "\n"
|
||||
<< flush;
|
||||
|
||||
// We need to clean up the JPEG object, close the input file, and return.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
|
||||
if (buffer != NULL) {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
if (image_filename_temp) {
|
||||
unlink(image_filename.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_stdio_src(&cinfo, fp);
|
||||
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
cinfo.scale_num = 1;
|
||||
cinfo.scale_denom = 1;
|
||||
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
width = cinfo.output_width;
|
||||
height = cinfo.output_height;
|
||||
num_channels = cinfo.output_components;
|
||||
|
||||
row_stride = width * num_channels;
|
||||
|
||||
// We'll pad row_stride out to word alignment. Windows requires this.
|
||||
row_stride = 4 * ((row_stride + 3) / 4);
|
||||
|
||||
size_t buffer_size = height * row_stride;
|
||||
buffer = new JSAMPLE[buffer_size];
|
||||
JSAMPLE *buffer_end = buffer + buffer_size;
|
||||
|
||||
JSAMPLE *rowptr = buffer;
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
assert(rowptr + row_stride <= buffer_end);
|
||||
jpeg_read_scanlines(&cinfo, &rowptr, 1);
|
||||
rowptr += row_stride;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
fclose(fp);
|
||||
if (image_filename_temp) {
|
||||
unlink(image_filename.c_str());
|
||||
}
|
||||
|
||||
data.append((const char *)buffer, buffer_size);
|
||||
delete[] buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,10 +42,18 @@ public:
|
|||
virtual void set_wparams(const P3DWindowParams &wparams);
|
||||
inline const P3DWindowParams &get_wparams() const;
|
||||
|
||||
virtual void set_image_filename(const string &image_filename);
|
||||
virtual void set_image_filename(const string &image_filename,
|
||||
bool image_filename_temp);
|
||||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress);
|
||||
|
||||
void setup_splash_image();
|
||||
|
||||
protected:
|
||||
bool read_image(const string &image_filename, bool image_filename_temp,
|
||||
int &height, int &width, int &num_channels, int &row_stride,
|
||||
string &data);
|
||||
|
||||
protected:
|
||||
P3DInstance *_inst;
|
||||
P3DFileParams _fparams;
|
||||
|
|
|
|||
|
|
@ -16,31 +16,6 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
// Stuff to use libjpeg.
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub;
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr *my_error_ptr;
|
||||
|
||||
METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
|
||||
// cinfo->err really points to a my_error_mgr struct, so coerce pointer
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
// Return control to the setjmp point
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -59,6 +34,7 @@ P3DWinSplashWindow(P3DInstance *inst) :
|
|||
_thread_running = false;
|
||||
_got_install = false;
|
||||
_image_filename_changed = false;
|
||||
_image_filename_temp = false;
|
||||
_install_label_changed = false;
|
||||
_install_progress = 0.0;
|
||||
|
||||
|
|
@ -82,14 +58,17 @@ P3DWinSplashWindow::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::set_image_filename
|
||||
// Access: Public, Virtual
|
||||
// Description: Specifies the name of a JPEG image file that is
|
||||
// displayed in the center of the splash window.
|
||||
// displayed in the center of the splash window. If
|
||||
// image_filename_temp is true, the file is immediately
|
||||
// deleted after it has been read.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
set_image_filename(const string &image_filename) {
|
||||
set_image_filename(const string &image_filename,
|
||||
bool image_filename_temp) {
|
||||
ACQUIRE_LOCK(_install_lock);
|
||||
if (_image_filename != image_filename) {
|
||||
_image_filename = image_filename;
|
||||
_image_filename_temp = image_filename_temp;
|
||||
_image_filename_changed = true;
|
||||
}
|
||||
RELEASE_LOCK(_install_lock);
|
||||
|
|
@ -209,7 +188,7 @@ thread_run() {
|
|||
ACQUIRE_LOCK(_install_lock);
|
||||
double install_progress = _install_progress;
|
||||
if (_image_filename_changed) {
|
||||
update_image_filename(_image_filename);
|
||||
update_image_filename(_image_filename, _image_filename_temp);
|
||||
}
|
||||
_image_filename_changed = false;
|
||||
if (_install_label_changed && _progress_bar != NULL) {
|
||||
|
|
@ -439,7 +418,7 @@ update_install_label(const string &install_label) {
|
|||
// sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
update_image_filename(const string &image_filename) {
|
||||
update_image_filename(const string &image_filename, bool image_filename_temp) {
|
||||
// Clear the old image.
|
||||
if (_bitmap != NULL) {
|
||||
DeleteObject(_bitmap);
|
||||
|
|
@ -450,70 +429,22 @@ update_image_filename(const string &image_filename) {
|
|||
// window.
|
||||
InvalidateRect(_hwnd, NULL, TRUE);
|
||||
|
||||
FILE *fp = fopen(image_filename.c_str(), "rb");
|
||||
if (fp == NULL) {
|
||||
nout << "Couldn't open splash file image: " << image_filename << "\n"
|
||||
<< flush;
|
||||
// Go read the image.
|
||||
string data;
|
||||
int num_channels, row_stride;
|
||||
if (!read_image(image_filename, image_filename_temp,
|
||||
_bitmap_height, _bitmap_width, num_channels, row_stride,
|
||||
data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We set up the normal JPEG error routines, then override error_exit.
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
struct my_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
|
||||
// Establish the setjmp return context for my_error_exit to use
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
// If we get here, the JPEG code has signaled an error.
|
||||
nout << "JPEG error decoding " << image_filename << "\n"
|
||||
<< flush;
|
||||
|
||||
// We need to clean up the JPEG object, close the input file, and return.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_stdio_src(&cinfo, fp);
|
||||
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
cinfo.scale_num = 1;
|
||||
cinfo.scale_denom = 1;
|
||||
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
_bitmap_width = cinfo.output_width;
|
||||
_bitmap_height = cinfo.output_height;
|
||||
|
||||
int row_stride = _bitmap_width * cinfo.output_components;
|
||||
// We have to pad row_stride out to DWORD alignment.
|
||||
row_stride = 4 * ((row_stride + 3) / 4);
|
||||
|
||||
size_t buffer_size = _bitmap_height * row_stride;
|
||||
JSAMPLE *buffer = new JSAMPLE[buffer_size];
|
||||
JSAMPLE *buffer_end = buffer + buffer_size;
|
||||
|
||||
JSAMPLE *rowptr = buffer;
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
assert(rowptr + row_stride <= buffer_end);
|
||||
jpeg_read_scanlines(&cinfo, &rowptr, 1);
|
||||
rowptr += row_stride;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// Now load the image.
|
||||
BITMAPINFOHEADER bmih;
|
||||
bmih.biSize = sizeof(bmih);
|
||||
bmih.biWidth = _bitmap_width;
|
||||
bmih.biHeight = -_bitmap_height;
|
||||
bmih.biPlanes = 1;
|
||||
bmih.biBitCount = 8 * cinfo.output_components;
|
||||
bmih.biBitCount = 8 * num_channels;
|
||||
bmih.biCompression = BI_RGB;
|
||||
bmih.biSizeImage = 0;
|
||||
bmih.biXPelsPerMeter = 0;
|
||||
|
|
@ -525,7 +456,7 @@ update_image_filename(const string &image_filename) {
|
|||
memcpy(&bmi, &bmih, sizeof(bmih));
|
||||
|
||||
HDC dc = GetDC(_hwnd);
|
||||
_bitmap = CreateDIBitmap(dc, &bmih, CBM_INIT, buffer, &bmi, 0);
|
||||
_bitmap = CreateDIBitmap(dc, &bmih, CBM_INIT, data.data(), &bmi, 0);
|
||||
ReleaseDC(_hwnd, dc);
|
||||
|
||||
nout << "Loaded splash file image: " << image_filename << "\n"
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ public:
|
|||
P3DWinSplashWindow(P3DInstance *inst);
|
||||
virtual ~P3DWinSplashWindow();
|
||||
|
||||
virtual void set_image_filename(const string &image_filename);
|
||||
virtual void set_image_filename(const string &image_filename,
|
||||
bool image_filename_temp);
|
||||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress);
|
||||
|
||||
|
|
@ -50,7 +51,8 @@ private:
|
|||
void make_window();
|
||||
void make_progress_bar();
|
||||
void update_install_label(const string &install_label);
|
||||
void update_image_filename(const string &image_filename);
|
||||
void update_image_filename(const string &image_filename,
|
||||
bool image_filename_temp);
|
||||
void close_window();
|
||||
|
||||
LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
|
@ -60,6 +62,7 @@ private:
|
|||
bool _got_install;
|
||||
bool _image_filename_changed;
|
||||
string _image_filename;
|
||||
bool _image_filename_temp;
|
||||
bool _install_label_changed;
|
||||
string _install_label;
|
||||
double _install_progress;
|
||||
|
|
|
|||
Loading…
Reference in New Issue