progress bars are back
This commit is contained in:
parent
aaa1924b60
commit
01ced75007
|
|
@ -23,11 +23,9 @@
|
|||
p3dInstanceManager.h p3dInstanceManager.I \
|
||||
p3dMultifileReader.h p3dMultifileReader.I \
|
||||
p3dPackage.h p3dPackage.I \
|
||||
p3dProgressWindow.h p3dProgressWindow.I \
|
||||
p3dSession.h p3dSession.I \
|
||||
p3dSplashWindow.h p3dSplashWindow.I \
|
||||
p3dWindowParams.h p3dWindowParams.I \
|
||||
p3dWinProgressWindow.h p3dWinProgressWindow.I \
|
||||
p3dWinSplashWindow.h p3dWinSplashWindow.I
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
|
|
@ -39,11 +37,9 @@
|
|||
p3dInstanceManager.cxx \
|
||||
p3dMultifileReader.cxx \
|
||||
p3dPackage.cxx \
|
||||
p3dProgressWindow.cxx \
|
||||
p3dSplashWindow.cxx \
|
||||
p3dSession.cxx \
|
||||
p3dWindowParams.cxx \
|
||||
p3dWinProgressWindow.cxx \
|
||||
p3dWinSplashWindow.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ P3DInstance::
|
|||
_packages.clear();
|
||||
|
||||
if (_splash_window != NULL) {
|
||||
_splash_window->close_window();
|
||||
nout << "Deleting splash window in destructor\n" << flush;
|
||||
delete _splash_window;
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
|
@ -98,9 +98,11 @@ set_fparams(const P3DFileParams &fparams) {
|
|||
_got_fparams = true;
|
||||
_fparams = fparams;
|
||||
|
||||
// Update the splash window.
|
||||
if (_splash_window != NULL) {
|
||||
_splash_window->set_fparams(_fparams);
|
||||
// Maybe create the splash window.
|
||||
if (!_instance_window_opened && _got_wparams) {
|
||||
if (_splash_window == NULL) {
|
||||
_splash_window = new SplashWindowType(this);
|
||||
}
|
||||
}
|
||||
|
||||
// This also sets up some internal data based on the contents of the
|
||||
|
|
@ -128,10 +130,9 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
_wparams = wparams;
|
||||
|
||||
// Update or create the splash window.
|
||||
if (!_instance_window_opened) {
|
||||
if (!_instance_window_opened && _got_fparams) {
|
||||
if (_splash_window == NULL) {
|
||||
_splash_window = new SplashWindowType(this);
|
||||
_splash_window->open_window();
|
||||
} else {
|
||||
_splash_window->set_wparams(_wparams);
|
||||
}
|
||||
|
|
@ -238,7 +239,7 @@ get_request() {
|
|||
nout << "Instance " << this << " got window_opened\n" << flush;
|
||||
_instance_window_opened = true;
|
||||
if (_splash_window != NULL) {
|
||||
_splash_window->close_window();
|
||||
nout << "Deleting splash window\n" << flush;
|
||||
delete _splash_window;
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
|
@ -257,6 +258,8 @@ get_request() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
add_request(P3D_request *request) {
|
||||
nout << "Instance " << this << " add_request(" << request->_request_type
|
||||
<< ")\n" << flush;
|
||||
request->_instance = this;
|
||||
|
||||
ACQUIRE_LOCK(_request_lock);
|
||||
|
|
@ -414,3 +417,16 @@ make_xml() {
|
|||
|
||||
return xinstance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::install_progress
|
||||
// Access: Private
|
||||
// Description: Notified as the _panda3d package is downloaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
install_progress(P3DPackage *package, double progress) {
|
||||
if (_splash_window != NULL) {
|
||||
_splash_window->set_install_label("Installing Panda3D");
|
||||
_splash_window->set_install_progress(progress);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ public:
|
|||
inline bool is_started() const;
|
||||
void request_stop();
|
||||
|
||||
void async_notify(const string &message);
|
||||
|
||||
TiXmlElement *make_xml();
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
|
||||
P3D_request_ready_func *_func;
|
||||
|
||||
bool _got_fparams;
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
// Filename: p3dProgressWindow.I
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Filename: p3dProgressWindow.cxx
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "p3dProgressWindow.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DProgressWindow::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DProgressWindow::
|
||||
P3DProgressWindow(P3DPackage *package, P3DSession *session,
|
||||
P3DInstance *inst) :
|
||||
_package(package),
|
||||
_session(session),
|
||||
_inst(inst)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DProgressWindow::package_ready
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DProgressWindow::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->_panda3d_callback = NULL;
|
||||
if (package == _session->_panda3d) {
|
||||
if (success) {
|
||||
_session->start_p3dpython();
|
||||
} else {
|
||||
nout << "Failed to install " << package->get_package_name()
|
||||
<< "_" << package->get_package_version() << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected panda3d package: " << package << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected callback for P3DSession\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Filename: p3dProgressWindow.h
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 P3DPROGRESSWINDOW_H
|
||||
#define P3DPROGRESSWINDOW_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
#include "p3dPackage.h"
|
||||
#include "p3dWindowParams.h"
|
||||
|
||||
class P3DInstance;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DProgressWindow
|
||||
// Description : This window is displayed temporarily, in place of an
|
||||
// instance's actual window, during the initial download
|
||||
// of the Panda3D code. When the download is finished,
|
||||
// it notifies the session.
|
||||
//
|
||||
// This is the base implementation; it contains no
|
||||
// specific code to open a window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DProgressWindow : public P3DPackage::Callback {
|
||||
public:
|
||||
P3DProgressWindow(P3DPackage *package, P3DSession *session,
|
||||
P3DInstance *inst);
|
||||
|
||||
virtual void package_ready(P3DPackage *package, bool success);
|
||||
|
||||
protected:
|
||||
P3DPackage *_package;
|
||||
P3DSession *_session;
|
||||
P3DInstance *_inst;
|
||||
|
||||
P3DWindowParams _wparams;
|
||||
};
|
||||
|
||||
#include "p3dProgressWindow.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -299,6 +299,7 @@ py_request_func(PyObject *args) {
|
|||
xrequest->SetAttribute("message", message);
|
||||
doc.LinkEndChild(decl);
|
||||
doc.LinkEndChild(xrequest);
|
||||
nout << "sending " << doc << "\n" << flush;
|
||||
_pipe_write << doc << flush;
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,20 +15,12 @@
|
|||
#include "p3dSession.h"
|
||||
#include "p3dInstance.h"
|
||||
#include "p3dInstanceManager.h"
|
||||
#include "p3dProgressWindow.h"
|
||||
#include "p3dWinProgressWindow.h"
|
||||
#include "p3d_plugin_config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef P3DWinProgressWindow ProgressWindowType;
|
||||
#else
|
||||
typedef P3DProgressWindow ProgressWindowType;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -161,23 +153,7 @@ start_instance(P3DInstance *inst) {
|
|||
} else {
|
||||
// Otherwise, set a callback, so we'll know when it is ready.
|
||||
if (_panda3d_callback == NULL) {
|
||||
|
||||
_panda3d_callback = new P3DProgressWindow(_panda3d, this, inst);
|
||||
|
||||
/*
|
||||
// The callback object will be a ProgressWindow, to show
|
||||
// visual progress to the user while we're downloading.
|
||||
if (inst->get_window_type() == P3D_WT_hidden) {
|
||||
// For a hidden window, just create an instance of the base
|
||||
// class, which manifests no actual window.
|
||||
_panda3d_callback = new P3DProgressWindow(_panda3d, this, inst);
|
||||
} else {
|
||||
// For a non-hidden window, create an instance of
|
||||
// ProgressWindowType, which is typedeffed above to be the kind
|
||||
// of class that actually does manifest a window.
|
||||
_panda3d_callback = new ProgressWindowType(_panda3d, this, inst);
|
||||
}
|
||||
*/
|
||||
_panda3d_callback = new PackageCallback(this);
|
||||
_panda3d->set_callback(_panda3d_callback);
|
||||
}
|
||||
}
|
||||
|
|
@ -234,6 +210,20 @@ send_command(TiXmlDocument *command) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::install_progress
|
||||
// Access: Private
|
||||
// Description: Notified as the _panda3d package is downloaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::
|
||||
install_progress(P3DPackage *package, double progress) {
|
||||
Instances::iterator ii;
|
||||
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
|
||||
P3DInstance *inst = (*ii).second;
|
||||
inst->install_progress(package, progress);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::start_p3dpython
|
||||
// Access: Private
|
||||
|
|
@ -712,3 +702,51 @@ posix_create_process(const string &program, const string &start_dir,
|
|||
}
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DSession::PackageCallback::
|
||||
PackageCallback(P3DSession *session) :
|
||||
_session(session)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::package_ready
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::PackageCallback::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->_panda3d_callback = NULL;
|
||||
if (package == _session->_panda3d) {
|
||||
if (success) {
|
||||
_session->start_p3dpython();
|
||||
} else {
|
||||
nout << "Failed to install " << package->get_package_name()
|
||||
<< "_" << package->get_package_version() << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected panda3d package: " << package << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected callback for P3DSession\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::install_progress
|
||||
// Access: Public, Virtual
|
||||
// Description: This callback is received during the download process
|
||||
// to inform us how much has been installed so far.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::PackageCallback::
|
||||
install_progress(P3DPackage *package, double progress) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->install_progress(package, progress);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
void send_command(TiXmlDocument *command);
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
void start_p3dpython();
|
||||
|
||||
void spawn_read_thread();
|
||||
|
|
@ -79,6 +80,17 @@ private:
|
|||
HandleStream &pipe_read, HandleStream &pipe_write);
|
||||
#endif
|
||||
|
||||
class PackageCallback : public P3DPackage::Callback {
|
||||
public:
|
||||
PackageCallback(P3DSession *session);
|
||||
|
||||
virtual void install_progress(P3DPackage *package, double progress);
|
||||
virtual void package_ready(P3DPackage *package, bool success);
|
||||
|
||||
protected:
|
||||
P3DSession *_session;
|
||||
};
|
||||
|
||||
private:
|
||||
string _session_key;
|
||||
string _python_version;
|
||||
|
|
@ -97,7 +109,7 @@ private:
|
|||
Commands _commands;
|
||||
|
||||
P3DPackage *_panda3d;
|
||||
P3DProgressWindow *_panda3d_callback;
|
||||
PackageCallback *_panda3d_callback;
|
||||
|
||||
// Members for communicating with the p3dpython child process.
|
||||
#ifdef _WIN32
|
||||
|
|
@ -119,7 +131,7 @@ private:
|
|||
pthread_t _read_thread;
|
||||
#endif
|
||||
|
||||
friend class P3DProgressWindow;
|
||||
friend class PackageCallback;
|
||||
};
|
||||
|
||||
#include "p3dSession.I"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: By the time the SplashWindow is created, the instance
|
||||
// has received both its fparams and its wparams. Copy
|
||||
// them both into this class for reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DSplashWindow::
|
||||
P3DSplashWindow(P3DInstance *inst) :
|
||||
|
|
@ -36,16 +38,6 @@ P3DSplashWindow::
|
|||
~P3DSplashWindow() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_fparams
|
||||
// Access: Public, Virtual
|
||||
// Description: Sets up the file parameters for the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
set_fparams(const P3DFileParams &fparams) {
|
||||
_fparams = fparams;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::set_wparams
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -59,21 +51,21 @@ set_wparams(const P3DWindowParams &wparams) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::open_window
|
||||
// Function: P3DSplashWindow::set_install_label
|
||||
// Access: Public, Virtual
|
||||
// Description: Creates the splash window.
|
||||
// Description: Specifies the text that is displayed above the
|
||||
// install progress bar.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
open_window() {
|
||||
nout << "P3DSplashWindow::open_window()\n" << flush;
|
||||
set_install_label(const string &install_label) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSplashWindow::close_window
|
||||
// Function: P3DSplashWindow::set_install_progress
|
||||
// Access: Public, Virtual
|
||||
// Description: Closes the window created above.
|
||||
// Description: Moves the install progress bar from 0.0 to 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSplashWindow::
|
||||
close_window() {
|
||||
nout << "P3DSplashWindow::close_window()\n" << flush;
|
||||
set_install_progress(double install_progress) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,14 +37,13 @@ public:
|
|||
P3DSplashWindow(P3DInstance *inst);
|
||||
virtual ~P3DSplashWindow();
|
||||
|
||||
virtual void set_fparams(const P3DFileParams &fparams);
|
||||
inline const P3DFileParams &get_fparams() const;
|
||||
|
||||
virtual void set_wparams(const P3DWindowParams &wparams);
|
||||
inline const P3DWindowParams &get_wparams() const;
|
||||
|
||||
virtual void open_window();
|
||||
virtual void close_window();
|
||||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress);
|
||||
|
||||
protected:
|
||||
P3DInstance *_inst;
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
// Filename: p3dWinProgressWindow.I
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,354 +0,0 @@
|
|||
// Filename: p3dWinProgressWindow.cxx
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "p3dWinProgressWindow.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DWinProgressWindow::
|
||||
P3DWinProgressWindow(P3DPackage *package, P3DSession *session,
|
||||
P3DInstance *inst) :
|
||||
P3DProgressWindow(package, session, inst)
|
||||
{
|
||||
_thread = NULL;
|
||||
_hwnd = NULL;
|
||||
_progress_bar = NULL;
|
||||
_thread_running = false;
|
||||
|
||||
INIT_LOCK(_progress_lock);
|
||||
|
||||
assert(_wparams.get_window_type() != P3D_WT_hidden);
|
||||
start_thread();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DWinProgressWindow::
|
||||
~P3DWinProgressWindow() {
|
||||
stop_thread();
|
||||
|
||||
DESTROY_LOCK(_progress_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::install_progress
|
||||
// Access: Public, Virtual
|
||||
// Description: This callback is received during the download process
|
||||
// to inform us how much has been installed so far.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
install_progress(P3DPackage *package, double progress) {
|
||||
P3DProgressWindow::install_progress(package, progress);
|
||||
|
||||
ACQUIRE_LOCK(_progress_lock);
|
||||
_progress = progress;
|
||||
RELEASE_LOCK(_progress_lock);
|
||||
|
||||
// Post a silly message to spin the message loop.
|
||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||
|
||||
if (!_thread_running) {
|
||||
_inst->request_stop();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::start_thraed
|
||||
// Access: Private
|
||||
// Description: Spawns the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
start_thread() {
|
||||
_thread_continue = true;
|
||||
_thread = CreateThread(NULL, 0, &win_thread_run, this, 0, &_thread_id);
|
||||
if (_thread != NULL) {
|
||||
_thread_running = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::stop_thraed
|
||||
// Access: Private
|
||||
// Description: Terminates and joins the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
stop_thread() {
|
||||
_thread_continue = false;
|
||||
// Post a silly message to spin the message loop.
|
||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||
|
||||
WaitForSingleObject(_thread, INFINITE);
|
||||
CloseHandle(_thread);
|
||||
_thread = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::thread_run
|
||||
// Access: Private
|
||||
// Description: The sub-thread's main run method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
thread_run() {
|
||||
make_window();
|
||||
|
||||
double last_progress = -1.0;
|
||||
|
||||
_loop_started = GetTickCount();
|
||||
MSG msg;
|
||||
int retval;
|
||||
retval = GetMessage(&msg, NULL, 0, 0);
|
||||
while (retval != 0 && _thread_continue) {
|
||||
if (retval == -1) {
|
||||
nout << "Error processing message queue.\n";
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
{
|
||||
ACQUIRE_LOCK(_progress_lock);
|
||||
double new_progress = _progress;
|
||||
RELEASE_LOCK(_progress_lock);
|
||||
|
||||
if (new_progress != last_progress) {
|
||||
if (_progress_bar == NULL) {
|
||||
// Is it time to create the progress bar?
|
||||
int now = GetTickCount();
|
||||
if (now - _loop_started > 2000) {
|
||||
make_progress_bar();
|
||||
}
|
||||
} else {
|
||||
// Update the progress bar. We do this only within the
|
||||
// thread, to ensure we don't get a race condition when
|
||||
// starting or closing the thread.
|
||||
SendMessage(_progress_bar, PBM_SETPOS, (int)(new_progress * 100.0), 0);
|
||||
|
||||
last_progress = new_progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = GetMessage(&msg, NULL, 0, 0);
|
||||
}
|
||||
|
||||
close_window();
|
||||
_thread_running = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::win_thread_run
|
||||
// Access: Private, Static
|
||||
// Description: The OS-specific thread callback function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DWORD P3DWinProgressWindow::
|
||||
win_thread_run(LPVOID data) {
|
||||
((P3DWinProgressWindow *)data)->thread_run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::make_window
|
||||
// Access: Private
|
||||
// Description: Creates the window for displaying progress. Runs
|
||||
// within the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
make_window() {
|
||||
WNDCLASS wc;
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
|
||||
static bool registered_class = false;
|
||||
if (!registered_class) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.lpfnWndProc = window_proc;
|
||||
wc.hInstance = application;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszClassName = "panda3d_progress";
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
nout << "Could not register window class!\n";
|
||||
}
|
||||
registered_class = true;
|
||||
}
|
||||
|
||||
int x = CW_USEDEFAULT;
|
||||
int y = CW_USEDEFAULT;
|
||||
if (_wparams.get_win_x() != 0 && _wparams.get_win_y() != 0) {
|
||||
x = _wparams.get_win_x();
|
||||
y = _wparams.get_win_y();
|
||||
}
|
||||
|
||||
int width = 320;
|
||||
int height = 240;
|
||||
if (_wparams.get_win_width() != 0 && _wparams.get_win_height() != 0) {
|
||||
width = _wparams.get_win_width();
|
||||
height = _wparams.get_win_height();
|
||||
}
|
||||
|
||||
if (_wparams.get_window_type() == P3D_WT_embedded) {
|
||||
// Create an embedded window.
|
||||
DWORD window_style =
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
|
||||
HWND parent_hwnd = _wparams.get_parent_window()._hwnd;
|
||||
|
||||
_hwnd =
|
||||
CreateWindow("panda3d_progress", "Panda3D", window_style,
|
||||
x, y, width, height,
|
||||
parent_hwnd, NULL, application, 0);
|
||||
|
||||
if (!_hwnd) {
|
||||
nout << "Could not create embedded window!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Create a toplevel window.
|
||||
DWORD window_style =
|
||||
WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||
WS_SIZEBOX | WS_MAXIMIZEBOX;
|
||||
|
||||
_hwnd =
|
||||
CreateWindow("panda3d_progress", "Panda3D", window_style,
|
||||
x, y, width, height,
|
||||
NULL, NULL, application, 0);
|
||||
if (!_hwnd) {
|
||||
nout << "Could not create toplevel window!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't initially show the toplevel window. We'll show it
|
||||
// when we create the actual progress bar, a few seconds later;
|
||||
// otherwise, it might be distracting if the window pops up and
|
||||
// then immediately disappears.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::make_progress_bar
|
||||
// Access: Private
|
||||
// Description: Creates the progress bar and label. Runs
|
||||
// within the sub-thread. This is done a few seconds
|
||||
// after the main window is created, to give us a chance
|
||||
// to launch quickly without bothering the user.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
make_progress_bar() {
|
||||
if (_progress_bar != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
DWORD window_style =
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(_hwnd, &rect);
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
|
||||
int bar_width = min((int)(width * 0.6), 400);
|
||||
int bar_height = min((int)(height * 0.1), 24);
|
||||
int bar_x = (width - bar_width) / 2;
|
||||
int bar_y = (height - bar_height) / 2;
|
||||
|
||||
_progress_bar =
|
||||
CreateWindowEx(0, PROGRESS_CLASS, "", window_style,
|
||||
bar_x, bar_y, bar_width, bar_height,
|
||||
_hwnd, NULL, application, 0);
|
||||
|
||||
// Create a static text label. What a major pain *this* is.
|
||||
string text_string = "Installing " + _package->get_package_display_name();
|
||||
const char *text = text_string.c_str();
|
||||
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
||||
|
||||
HDC dc = GetDC(_hwnd);
|
||||
SelectObject(dc, font);
|
||||
SIZE text_size;
|
||||
GetTextExtentPoint32(dc, text, strlen(text), &text_size);
|
||||
ReleaseDC(_hwnd, dc);
|
||||
|
||||
int text_width = text_size.cx;
|
||||
int text_height = text_size.cy;
|
||||
int text_x = (width - text_width) / 2;
|
||||
int text_y = bar_y - text_height - 2;
|
||||
|
||||
CreateWindowEx(0, "STATIC", text, SS_OWNERDRAW | window_style,
|
||||
text_x, text_y, text_width, text_height,
|
||||
_hwnd, NULL, application, 0);
|
||||
|
||||
// Ensure the main window is visible now.
|
||||
ShowWindow(_hwnd, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::close_window
|
||||
// Access: Private
|
||||
// Description: Closes the window created above.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinProgressWindow::
|
||||
close_window() {
|
||||
if (_hwnd) {
|
||||
ShowWindow(_hwnd, SW_HIDE);
|
||||
CloseWindow(_hwnd);
|
||||
_hwnd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinProgressWindow::window_proc
|
||||
// Access: Private, Static
|
||||
// Description: The windows event-processing handler.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LONG P3DWinProgressWindow::
|
||||
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch (msg) {
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_DRAWITEM:
|
||||
{
|
||||
DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
|
||||
FillRect(dis->hDC, &(dis->rcItem), WHITE_BRUSH);
|
||||
|
||||
static const int text_buffer_size = 512;
|
||||
char text_buffer[text_buffer_size];
|
||||
GetWindowText(dis->hwndItem, text_buffer, text_buffer_size);
|
||||
|
||||
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
||||
SelectObject(dis->hDC, font);
|
||||
SetBkColor(dis->hDC, 0x00ffffff);
|
||||
|
||||
DrawText(dis->hDC, text_buffer, -1, &(dis->rcItem),
|
||||
DT_BOTTOM | DT_CENTER | DT_SINGLELINE);
|
||||
}
|
||||
};
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
// Filename: p3dWinProgressWindow.h
|
||||
// Created by: drose (17Jun09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 P3DWINPROGRESSWINDOW_H
|
||||
#define P3DWINPROGRESSWINDOW_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "p3dProgressWindow.h"
|
||||
#include "p3d_lock.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DWinProgressWindow
|
||||
// Description : This is the Windows implementation of the
|
||||
// initial-download window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DWinProgressWindow : public P3DProgressWindow {
|
||||
public:
|
||||
P3DWinProgressWindow(P3DPackage *package, P3DSession *session, P3DInstance *inst);
|
||||
virtual ~P3DWinProgressWindow();
|
||||
|
||||
protected:
|
||||
virtual void install_progress(P3DPackage *package, double progress);
|
||||
|
||||
private:
|
||||
void start_thread();
|
||||
void stop_thread();
|
||||
|
||||
private:
|
||||
// These methods run only within the window thread.
|
||||
void thread_run();
|
||||
static DWORD WINAPI win_thread_run(LPVOID data);
|
||||
|
||||
void make_window();
|
||||
void make_progress_bar();
|
||||
void close_window();
|
||||
|
||||
static LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
private:
|
||||
double _progress;
|
||||
LOCK _progress_lock;
|
||||
int _loop_started;
|
||||
|
||||
bool _thread_continue;
|
||||
bool _thread_running;
|
||||
HANDLE _thread;
|
||||
DWORD _thread_id;
|
||||
HWND _hwnd;
|
||||
HWND _progress_bar;
|
||||
};
|
||||
|
||||
#include "p3dWinProgressWindow.I"
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif
|
||||
|
|
@ -25,7 +25,19 @@ P3DWinSplashWindow::
|
|||
P3DWinSplashWindow(P3DInstance *inst) :
|
||||
P3DSplashWindow(inst)
|
||||
{
|
||||
_thread = NULL;
|
||||
_thread_id = 0;
|
||||
_hwnd = NULL;
|
||||
_progress_bar = NULL;
|
||||
_text_label = NULL;
|
||||
_thread_running = false;
|
||||
_got_install = false;
|
||||
_install_progress = 0.0;
|
||||
_install_label_changed = false;
|
||||
|
||||
INIT_LOCK(_install_lock);
|
||||
|
||||
start_thread();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -35,17 +47,165 @@ P3DWinSplashWindow(P3DInstance *inst) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
P3DWinSplashWindow::
|
||||
~P3DWinSplashWindow() {
|
||||
close_window();
|
||||
stop_thread();
|
||||
|
||||
DESTROY_LOCK(_install_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::open_window
|
||||
// Function: P3DWinSplashWindow::set_install_label
|
||||
// Access: Public, Virtual
|
||||
// Description: Creates the splash window.
|
||||
// Description: Specifies the text that is displayed above the
|
||||
// install progress bar.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
open_window() {
|
||||
P3DSplashWindow::open_window();
|
||||
set_install_label(const string &install_label) {
|
||||
ACQUIRE_LOCK(_install_lock);
|
||||
if (_install_label != install_label) {
|
||||
_install_label = install_label;
|
||||
_install_label_changed = true;
|
||||
}
|
||||
RELEASE_LOCK(_install_lock);
|
||||
|
||||
// Post a silly message to spin the message loop.
|
||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||
|
||||
if (!_thread_running && _thread_continue) {
|
||||
// The user must have closed the window. Let's shut down the
|
||||
// instance, too.
|
||||
_inst->request_stop();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::set_install_progress
|
||||
// Access: Public, Virtual
|
||||
// Description: Moves the install progress bar from 0.0 to 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
set_install_progress(double install_progress) {
|
||||
_got_install = true;
|
||||
|
||||
ACQUIRE_LOCK(_install_lock);
|
||||
_install_progress = install_progress;
|
||||
RELEASE_LOCK(_install_lock);
|
||||
|
||||
// Post a silly message to spin the message loop.
|
||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||
|
||||
if (!_thread_running && _thread_continue) {
|
||||
// The user must have closed the window. Let's shut down the
|
||||
// instance, too.
|
||||
_inst->request_stop();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::start_thraed
|
||||
// Access: Private
|
||||
// Description: Spawns the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
start_thread() {
|
||||
_thread_continue = true;
|
||||
_thread = CreateThread(NULL, 0, &win_thread_run, this, 0, &_thread_id);
|
||||
if (_thread != NULL) {
|
||||
_thread_running = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::stop_thraed
|
||||
// Access: Private
|
||||
// Description: Terminates and joins the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
stop_thread() {
|
||||
_thread_continue = false;
|
||||
// Post a silly message to spin the message loop.
|
||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||
|
||||
WaitForSingleObject(_thread, INFINITE);
|
||||
CloseHandle(_thread);
|
||||
_thread = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::thread_run
|
||||
// Access: Private
|
||||
// Description: The sub-thread's main run method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
thread_run() {
|
||||
make_window();
|
||||
|
||||
double last_progress = -1.0;
|
||||
|
||||
_loop_started = GetTickCount();
|
||||
MSG msg;
|
||||
int retval;
|
||||
retval = GetMessage(&msg, NULL, 0, 0);
|
||||
while (retval != 0 && _thread_continue) {
|
||||
if (retval == -1) {
|
||||
nout << "Error processing message queue.\n";
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
if (_got_install) {
|
||||
ACQUIRE_LOCK(_install_lock);
|
||||
double install_progress = _install_progress;
|
||||
if (_install_label_changed && _progress_bar != NULL) {
|
||||
update_install_label(_install_label);
|
||||
}
|
||||
_install_label_changed = false;
|
||||
RELEASE_LOCK(_install_lock);
|
||||
|
||||
if (install_progress != last_progress) {
|
||||
if (_progress_bar == NULL) {
|
||||
// Is it time to create the progress bar?
|
||||
int now = GetTickCount();
|
||||
if (now - _loop_started > 2000) {
|
||||
make_progress_bar();
|
||||
}
|
||||
} else {
|
||||
// Update the progress bar. We do this only within the
|
||||
// thread, to ensure we don't get a race condition when
|
||||
// starting or closing the thread.
|
||||
SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0);
|
||||
|
||||
last_progress = install_progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = GetMessage(&msg, NULL, 0, 0);
|
||||
}
|
||||
|
||||
close_window();
|
||||
_thread_running = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::win_thread_run
|
||||
// Access: Private, Static
|
||||
// Description: The OS-specific thread callback function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DWORD P3DWinSplashWindow::
|
||||
win_thread_run(LPVOID data) {
|
||||
((P3DWinSplashWindow *)data)->thread_run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::make_window
|
||||
// Access: Private
|
||||
// Description: Creates the window for displaying progress. Runs
|
||||
// within the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
make_window() {
|
||||
WNDCLASS wc;
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
|
|
@ -55,7 +215,7 @@ open_window() {
|
|||
ZeroMemory(&wc, sizeof(WNDCLASS));
|
||||
wc.lpfnWndProc = window_proc;
|
||||
wc.hInstance = application;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszClassName = "panda3d_splash";
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
|
|
@ -110,21 +270,117 @@ open_window() {
|
|||
nout << "Could not create toplevel window!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
ShowWindow(_hwnd, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the main window is visible now.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::make_progress_bar
|
||||
// Access: Private
|
||||
// Description: Creates the progress bar and label. Runs
|
||||
// within the sub-thread. This is done a few seconds
|
||||
// after the main window is created, to give us a chance
|
||||
// to launch quickly without bothering the user.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
make_progress_bar() {
|
||||
if (_progress_bar != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ACQUIRE_LOCK(_install_lock);
|
||||
string install_label = _install_label;
|
||||
double install_progress = _install_progress;
|
||||
_install_label_changed = false;
|
||||
RELEASE_LOCK(_install_lock);
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
DWORD window_style =
|
||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(_hwnd, &rect);
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
|
||||
int bar_width = min((int)(width * 0.6), 400);
|
||||
int bar_height = min((int)(height * 0.1), 24);
|
||||
int bar_x = (width - bar_width) / 2;
|
||||
int bar_y = (height - bar_height) / 2;
|
||||
|
||||
_progress_bar =
|
||||
CreateWindowEx(0, PROGRESS_CLASS, "", window_style,
|
||||
bar_x, bar_y, bar_width, bar_height,
|
||||
_hwnd, NULL, application, 0);
|
||||
SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0);
|
||||
ShowWindow(_progress_bar, SW_SHOWNORMAL);
|
||||
|
||||
update_install_label(install_label);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::update_install_label
|
||||
// Access: Private
|
||||
// Description: Changes the text on the install label. Runs within
|
||||
// the sub-thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
update_install_label(const string &install_label) {
|
||||
assert(_progress_bar != NULL);
|
||||
|
||||
if (_text_label != NULL) {
|
||||
DestroyWindow(_text_label);
|
||||
_text_label = NULL;
|
||||
}
|
||||
|
||||
if (install_label.empty()) {
|
||||
// Trivial case.
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a static text label. What a major pain *this* is.
|
||||
|
||||
const char *text = install_label.c_str();
|
||||
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
||||
|
||||
HDC dc = GetDC(_hwnd);
|
||||
SelectObject(dc, font);
|
||||
SIZE text_size;
|
||||
GetTextExtentPoint32(dc, text, strlen(text), &text_size);
|
||||
ReleaseDC(_hwnd, dc);
|
||||
|
||||
HINSTANCE application = GetModuleHandle(NULL);
|
||||
DWORD window_style =
|
||||
SS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(_hwnd, &rect);
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
|
||||
int bar_height = min((int)(height * 0.1), 24);
|
||||
int bar_y = (height - bar_height) / 2;
|
||||
|
||||
int text_width = text_size.cx;
|
||||
int text_height = text_size.cy;
|
||||
int text_x = (width - text_width) / 2;
|
||||
int text_y = bar_y - text_height - 2;
|
||||
|
||||
_text_label = CreateWindowEx(0, "STATIC", text, window_style,
|
||||
text_x, text_y, text_width, text_height,
|
||||
_hwnd, NULL, application, 0);
|
||||
ShowWindow(_text_label, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWinSplashWindow::close_window
|
||||
// Access: Public, Virtual
|
||||
// Access: Private
|
||||
// Description: Closes the window created above.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DWinSplashWindow::
|
||||
close_window() {
|
||||
P3DSplashWindow::close_window();
|
||||
if (_hwnd) {
|
||||
ShowWindow(_hwnd, SW_HIDE);
|
||||
CloseWindow(_hwnd);
|
||||
|
|
|
|||
|
|
@ -34,14 +34,41 @@ public:
|
|||
P3DWinSplashWindow(P3DInstance *inst);
|
||||
virtual ~P3DWinSplashWindow();
|
||||
|
||||
virtual void open_window();
|
||||
virtual void close_window();
|
||||
virtual void set_install_label(const string &install_label);
|
||||
virtual void set_install_progress(double install_progress);
|
||||
|
||||
private:
|
||||
void start_thread();
|
||||
void stop_thread();
|
||||
|
||||
private:
|
||||
// These methods run only within the window thread.
|
||||
void thread_run();
|
||||
static DWORD WINAPI win_thread_run(LPVOID data);
|
||||
|
||||
void make_window();
|
||||
void make_progress_bar();
|
||||
void update_install_label(const string &install_label);
|
||||
void close_window();
|
||||
|
||||
static LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
private:
|
||||
bool _got_install;
|
||||
bool _install_label_changed;
|
||||
string _install_label;
|
||||
double _install_progress;
|
||||
LOCK _install_lock;
|
||||
|
||||
int _loop_started;
|
||||
|
||||
bool _thread_continue;
|
||||
bool _thread_running;
|
||||
HANDLE _thread;
|
||||
DWORD _thread_id;
|
||||
HWND _hwnd;
|
||||
HWND _progress_bar;
|
||||
HWND _text_label;
|
||||
};
|
||||
|
||||
#include "p3dWinSplashWindow.I"
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
#include "p3dInstanceManager.cxx"
|
||||
#include "p3dMultifileReader.cxx"
|
||||
#include "p3dPackage.cxx"
|
||||
#include "p3dProgressWindow.cxx"
|
||||
#include "p3dSplashWindow.cxx"
|
||||
#include "p3dSession.cxx"
|
||||
#include "p3dWindowParams.cxx"
|
||||
#include "p3dWinProgressWindow.cxx"
|
||||
#include "p3dWinSplashWindow.cxx"
|
||||
|
|
|
|||
|
|
@ -334,8 +334,9 @@ stream_as_file(NPStream *stream, const char *fname) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void PPInstance::
|
||||
handle_request(P3D_request *request) {
|
||||
logfile << "handle_request: " << request << ", " << request->_instance
|
||||
<< " within " << this << ", " << _p3d_inst << "\n" << flush;
|
||||
logfile
|
||||
<< "handle_request: " << request << ", " << request->_request_type
|
||||
<< " within " << this << "\n" << flush;
|
||||
assert(request->_instance == _p3d_inst);
|
||||
|
||||
bool handled = false;
|
||||
|
|
@ -428,7 +429,13 @@ send_window() {
|
|||
|
||||
P3D_window_handle parent_window;
|
||||
#ifdef _WIN32
|
||||
parent_window._hwnd = (HWND)(_window.window);
|
||||
if (_window.type == NPWindowTypeWindow) {
|
||||
parent_window._hwnd = (HWND)(_window.window);
|
||||
} else {
|
||||
// Hmm, it's just a drawable; but we didn't ask for a windowless
|
||||
// plugin.
|
||||
parent_window._hwnd = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actually, we set up the window starting at (0, 0), instead of
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ open_logfile() {
|
|||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
UINT _timer = 0;
|
||||
DWORD main_thread_id = 0;
|
||||
#endif
|
||||
LOCK _timer_lock;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: handle_request_loop
|
||||
|
|
@ -45,44 +45,45 @@ LOCK _timer_lock;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
handle_request_loop() {
|
||||
assert(is_plugin_loaded());
|
||||
if (!is_plugin_loaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
logfile << "about to call P3D_check_request()\n" << flush;
|
||||
P3D_instance *p3d_inst = P3D_check_request(false);
|
||||
logfile << "P3D_check_request() returns " << p3d_inst << "\n" << flush;
|
||||
while (p3d_inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(p3d_inst);
|
||||
logfile << "got request " << request << "\n";
|
||||
if (request != (P3D_request *)NULL) {
|
||||
PPInstance *inst = (PPInstance *)(p3d_inst->_user_data);
|
||||
assert(inst != NULL);
|
||||
inst->handle_request(request);
|
||||
}
|
||||
p3d_inst = P3D_check_request(false);
|
||||
logfile << "P3D_check_request() returns " << p3d_inst << "\n" << flush;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: win_timer_func
|
||||
// Description: The Windows flavor of the timer callback function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef _WIN32
|
||||
static VOID CALLBACK
|
||||
win_timer_func(HWND hwnd, UINT msg, UINT_PTR event, DWORD time) {
|
||||
ACQUIRE_LOCK(_timer_lock);
|
||||
logfile
|
||||
<< "win_timer_func " << hwnd << ", " << msg << ", " << event
|
||||
<< ", " << time << "\n"
|
||||
<< "timer thread = " << GetCurrentThreadId() << "\n"
|
||||
<< flush;
|
||||
KillTimer(NULL, _timer);
|
||||
_timer = 0;
|
||||
RELEASE_LOCK(_timer_lock);
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: window_proc
|
||||
// Description: We bind this function to the parent windows we are
|
||||
// given in NPP_New(), so we can spin the request_loop
|
||||
// when needed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static LONG
|
||||
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
// If this is a toplevel window event, but not something caused as a
|
||||
// result of something done by handle_request_loop(), then call
|
||||
// handle_request_loop() to see if there are any new requests to be
|
||||
// forwarded to the main thread.
|
||||
static int recursion_protect = 0;
|
||||
++recursion_protect;
|
||||
if (recursion_protect == 1) {
|
||||
handle_request_loop();
|
||||
}
|
||||
--recursion_protect;
|
||||
|
||||
handle_request_loop();
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
#endif // _WIN32
|
||||
#endif // _WIN32
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: request_ready
|
||||
|
|
@ -94,20 +95,15 @@ win_timer_func(HWND hwnd, UINT msg, UINT_PTR event, DWORD time) {
|
|||
void
|
||||
request_ready(P3D_instance *instance) {
|
||||
logfile
|
||||
<< "request_ready"
|
||||
// << " thread = " << GetCurrentThreadId()
|
||||
<< "request_ready in " << instance
|
||||
<< " thread = " << GetCurrentThreadId()
|
||||
<< "\n" << flush;
|
||||
|
||||
// Since we might be in a sub-thread at this point, use a timer to
|
||||
// forward this event to the main thread.
|
||||
// Since we might be in a sub-thread at this point, use a Windows
|
||||
// message to forward this event to the main thread.
|
||||
|
||||
#ifdef _WIN32
|
||||
ACQUIRE_LOCK(_timer_lock);
|
||||
if (_timer == 0) {
|
||||
_timer = SetTimer(NULL, 0, 0, win_timer_func);
|
||||
logfile << "_timer = " << _timer << "\n" << flush;
|
||||
}
|
||||
RELEASE_LOCK(_timer_lock);
|
||||
PostThreadMessage(main_thread_id, WM_USER, 0, 0);
|
||||
#else
|
||||
// TODO: send the message to the main thread properly.
|
||||
handle_request_loop();
|
||||
|
|
@ -139,12 +135,16 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
|
|||
|
||||
open_logfile();
|
||||
logfile << "initializing\n" << flush;
|
||||
// logfile << "main thread = " << GetCurrentThreadId() << "\n";
|
||||
|
||||
#ifdef _WIN32
|
||||
// Save the calling thread ID (i.e. the main thread) so we can post
|
||||
// messages back to this thread when needed.
|
||||
main_thread_id = GetCurrentThreadId();
|
||||
logfile << "main thread = " << main_thread_id << "\n";
|
||||
#endif
|
||||
|
||||
logfile << "browserFuncs = " << browserFuncs << "\n" << flush;
|
||||
|
||||
INIT_LOCK(_timer_lock);
|
||||
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
string plugin_location = "c:/cygwin/home/drose/player/direct/built/lib/p3d_plugin.dll";
|
||||
|
|
@ -202,23 +202,8 @@ NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) {
|
|||
NPError OSCALL
|
||||
NP_Shutdown(void) {
|
||||
logfile << "shutdown\n" << flush;
|
||||
|
||||
ACQUIRE_LOCK(_timer_lock);
|
||||
#ifdef _WIN32
|
||||
if (_timer != 0) {
|
||||
KillTimer(NULL, _timer);
|
||||
_timer = 0;
|
||||
}
|
||||
#endif
|
||||
RELEASE_LOCK(_timer_lock);
|
||||
DESTROY_LOCK(_timer_lock);
|
||||
|
||||
logfile << "unloading plugin\n" << flush;
|
||||
|
||||
unload_plugin();
|
||||
|
||||
logfile << "done shutdown\n" << flush;
|
||||
|
||||
// Not clear whether there's a return value or not. Some versions
|
||||
// of the API have different opinions on this.
|
||||
return NPERR_NO_ERROR;
|
||||
|
|
@ -270,6 +255,14 @@ NPP_SetWindow(NPP instance, NPWindow *window) {
|
|||
<< ", " << window->width << ", " << window->height
|
||||
<< "\n" << flush;
|
||||
|
||||
if (window->type == NPWindowTypeWindow) {
|
||||
// Subclass the window to make it call our own window_proc instead
|
||||
// of whatever window_proc it has already. This is just a dopey
|
||||
// trick to allow us to poll events in the main thread.
|
||||
HWND hwnd = (HWND)window->window;
|
||||
LONG_PTR orig = SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)window_proc);
|
||||
}
|
||||
|
||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||
assert(inst != NULL);
|
||||
inst->set_window(window);
|
||||
|
|
@ -426,3 +419,4 @@ NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
|
|||
logfile << "SetValue " << variable << "\n";
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -248,10 +248,11 @@ P3D_instance *
|
|||
create_instance(const string &arg, P3D_window_type window_type,
|
||||
int win_x, int win_y, int win_width, int win_height,
|
||||
P3D_window_handle parent_window,
|
||||
const string &output_filename) {
|
||||
const Filename &output_filename) {
|
||||
|
||||
string os_output_filename = output_filename.to_os_specific();
|
||||
P3D_token tokens[] = {
|
||||
{ "output_filename", output_filename.c_str() },
|
||||
{ "output_filename", os_output_filename.c_str() },
|
||||
{ "src", arg.c_str() },
|
||||
};
|
||||
int num_tokens = sizeof(tokens) / sizeof(P3D_token);
|
||||
|
|
@ -343,8 +344,8 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
|||
extern int optind;
|
||||
const char *optstr = "p:l:t:s:o:h";
|
||||
|
||||
string p3d_plugin_filename;
|
||||
string output_filename;
|
||||
Filename p3d_plugin_filename;
|
||||
Filename output_filename;
|
||||
P3D_window_type window_type = P3D_WT_toplevel;
|
||||
int win_x = 0, win_y = 0;
|
||||
int win_width = 0, win_height = 0;
|
||||
|
|
@ -354,11 +355,11 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
|||
while (flag != EOF) {
|
||||
switch (flag) {
|
||||
case 'p':
|
||||
p3d_plugin_filename = optarg;
|
||||
p3d_plugin_filename = Filename::from_os_specific(optarg);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
output_filename = optarg;
|
||||
output_filename = Filename::from_os_specific(optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
|
@ -407,7 +408,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!load_plugin(p3d_plugin_filename)) {
|
||||
if (!load_plugin(p3d_plugin_filename.to_os_specific())) {
|
||||
cerr << "Unable to load Panda3D plugin.\n";
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,6 @@ class AppRunner(DirectObject):
|
|||
# One day we will have support for multiple instances within a
|
||||
# Python session. Against that day, we save the instance ID
|
||||
# for this instance.
|
||||
print "setP3DFilename(%s, %s, %s)" % (p3dFilename, tokens, instanceId)
|
||||
self.instanceId = instanceId
|
||||
|
||||
tokenDict = dict(tokens)
|
||||
|
|
|
|||
Loading…
Reference in New Issue