Skip to content

Commit

Permalink
UI|Client: Working on the multiplayer dialog
Browse files Browse the repository at this point in the history
Listing found servers. The Game can now be asked to provide the
ID of the game logo image.
  • Loading branch information
skyjake committed Jan 23, 2014
1 parent 6656bf7 commit e548c62
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 4 deletions.
5 changes: 5 additions & 0 deletions doomsday/client/include/game.h
Expand Up @@ -113,6 +113,11 @@ class Game : public de::game::Game
*/
de::Path const &bindingConfig() const;

/**
* Returns the identifier of the Style logo image to represent this game.
*/
de::String logoImageId() const;

/**
* Add a new manifest to the list of manifests.
*
Expand Down
2 changes: 2 additions & 0 deletions doomsday/client/include/network/serverlink.h
Expand Up @@ -64,6 +64,8 @@ class ServerLink : public de::shell::AbstractLink

QList<de::Address> foundServers() const;

bool isFound(de::Address const &host) const;

bool foundServerInfo(de::Address const &host, serverinfo_t *info) const;

bool foundServerInfo(int index, serverinfo_t *info) const;
Expand Down
22 changes: 22 additions & 0 deletions doomsday/client/src/game.cpp
Expand Up @@ -128,6 +128,28 @@ String const &Game::identityKey() const
return d->identityKey;
}

String Game::logoImageId() const
{
String idKey = identityKey();

/// @todo The name of the plugin should be accessible via the plugin loader.
String plugName;
if(idKey.contains("heretic"))
{
plugName = "libheretic";
}
else if(idKey.contains("hexen"))
{
plugName = "libhexen";
}
else
{
plugName = "libdoom";
}

return "logo.game." + plugName;
}

Path const &Game::mainConfig() const
{
return d->mainConfig;
Expand Down
5 changes: 5 additions & 0 deletions doomsday/client/src/network/serverlink.cpp
Expand Up @@ -282,6 +282,11 @@ QList<Address> ServerLink::foundServers() const
return d->allFound().keys();
}

bool ServerLink::isFound(Address const &host) const
{
return d->allFound().contains(host);
}

bool ServerLink::foundServerInfo(int index, serverinfo_t *info) const
{
Instance::Servers all = d->allFound();
Expand Down
5 changes: 5 additions & 0 deletions doomsday/client/src/ui/clientwindow.cpp
Expand Up @@ -311,6 +311,11 @@ DENG2_OBSERVES(App, StartupComplete)
mode = newMode;
}

/**
* Completes the initialization of the main window. This is called only after the
* window is created and visible, so that OpenGL operations and actions on the native
* window can be performed without restrictions.
*/
void finishMainWindowInit()
{
#ifdef MACOSX
Expand Down
167 changes: 165 additions & 2 deletions doomsday/client/src/ui/dialogs/multiplayerdialog.cpp
Expand Up @@ -17,15 +17,178 @@
*/

#include "ui/dialogs/multiplayerdialog.h"
#include "network/serverlink.h"
#include "clientapp.h"
#include "dd_main.h"

#include <de/SignalAction>
#include <de/SequentialLayout>
#include <de/ChildWidgetOrganizer>
#include <de/ui/Item>

using namespace de;

DENG2_PIMPL(MultiplayerDialog)
DENG_GUI_PIMPL(MultiplayerDialog)
, DENG2_OBSERVES(ServerLink, DiscoveryUpdate)
, public ChildWidgetOrganizer::IWidgetFactory
{
static String hostId(serverinfo_t const &sv)
{
return String("%1:%2").arg(sv.address).arg(sv.port);
}

class ServerListItem : public ui::Item
{
public:
ServerListItem(serverinfo_t const &serverInfo)
{
setData(hostId(serverInfo));
std::memcpy(&_info, &serverInfo, sizeof(serverInfo));
}

serverinfo_t const &info() const
{
return _info;
}

void setInfo(serverinfo_t const &serverInfo)
{
std::memcpy(&_info, &serverInfo, sizeof(serverInfo));
notifyChange();
}

private:
serverinfo_t _info;
};

/**
* Widget representing a ServerListItem in the dialog's menu.
*/
struct ServerWidget : public GuiWidget
{
LabelWidget *title;
//LabelWidget *info;
ButtonWidget *extra;
ButtonWidget *join;

ServerWidget()
{
add(title = new LabelWidget);
//add(info = new LabelWidget);
add(extra = new ButtonWidget);
add(join = new ButtonWidget);

extra->setText(tr("..."));
join->setText(tr("Join"));

title->setSizePolicy(ui::Expand, ui::Expand);
title->setTextAlignment(ui::AlignRight);
title->setTextLineAlignment(ui::AlignLeft);
title->setImageAlignment(ui::AlignTop);

//info->setSizePolicy(ui::Expand, ui::Expand);
extra->setSizePolicy(ui::Expand, ui::Expand);
join->setSizePolicy(ui::Expand, ui::Expand);

join->disable();

SequentialLayout layout(rule().left(), rule().top(), ui::Right);
layout << *title << *extra << *join;
rule().setSize(layout.width(), layout.height());
}

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

if(style().images().has(svGame.logoImageId()))
{
title->setImage(style().images().image(svGame.logoImageId()));
}

title->setText(String(_E(1) "%1%2" _E(2) "%3"
_E(.)_E(.)_E(l)_E(D) "\n%4\n%5/%6 players")
.arg(item.info().name)
.arg(!String(item.info().description).isEmpty()? "\n" : "")
.arg(item.info().description)
.arg(item.info().gameConfig)
.arg(item.info().numPlayers)
.arg(item.info().maxPlayers));
}
catch(Error const &)
{
/// @todo
}
}
};

MenuWidget *list;

Instance(Public *i) : Base(i)
{
self.area().add(list = new MenuWidget);

// Configure the server list widet.
list->setGridSize(1, ui::Expand, 0, ui::Expand);
list->organizer().setWidgetFactory(*this);

link().audienceForDiscoveryUpdate += this;
}

~Instance()
{
link().audienceForDiscoveryUpdate -= this;
}

GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *)
{
return new ServerWidget;
}

void updateItemWidget(GuiWidget &widget, ui::Item const &item)
{
widget.as<ServerWidget>().updateFromItem(item.as<ServerListItem>());
}

void linkDiscoveryUpdate(ServerLink const &link)
{
qDebug() << "discovery" << link.foundServerCount();

// Remove obsolete entries.
for(ui::Data::Pos idx = 0; idx < list->items().size(); ++idx)
{
String const id = list->items().at(idx).data().toString();
if(!link.isFound(Address::parse(id)))
{
list->items().remove(idx--);
}
}

// Add new entries and update existing ones.
foreach(de::Address const &host, link.foundServers())
{
serverinfo_t info;
if(!link.foundServerInfo(host, &info)) continue;

ui::Data::Pos found = list->items().findData(hostId(info));
if(found == ui::Data::InvalidPos)
{
// Needs to be added.
list->items().append(new ServerListItem(info));
}
else
{
// Update the info.
list->items().at(found).as<ServerListItem>().setInfo(info);
}
}
}

static ServerLink &link()
{
return ClientApp::serverLink();
}
};

Expand All @@ -40,7 +203,7 @@ MultiplayerDialog::MultiplayerDialog(String const &name)
layout.setGridSize(1, 0);
//layout.setColumnAlignment(0, ui::AlignRight);

layout << *lab;
layout << *lab << *d->list;

area().setContentSize(layout.width(), layout.height());

Expand Down
4 changes: 2 additions & 2 deletions doomsday/client/src/ui/widgets/gameselectionwidget.cpp
Expand Up @@ -85,9 +85,9 @@ DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation)
{
plugName = "libdoom";
}
if(style().images().has("logo.game." + plugName))
if(style().images().has(game.logoImageId()))
{
item->setImage(style().images().image("logo.game." + plugName));
item->setImage(style().images().image(game.logoImageId()));
}

return item;
Expand Down

0 comments on commit e548c62

Please sign in to comment.