Skip to content

Commit

Permalink
UI|Home: Load game title pictures from the WAD files of each game
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Mar 30, 2016
1 parent 6fe50b1 commit 5961655
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 21 deletions.
61 changes: 61 additions & 0 deletions doomsday/apps/client/include/resource/idtech1image.h
@@ -0,0 +1,61 @@
/** @file idtech1image.h
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef DENG_CLIENT_RESOURCE_IDTECH1IMAGE_H
#define DENG_CLIENT_RESOURCE_IDTECH1IMAGE_H

#include <de/Image>

/**
* Image that imports its content using Id Tech 1 graphics formats.
*/
class IdTech1Image : public de::Image
{
public:
enum Format {
Automatic,
RawVGAScreen,
Patch
};

public:
/**
* Constructs a new Id Tech 1 image. The Image object gets initialized with the
* RGBA_8888 contents of the image.
*
* @param data Image data. Format detected automatically.
* @param palette RGB palette containing color triplets. The size of the palette
* must be big enough to contain all the color indices used in the
* image data.
*/
IdTech1Image(de::IByteArray const &data, de::IByteArray const &palette,
Format format = Automatic);

de::Vector2i origin() const;

/**
* Size of the image data as declared in its metadata. May not match the actual
* image size.
*/
Size nominalSize() const;

private:
DENG2_PRIVATE(d)
};

#endif // DENG_CLIENT_RESOURCE_IDTECH1IMAGE_H
74 changes: 74 additions & 0 deletions doomsday/apps/client/src/resource/idtech1image.cpp
@@ -0,0 +1,74 @@
/** @file idtech1image.cpp
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "resource/idtech1image.h"

#include <doomsday/resource/patch.h>

using namespace de;
using namespace res;

DENG2_PIMPL_NOREF(IdTech1Image)
{
Vector2i origin;
Size nominalSize;
};

IdTech1Image::IdTech1Image(IByteArray const &data, IByteArray const &palette, Format format)
: d(new Instance)
{
Size const rawSize(320, 200);

if(format == Automatic)
{
// Try to guess which format the data uses.
if(data.size() == rawSize.x * rawSize.y)
{
format = RawVGAScreen;
}
else
{
format = Patch;
}
}

if(format == RawVGAScreen)
{
d->nominalSize = rawSize;
Image::operator = (fromIndexedData(rawSize, data, palette));
}
else
{
auto const metadata = Patch::loadMetadata(data);
d->nominalSize = metadata.logicalDimensions;
d->origin = metadata.origin;

Image::operator = (Image::fromMaskedIndexedData(metadata.dimensions,
Patch::load(data), palette));
}
}

Vector2i IdTech1Image::origin() const
{
return d->origin;
}

Image::Size IdTech1Image::nominalSize() const
{
return d->nominalSize;
}
2 changes: 1 addition & 1 deletion doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp
Expand Up @@ -347,7 +347,7 @@ DENG_GUI_PIMPL(GameColumnWidget)
auto *heading = LabelWidget::newWithText(tr("Custom Profiles"));
heading->setSizePolicy(ui::Filled, ui::Expand);
heading->setFont("heading");
heading->setTextColor("accent");
//heading->setTextColor("accent");
heading->setAlignment(ui::AlignLeft);
heading->margins().setLeftRight("");
return heading;
Expand Down
67 changes: 51 additions & 16 deletions doomsday/apps/client/src/ui/home/gamepanelbuttonwidget.cpp
Expand Up @@ -21,11 +21,15 @@
#include "ui/savedsessionlistdata.h"
#include "ui/dialogs/packagesdialog.h"
#include "ui/widgets/packagesbuttonwidget.h"
#include "resource/idtech1image.h"
#include "dd_main.h"

#include <doomsday/console/exec.h>
#include <doomsday/doomsdayapp.h>
#include <doomsday/games.h>
#include <doomsday/DoomsdayApp>
#include <doomsday/Games>
#include <doomsday/LumpCatalog>
#include <doomsday/LumpDirectory>

#include <de/App>
#include <de/CallbackAction>
#include <de/ChildWidgetOrganizer>
Expand All @@ -43,12 +47,16 @@ DENG_GUI_PIMPL(GamePanelButtonWidget)
PackagesButtonWidget *packagesButton;
ButtonWidget *playButton;
ButtonWidget *deleteSaveButton;
res::LumpCatalog catalog;

Instance(Public *i, GameProfile &profile, SavedSessionListData const &savedItems)
: Base(i)
, gameProfile(profile)
, savedItems(savedItems)
{
self.icon().setImageFit(ui::FitToHeight | ui::OriginalAspectRatio);
self.icon().setBehavior(ContentClipping);

packagesButton = new PackagesButtonWidget;
packagesButton->setDialogTitle(profile.name());
self.addButton(packagesButton);
Expand All @@ -60,6 +68,10 @@ DENG_GUI_PIMPL(GamePanelButtonWidget)
StringList pkgs;
for(auto const &i : ids) pkgs << i;
gameProfile.setPackages(pkgs);
if(catalog.setPackages(gameProfile.allRequiredPackages()))
{
updateGameTitleImage();
}
});

playButton = new ButtonWidget;
Expand Down Expand Up @@ -113,20 +125,6 @@ DENG_GUI_PIMPL(GamePanelButtonWidget)
}
}

/// Action that deletes a savegame folder.
struct DeleteAction : public Action
{
GamePanelButtonWidget *widget;
String savePath;
DeleteAction(GamePanelButtonWidget *wgt, String const &path)
: widget(wgt), savePath(path) {}
void trigger() {
widget->unselectSave();
App::rootFolder().removeFile(savePath);
App::fileSystem().refresh();
}
};

void deleteButtonPressed()
{
DENG2_ASSERT(saves->selectedPos() != ui::Data::InvalidPos);
Expand All @@ -151,6 +149,39 @@ DENG_GUI_PIMPL(GamePanelButtonWidget)
pop->open();
}

void updateGameTitleImage()
{
if(!game().isPlayable())
{
// Use a generic logo, some files are missing.
QImage img(64, 64, QImage::Format_ARGB32);
img.fill(Qt::white);
self.icon().setImage(img);
return;
}

try
{
Block const playPal = catalog.read("PLAYPAL");
Block const title = catalog.read("TITLE");
Block const titlePic = catalog.read("TITLEPIC");

IdTech1Image img(title.isEmpty()? titlePic : title, playPal);

// Apply VGA aspect correction while downscaling 50%.
self.icon().setImage(img.toQImage().scaled(img.width()/2,
img.height()/2 * 1.2f,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
}
catch(Error const &er)
{
LOG_RES_WARNING("Failed to load title picture for game profile \"%s\": %s")
<< gameProfile.name()
<< er.asText();
}
}

//- ChildWidgetOrganizer::IFilter ---------------------------------------------

bool isItemAccepted(ChildWidgetOrganizer const &,
Expand Down Expand Up @@ -217,6 +248,10 @@ void GamePanelButtonWidget::updateContent()
.arg(meta));

d->packagesButton->setPackages(d->gameProfile.packages());
if(d->catalog.setPackages(d->gameProfile.allRequiredPackages()))
{
d->updateGameTitleImage();
}
}

void GamePanelButtonWidget::unselectSave()
Expand Down
8 changes: 4 additions & 4 deletions doomsday/apps/client/src/ui/home/homewidget.cpp
Expand Up @@ -154,15 +154,15 @@ DENG_GUI_PIMPL(HomeWidget)
{
// Edge navigation buttons are only visible when hoving on them.
button.set(Background(style().colors().colorf("text")));
button.setImageColor(style().colors().colorf("inverted.text"));
button.setImageColor(style().colors().colorf("inverted.text") + Vector4f(0, 0, 0, 2));
button.setOverrideImageSize(style().fonts().font("default").height().value() * 2);
button.setOpacity(0);
button.setBehavior(Widget::Focusable, UnsetFlags); // only for the mouse
button.setAttribute(EatAllMouseEvents, SetFlags);
button.audienceForStateChange() += this;

button.rule()
.setInput(Rule::Width, style().fonts().font("default").height() * 2)
.setInput(Rule::Width, style().fonts().font("default").height() * 1.5f)
.setInput(Rule::Bottom, self.rule().bottom())
.setInput(Rule::Top, tabs->rule().bottom());
}
Expand All @@ -172,11 +172,11 @@ DENG_GUI_PIMPL(HomeWidget)
// Hide navigation buttons when they are not being used.
if(state == ButtonWidget::Down)
{
button.setOpacity(.4f);
button.setOpacity(.3f);
}
else
{
button.setOpacity(state == ButtonWidget::Up? 0 : .2f, 0.25);
button.setOpacity(state == ButtonWidget::Up? 0 : .1f, 0.25);
}
}

Expand Down

0 comments on commit 5961655

Please sign in to comment.