Permalink
Browse files

MUTATIONOFJB: Add font support and conversation widget.

  • Loading branch information...
LubomirR authored and sev- committed Apr 14, 2018
1 parent 5290d9a commit 61c106b3307ee2f8aaa579dbc5d7c8f8e62ae41a
@@ -0,0 +1,125 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#include "mutationofjb/font.h"
#include "mutationofjb/encryptedfile.h"
#include "mutationofjb/util.h"
#include "common/debug.h"

namespace MutationOfJB {

Font::Font(const Common::String &fileName, int horizSpacing, int vertSpacing) :
_horizSpacing(horizSpacing),
_vertSpacing(vertSpacing) {

load(fileName);
}

bool Font::load(const Common::String &fileName) {
EncryptedFile file;
file.open(fileName);
if (!file.isOpen()) {
reportFileMissingError(fileName.c_str());
return false;
}

file.seek(0x02D6, SEEK_SET); // Skip header + unknown data (unused palette?).

uint16 noGlyphs = 0;
noGlyphs = file.readUint16LE();

file.seek(7, SEEK_CUR); // Skip unknown data (0s).

uint8 maxHeight = 0;

while (noGlyphs--) {
const uint8 character = file.readByte();
const uint8 width = file.readByte();
const uint8 height = file.readByte();

Graphics::ManagedSurface &surf = _glyphs[character];
surf.create(width, height);
for (int h = 0; h < height; ++h) {
file.read(surf.getBasePtr(0, h), width);
}

if (height > maxHeight) {
maxHeight = height;
}
}

if (_vertSpacing == -1) {
_vertSpacing = maxHeight;
}

return true;
}


void Font::drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf) {
GlyphMap::iterator it = _glyphs.find(glyph);
if (it == _glyphs.end()) {
warning("Glyph %d not found", glyph);
return;
}

Graphics::ManagedSurface &glyphSurface = it->_value;

Graphics::ManagedSurface tmp(glyphSurface);
for (int h = 0; h < tmp.h; ++h) {
uint8 *ptr = reinterpret_cast<uint8 *>(tmp.getBasePtr(0, h));
for (int w = 0; w < tmp.w; ++w) {
if (*ptr != 0) {
*ptr = transformColor(baseColor, *ptr);
}
ptr++;
}
}
surf.transBlitFrom(tmp.rawSurface(), Common::Point(x, y));

x += glyphSurface.w + _horizSpacing;
}

void Font::drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf) {
for (uint i = 0; i < str.size(); ++i) {
drawGlyph(str[i], baseColor, x, y, surf); // "x" is updated.
}
}

uint8 Font::transformColor(uint8 baseColor, uint8 glyphColor) {
return baseColor + glyphColor - 0x10;
}

SystemFont::SystemFont() : Font("sysfnt.aft", 1, 7) {}

SpeechFont::SpeechFont() : Font("font1.aft", -1, -1) {}

uint8 SpeechFont::transformColor(uint8 baseColor, uint8 glyphColor) {
// Hack in original game.
if (glyphColor == 0x11) {
return 0xC0;
}

return Font::transformColor(baseColor, glyphColor);
}

}
@@ -0,0 +1,70 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#ifndef MUTATIONOFJB_FONT_H
#define MUTATIONOFJB_FONT_H

#include "common/scummsys.h"
#include "common/hashmap.h"
#include "graphics/managed_surface.h"

namespace Common {
class String;
}

namespace MutationOfJB {

class Font {
public:
Font(const Common::String &fileName, int horizSpacing, int vertSpacing);
virtual ~Font() {}
void drawString(const Common::String &str, uint8 baseColor, int16 x, int16 y, Graphics::ManagedSurface &surf);

protected:
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor);

private:
void drawGlyph(uint8 glyph, uint8 baseColor, int16 &x, int16 &y, Graphics::ManagedSurface &surf);
bool load(const Common::String &fileName);

int _horizSpacing;
int _vertSpacing;
typedef Common::HashMap<uint8, Graphics::ManagedSurface> GlyphMap;
GlyphMap _glyphs;
};

class SystemFont : public Font {
public:
SystemFont();
};

class SpeechFont : public Font {
public:
SpeechFont();

protected:
virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) override;
};

}

#endif
@@ -192,4 +192,12 @@ void Game::setCurrentAction(ActionInfo::Action action) {
_currentAction = action;
}

Font& Game::getSystemFont() {
return _systemFont;
}

Font& Game::getSpeechFont() {
return _speechFont;
}

}
@@ -25,6 +25,7 @@

#include "common/scummsys.h"
#include "mutationofjb/script.h"
#include "mutationofjb/font.h"
#include "mutationofjb/gui.h"

namespace Common {
@@ -64,6 +65,9 @@ class Game {
ActionInfo::Action getCurrentAction() const;
void setCurrentAction(ActionInfo::Action);

Font& getSystemFont();
Font& getSpeechFont();

private:
bool loadGameData(bool partB);
void runActiveCommand();
@@ -81,6 +85,9 @@ class Game {
ActionInfo::Action _currentAction;

ScriptExecutionContext _scriptExecCtx;

SystemFont _systemFont;
SpeechFont _speechFont;
};

}
@@ -30,6 +30,7 @@
#include "mutationofjb/widgets/widget.h"
#include "mutationofjb/widgets/inventorywidget.h"
#include "mutationofjb/widgets/imagewidget.h"
#include "mutationofjb/widgets/conversationwidget.h"
#include "common/rect.h"
#include "graphics/screen.h"

@@ -120,6 +121,12 @@ bool Gui::init() {
_widgets.push_back(button);
}

const Common::Rect conversationRect(CONVERSATION_X, CONVERSATION_Y, CONVERSATION_X + CONVERSATION_WIDTH, CONVERSATION_Y + CONVERSATION_HEIGHT);
const Graphics::Surface conversationSurface =_hudSurfaces[2].getSubArea(conversationRect);
_conversationWidget = new ConversationWidget(*this, conversationRect, conversationSurface);
_conversationWidget->setVisible(false);
_widgets.push_back(_conversationWidget);

return true;
}

@@ -141,6 +148,10 @@ void Gui::update() {
}
}

ConversationWidget& Gui::getConversationWidget() {
return *_conversationWidget;
}

class InventoryAnimationDecoderCallback : public AnimationDecoderCallback {
public:
InventoryAnimationDecoderCallback(Gui &gui) : _gui(gui) {}
@@ -43,9 +43,21 @@ namespace MutationOfJB {
class Game;
class Widget;
class InventoryWidget;
class ConversationWidget;

class Gui : public InventoryObserver, public ButtonWidgetCallback {
public:
enum Colors {
WHITE = 0xC6,
DARKGRAY = 0xC2,
LIGHTGRAY = 0xC4,
GREEN = 0xC8,
ORANGE = 0xCA,
DARKBLUE = 0xD6,
LIGHTBLUE = 0xDA,
BROWN = 0xDC
};

typedef Common::HashMap<Common::String, int> InventoryMap;

friend class InventoryAnimationDecoderCallback;
@@ -64,6 +76,8 @@ class Gui : public InventoryObserver, public ButtonWidgetCallback {
virtual void onInventoryChanged() override;
virtual void onButtonClicked(ButtonWidget *) override;

ConversationWidget& getConversationWidget();

private:
bool loadInventoryGfx();
bool loadHudGfx();
@@ -78,6 +92,7 @@ class Gui : public InventoryObserver, public ButtonWidgetCallback {
Common::Array<Graphics::Surface> _hudSurfaces;

InventoryWidget *_inventoryWidget;
ConversationWidget *_conversationWidget;
Common::Array<Widget *> _widgets;
};

@@ -20,13 +20,15 @@ MODULE_OBJS := \
commands/saycommand.o \
commands/seqcommand.o \
widgets/buttonwidget.o \
widgets/conversationwidget.o \
widgets/imagewidget.o \
widgets/inventorywidget.o \
widgets/widget.o \
animationdecoder.o \
debug.o \
detection.o \
encryptedfile.o \
font.o \
game.o \
gamedata.o \
gui.o \
@@ -0,0 +1,65 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#include "mutationofjb/widgets/conversationwidget.h"
#include "mutationofjb/game.h"
#include "mutationofjb/gui.h"
#include "mutationofjb/font.h"

namespace MutationOfJB {

enum {
CONVERSATION_LINES_X = 5,
CONVERSATION_LINES_Y = 151,
CONVERSATION_LINE_HEIGHT = 12
};

ConversationWidget::ConversationWidget(Gui &gui, const Common::Rect &area, const Graphics::Surface &surface) :
Widget(gui, area),
_surface(surface) {}


void ConversationWidget::setLine(int lineNo, const Common::String &str) {
if (lineNo >= CONVERSATION_LINES) {
return;
}

_lines[lineNo] = str;
markDirty();
}

void ConversationWidget::_draw(Graphics::ManagedSurface &surface) {
surface.blitFrom(_surface, Common::Point(_area.left, _area.top));

for (int i = 0; i < CONVERSATION_LINES; ++i) {
Common::String &line = _lines[i];
if (line.empty()) {
continue;
}

// TODO: Active line should be Gui::WHITE.
_gui.getGame().getSystemFont().drawString(line, Gui::LIGHTGRAY, CONVERSATION_LINES_X, CONVERSATION_LINES_Y + i * CONVERSATION_LINE_HEIGHT, surface);
}
}

}

Oops, something went wrong.

0 comments on commit 61c106b

Please sign in to comment.