Skip to content

Commit

Permalink
UI|Client|Games: Game availability changes now have their own audience
Browse files Browse the repository at this point in the history
Rather than updating game availability in the UI after app startup
is complete, we'll do updates whenever Games has finished locating
startup resources.

Also made it possible forget and recheck the startup resources.
  • Loading branch information
skyjake committed Feb 12, 2015
1 parent 3efff8f commit 4d19071
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 14 deletions.
8 changes: 8 additions & 0 deletions doomsday/client/include/games.h
Expand Up @@ -63,6 +63,9 @@ class Games
/// Notified when a new game is added.
DENG2_DEFINE_AUDIENCE2(Addition, void gameAdded(Game &game))

/// Notified after game resources have been located.
DENG2_DEFINE_AUDIENCE2(Readiness, void gameReadinessUpdated())

public:
Games();

Expand Down Expand Up @@ -122,6 +125,11 @@ class Games
*/
void locateAllResources();

/**
* Forgets the previously located resources of all registered games.
*/
void forgetAllResources();

/**
* Collects all games.
*
Expand Down
21 changes: 21 additions & 0 deletions doomsday/client/src/games.cpp
Expand Up @@ -93,9 +93,11 @@ DENG2_PIMPL(Games)
}

DENG2_PIMPL_AUDIENCE(Addition)
DENG2_PIMPL_AUDIENCE(Readiness)
};

DENG2_AUDIENCE_METHOD(Games, Addition)
DENG2_AUDIENCE_METHOD(Games, Readiness)

Games::Games() : d(new Instance(this))
{}
Expand Down Expand Up @@ -265,6 +267,25 @@ void Games::locateAllResources()
{
BusyMode_RunNewTaskWithName(BUSYF_STARTUP | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0),
locateAllResourcesWorker, (void *)this, "Locating game resources...");

DENG2_FOR_AUDIENCE2(Readiness, i)
{
i->gameReadinessUpdated();
}
}

void Games::forgetAllResources()
{
foreach(Game *game, d->games)
{
foreach(ResourceManifest *manifest, game->manifests())
{
if(manifest->fileFlags() & FF_STARTUP)
{
manifest->forgetFile();
}
}
}
}

D_CMD(ListGames)
Expand Down
42 changes: 36 additions & 6 deletions doomsday/client/src/ui/widgets/mpsessionmenuwidget.cpp
Expand Up @@ -36,6 +36,7 @@ using namespace de;

DENG_GUI_PIMPL(MPSessionMenuWidget)
, DENG2_OBSERVES(App, GameChange)
, DENG2_OBSERVES(Games, Readiness)
, DENG2_OBSERVES(ServerLink, DiscoveryUpdate)
{
static ServerLink &link() { return ClientApp::serverLink(); }
Expand Down Expand Up @@ -119,28 +120,32 @@ DENG_GUI_PIMPL(MPSessionMenuWidget)
*/
struct ServerWidget : public GameSessionWidget
{
ServerListItem const *svItem = nullptr;

ServerWidget()
{
loadButton().disable();
}

Game const *game() const
{
if(!svItem) return nullptr;
return &App_Games().byIdentityKey(svItem->info().gameIdentityKey);
}

void updateFromItem(ServerListItem const &item)
{
try
{
Game const &svGame = App_Games().byIdentityKey(item.info().gameIdentityKey);
svItem = &item;
Game const &svGame = *game();

if(style().images().has(svGame.logoImageId()))
{
loadButton().setImage(style().images().image(svGame.logoImageId()));
}

serverinfo_t const &sv = item.info();

loadButton().enable(sv.canJoin &&
sv.version == DOOMSDAY_VERSION &&
svGame.allStartupFilesFound());

loadButton().setText(String(_E(F)_E(s) "%2\n" _E(.)_E(.)_E(C) "(%4) " _E(.)
_E(1)_E(>) "%1" _E(.)_E(<)_E(D)_E(l) "\n%5 %3")
.arg(sv.name)
Expand All @@ -151,12 +156,24 @@ DENG_GUI_PIMPL(MPSessionMenuWidget)

// Extra information.
document().setText(ServerInfo_AsStyledText(&sv));

updateAvailability();
}
catch(Error const &)
{
svItem = nullptr;

/// @todo
}
}

void updateAvailability()
{
loadButton().enable(svItem &&
svItem->info().canJoin &&
svItem->info().version == DOOMSDAY_VERSION &&
game()->allStartupFilesFound());
}
};

DiscoveryMode mode;
Expand All @@ -169,13 +186,15 @@ DENG_GUI_PIMPL(MPSessionMenuWidget)
{
link().audienceForDiscoveryUpdate += this;
App::app().audienceForGameChange() += this;
App_Games().audienceForReadiness() += this;
}

~Instance()
{
releaseRef(maxHeightRule);
link().audienceForDiscoveryUpdate -= this;
App::app().audienceForGameChange() -= this;
App_Games().audienceForReadiness() -= this;
}

/**
Expand Down Expand Up @@ -268,6 +287,17 @@ DENG_GUI_PIMPL(MPSessionMenuWidget)
link().discoverUsingMaster();
}
}

void gameReadinessUpdated()
{
foreach(Widget *w, self.childWidgets())
{
if(ServerWidget *sw = w->maybeAs<ServerWidget>())
{
sw->updateAvailability();
}
}
}
};

MPSessionMenuWidget::MPSessionMenuWidget(DiscoveryMode discovery)
Expand Down
8 changes: 4 additions & 4 deletions doomsday/client/src/ui/widgets/savedsessionmenuwidget.cpp
Expand Up @@ -36,7 +36,7 @@ using de::game::Session;
using de::game::SavedSession;

DENG_GUI_PIMPL(SavedSessionMenuWidget)
, DENG2_OBSERVES(App, StartupComplete)
, DENG2_OBSERVES(Games, Readiness)
, DENG2_OBSERVES(Session::SavedIndex, AvailabilityUpdate)
, DENG2_OBSERVES(Loop, Iteration) // deferred refresh
{
Expand Down Expand Up @@ -172,18 +172,18 @@ DENG_GUI_PIMPL(SavedSessionMenuWidget)

Instance(Public *i) : Base(i)
{
App::app().audienceForStartupComplete() += this;
App_Games().audienceForReadiness() += this;
game::Session::savedIndex().audienceForAvailabilityUpdate() += this;
}

~Instance()
{
Loop::get().audienceForIteration() -= this;
App::app().audienceForStartupComplete() -= this;
App_Games().audienceForReadiness() -= this;
game::Session::savedIndex().audienceForAvailabilityUpdate() -= this;
}

void appStartupCompleted()
void gameReadinessUpdated()
{
// Startup resources for all games have been located.
// We can now determine which of the saved sessions are loadable.
Expand Down
Expand Up @@ -29,8 +29,8 @@ using namespace de;

DENG_GUI_PIMPL(SingleplayerSessionMenuWidget)
, DENG2_OBSERVES(Games, Addition)
, DENG2_OBSERVES(Games, Readiness)
, DENG2_OBSERVES(Loop, Iteration) // deferred updates
, DENG2_OBSERVES(App, StartupComplete)
, DENG2_OBSERVES(App, GameChange)
{
/// ActionItem with a Game member, for loading a particular game.
Expand Down Expand Up @@ -72,17 +72,17 @@ DENG_GUI_PIMPL(SingleplayerSessionMenuWidget)
Instance(Public *i) : Base(i)
{
App_Games().audienceForAddition() += this;
App_Games().audienceForReadiness() += this;
App::app().audienceForGameChange() += this;
App::app().audienceForStartupComplete() += this;
}

~Instance()
{
Loop::get().audienceForIteration() -= this;

App_Games().audienceForAddition() -= this;
App_Games().audienceForReadiness() -= this;
App::app().audienceForGameChange() -= this;
App::app().audienceForStartupComplete() -= this;
}

void gameAdded(Game &game)
Expand Down Expand Up @@ -173,7 +173,7 @@ DENG_GUI_PIMPL(SingleplayerSessionMenuWidget)
emit self.availabilityChanged();
}

void appStartupCompleted()
void gameReadinessUpdated()
{
updateGameAvailability();
}
Expand Down

0 comments on commit 4d19071

Please sign in to comment.