Skip to content

Commit

Permalink
make loadingscreen more responsive to user input.
Browse files Browse the repository at this point in the history
We now create a new thread that does the actual loading while the main
thread handles user input (and drawing of the loadingscreen ). That way
wesnoth can still react on user input such as close game requests while
reading the config files.
  • Loading branch information
gfgtdf committed Mar 30, 2016
1 parent f9ee42c commit 99bbaae
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 25 deletions.
21 changes: 13 additions & 8 deletions src/game_config_manager.cpp
Expand Up @@ -89,7 +89,7 @@ bool game_config_manager::init_game_config(FORCE_RELOAD_CONFIG force_reload)
game_config::scoped_preproc_define title_screen("TITLE_SCREEN",
!cmdline_opts_.multiplayer && !cmdline_opts_.test && !jump_to_editor_);

load_game_config(force_reload);
load_game_config_with_loadscreen(force_reload);

game_config::load_config(game_config_.child("game_config"));

Expand Down Expand Up @@ -119,10 +119,17 @@ bool map_includes(const preproc_map& general, const preproc_map& special)
}
} // end anonymous namespace

void game_config_manager::load_game_config(FORCE_RELOAD_CONFIG force_reload,
void game_config_manager::load_game_config_with_loadscreen(FORCE_RELOAD_CONFIG force_reload,
game_classification const* classification)
{
// Make sure that 'debug mode' symbol is set
gui2::tloadscreen::display(video_, [=]() {
load_game_config(force_reload, classification);
});
}
void game_config_manager::load_game_config(FORCE_RELOAD_CONFIG force_reload,
game_classification const* classification)
{
// Make sure that 'debug mode' symbol is set
// if command line parameter is selected
// also if we're in multiplayer and actual debug mode is disabled.
game_config::scoped_preproc_define debug_mode("DEBUG_MODE",
Expand All @@ -138,8 +145,6 @@ void game_config_manager::load_game_config(FORCE_RELOAD_CONFIG force_reload,
}
}

gui2::tloadscreen::display(video_);

// The loadscreen will erase the titlescreen.
// NOTE: even without loadscreen, needed after MP lobby.
try {
Expand Down Expand Up @@ -493,7 +498,7 @@ void game_config_manager::reload_changed_game_config()
void game_config_manager::load_game_config_for_editor()
{
game_config::scoped_preproc_define editor("EDITOR");
load_game_config(NO_FORCE_RELOAD);
load_game_config_with_loadscreen(NO_FORCE_RELOAD);
}

void game_config_manager::load_game_config_for_game(
Expand Down Expand Up @@ -529,7 +534,7 @@ void game_config_manager::load_game_config_for_game(
}

try{
load_game_config(NO_FORCE_RELOAD, &classification);
load_game_config_with_loadscreen(NO_FORCE_RELOAD, &classification);
}
catch(game::error&) {
cache_.clear_defines();
Expand All @@ -541,7 +546,7 @@ void game_config_manager::load_game_config_for_game(
previous_defines.push_back(new_define);
}

load_game_config(NO_FORCE_RELOAD);
load_game_config_with_loadscreen(NO_FORCE_RELOAD);

throw;
}
Expand Down
3 changes: 3 additions & 0 deletions src/game_config_manager.hpp
Expand Up @@ -59,6 +59,9 @@ class game_config_manager
void load_game_config(FORCE_RELOAD_CONFIG force_reload,
game_classification const* classification = NULL);

void load_game_config_with_loadscreen(FORCE_RELOAD_CONFIG force_reload,
game_classification const* classification = NULL);

// load_game_config() helper functions.
void load_addons_cfg();
void set_multiplayer_hashes();
Expand Down
5 changes: 3 additions & 2 deletions src/game_launcher.cpp
Expand Up @@ -1011,9 +1011,9 @@ void game_launcher::launch_game(RELOAD_GAME_DATA reload)
return;
}

gui2::tloadscreen::display(video());
gui2::tloadscreen::progress("load data");
gui2::tloadscreen::display(video(), [=]() {

gui2::tloadscreen::progress("load data");
if(reload == RELOAD_DATA) {
try {
game_config_manager::get()->
Expand All @@ -1022,6 +1022,7 @@ void game_launcher::launch_game(RELOAD_GAME_DATA reload)
return;
}
}
});

try {
campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types());
Expand Down
20 changes: 19 additions & 1 deletion src/gui/dialogs/loadscreen.cpp
Expand Up @@ -17,15 +17,21 @@
#include "gui/dialogs/loadscreen.hpp"
#include "gui/widgets/window.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/core/timer.hpp"
#include "video.hpp"

#include <boost/bind.hpp>
#include <boost/thread.hpp>

namespace gui2
{

REGISTER_DIALOG(loadscreen)

void tloadscreen::show(CVideo& video)
{
tdialog::show(video);
return;
if(video.faked()) {
return;
}
Expand Down Expand Up @@ -53,14 +59,18 @@ twindow* tloadscreen::build_window(CVideo& video) const
return build(video, window_id());
}

void tloadscreen::pre_show(twindow& /*window*/)
void tloadscreen::pre_show(twindow& window)
{
worker_.reset(new boost::thread(work_));
timer_id_ = add_timer(100, boost::bind(&tloadscreen::timer_callback, this, boost::ref(window)), true);
// FIXME
cursor::setter cur(cursor::WAIT);
}

void tloadscreen::post_show(twindow& /*window*/)
{
worker_.reset();
remove_timer(timer_id_);
cursor::setter cur(cursor::NORMAL);
}

Expand All @@ -79,4 +89,12 @@ void tloadscreen::progress(const char* stage)

tloadscreen* tloadscreen::current_load = NULL;

void tloadscreen::timer_callback(twindow& window)
{
if (!worker_ || worker_->timed_join(boost::posix_time::milliseconds(0))) {
window.close();

}
}

} // namespace gui2
34 changes: 27 additions & 7 deletions src/gui/dialogs/loadscreen.hpp
Expand Up @@ -15,8 +15,14 @@

#include "gui/dialogs/dialog.hpp"

class CVideo;
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>

class CVideo;
namespace boost
{
class thread;
}
namespace gui2
{

Expand All @@ -25,22 +31,32 @@ class twindow;
class tloadscreen : public tdialog
{
public:
tloadscreen()

tloadscreen(boost::function<void()> f)
: window_(NULL)
, previous_load(current_load)
, current_stage(NULL)
, timer_id_(0)
, work_(f)
, worker_()
{
current_load = this;
}

~tloadscreen()
{
close();
current_load = previous_load;
}

static void display(CVideo& video) {
tloadscreen().show(video);
static void display(CVideo& video, boost::function<void()> f) {
static bool already_shown = false;
if (already_shown) {
f();
}
else {
already_shown = true;
tloadscreen(f).show(video);
already_shown = false;
}
}

void show(CVideo& video);
Expand All @@ -56,20 +72,24 @@ class tloadscreen : public tdialog
void close();

private:
size_t timer_id_;
boost::function<void()> work_;
boost::scoped_ptr<boost::thread> worker_;
twindow* window_;

twindow* build_window(CVideo& video) const;

virtual const std::string& window_id() const;

void timer_callback(twindow& window);

/** Inherited from tdialog. */
void pre_show(twindow& window);

/** Inherited from tdialog. */
void post_show(twindow& window);

static tloadscreen* current_load;
tloadscreen*const previous_load;
const char* current_stage;
};

Expand Down
4 changes: 3 additions & 1 deletion src/play_controller.cpp
Expand Up @@ -224,7 +224,8 @@ struct throw_end_level

void play_controller::init(CVideo& video, const config& level)
{
gui2::tloadscreen::display(video);

gui2::tloadscreen::display(video, [this, &video, &level]() {
gui2::tloadscreen::progress("load level");

LOG_NG << "initializing game_state..." << (SDL_GetTicks() - ticks()) << std::endl;
Expand Down Expand Up @@ -307,6 +308,7 @@ void play_controller::init(CVideo& video, const config& level)
plugins_context_->set_callback("save_game", boost::bind(&play_controller::save_game_auto, this, boost::bind(get_str, _1, "filename" )), true);
plugins_context_->set_callback("save_replay", boost::bind(&play_controller::save_replay_auto, this, boost::bind(get_str, _1, "filename" )), true);
plugins_context_->set_callback("quit", throw_end_level(), false);
});
}

void play_controller::reset_gamestate(const config& level, int replay_pos)
Expand Down
15 changes: 9 additions & 6 deletions src/wesnoth.cpp
Expand Up @@ -640,13 +640,15 @@ static int do_gameloop(const std::vector<std::string>& args)
gui2::init();
const gui2::event::tmanager gui_event_manager;

gui2::tloadscreen::display(game->video());

game_config_manager config_manager(cmdline_opts, game->video(),
game->jump_to_editor());

gui2::tloadscreen::progress("load config");
res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD);
gui2::tloadscreen::display(game->video(), [&]() {
gui2::tloadscreen::progress("load config");
res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD);
});

if(res == false) {
std::cerr << "could not initialize game config\n";
return 1;
Expand Down Expand Up @@ -851,9 +853,10 @@ static int do_gameloop(const std::vector<std::string>& args)
}
continue;
} else if(res == gui2::ttitle_screen::RELOAD_GAME_DATA) {
gui2::tloadscreen::display(game->video());
config_manager.reload_changed_game_config();
image::flush_cache();
gui2::tloadscreen::display(game->video(), [&]() {
config_manager.reload_changed_game_config();
image::flush_cache();
});
continue;
} else if(res == gui2::ttitle_screen::START_MAP_EDITOR) {
game->start_editor();
Expand Down

0 comments on commit 99bbaae

Please sign in to comment.