From bd3b22b14b4251ea644cceba96334205f797e720 Mon Sep 17 00:00:00 2001 From: Einar Johan Trøan Sømåen Date: Mon, 9 Jul 2012 13:36:37 +0200 Subject: WINTERMUTE: Move font & particle emitter-related code to it's own subfolder --- engines/wintermute/Ad/AdEntity.cpp | 4 +- engines/wintermute/Ad/AdGame.cpp | 4 +- engines/wintermute/Ad/AdItem.cpp | 4 +- engines/wintermute/Ad/AdObject.cpp | 4 +- engines/wintermute/Ad/AdObject.h | 2 +- engines/wintermute/Ad/AdResponse.cpp | 2 +- engines/wintermute/Ad/AdResponseBox.cpp | 4 +- engines/wintermute/Ad/AdScene.cpp | 2 +- engines/wintermute/Ad/AdSentence.cpp | 2 +- engines/wintermute/Base/BFont.cpp | 206 ---- engines/wintermute/Base/BFont.h | 61 - engines/wintermute/Base/BFontBitmap.cpp | 540 --------- engines/wintermute/Base/BFontBitmap.h | 72 -- engines/wintermute/Base/BFontStorage.cpp | 135 --- engines/wintermute/Base/BFontStorage.h | 55 - engines/wintermute/Base/BFontTT.cpp | 758 ------------- engines/wintermute/Base/BFontTT.h | 180 --- engines/wintermute/Base/BGame.cpp | 4 +- engines/wintermute/Base/PartEmitter.cpp | 1199 -------------------- engines/wintermute/Base/PartEmitter.h | 139 --- engines/wintermute/Base/PartForce.cpp | 59 - engines/wintermute/Base/PartForce.h | 57 - engines/wintermute/Base/PartParticle.cpp | 257 ----- engines/wintermute/Base/PartParticle.h | 90 -- engines/wintermute/Base/font/BFont.cpp | 206 ++++ engines/wintermute/Base/font/BFont.h | 61 + engines/wintermute/Base/font/BFontBitmap.cpp | 540 +++++++++ engines/wintermute/Base/font/BFontBitmap.h | 72 ++ engines/wintermute/Base/font/BFontStorage.cpp | 135 +++ engines/wintermute/Base/font/BFontStorage.h | 55 + engines/wintermute/Base/font/BFontTT.cpp | 758 +++++++++++++ engines/wintermute/Base/font/BFontTT.h | 180 +++ engines/wintermute/Base/particles/PartEmitter.cpp | 1199 ++++++++++++++++++++ engines/wintermute/Base/particles/PartEmitter.h | 139 +++ engines/wintermute/Base/particles/PartForce.cpp | 59 + engines/wintermute/Base/particles/PartForce.h | 57 + engines/wintermute/Base/particles/PartParticle.cpp | 257 +++++ engines/wintermute/Base/particles/PartParticle.h | 90 ++ engines/wintermute/UI/UIButton.cpp | 4 +- engines/wintermute/UI/UIEdit.cpp | 4 +- engines/wintermute/UI/UIObject.cpp | 2 +- engines/wintermute/UI/UIText.cpp | 4 +- engines/wintermute/UI/UIWindow.cpp | 4 +- engines/wintermute/module.mk | 14 +- engines/wintermute/persistent.cpp | 6 +- 45 files changed, 3843 insertions(+), 3843 deletions(-) delete mode 100644 engines/wintermute/Base/BFont.cpp delete mode 100644 engines/wintermute/Base/BFont.h delete mode 100644 engines/wintermute/Base/BFontBitmap.cpp delete mode 100644 engines/wintermute/Base/BFontBitmap.h delete mode 100644 engines/wintermute/Base/BFontStorage.cpp delete mode 100644 engines/wintermute/Base/BFontStorage.h delete mode 100644 engines/wintermute/Base/BFontTT.cpp delete mode 100644 engines/wintermute/Base/BFontTT.h delete mode 100644 engines/wintermute/Base/PartEmitter.cpp delete mode 100644 engines/wintermute/Base/PartEmitter.h delete mode 100644 engines/wintermute/Base/PartForce.cpp delete mode 100644 engines/wintermute/Base/PartForce.h delete mode 100644 engines/wintermute/Base/PartParticle.cpp delete mode 100644 engines/wintermute/Base/PartParticle.h create mode 100644 engines/wintermute/Base/font/BFont.cpp create mode 100644 engines/wintermute/Base/font/BFont.h create mode 100644 engines/wintermute/Base/font/BFontBitmap.cpp create mode 100644 engines/wintermute/Base/font/BFontBitmap.h create mode 100644 engines/wintermute/Base/font/BFontStorage.cpp create mode 100644 engines/wintermute/Base/font/BFontStorage.h create mode 100644 engines/wintermute/Base/font/BFontTT.cpp create mode 100644 engines/wintermute/Base/font/BFontTT.h create mode 100644 engines/wintermute/Base/particles/PartEmitter.cpp create mode 100644 engines/wintermute/Base/particles/PartEmitter.h create mode 100644 engines/wintermute/Base/particles/PartForce.cpp create mode 100644 engines/wintermute/Base/particles/PartForce.h create mode 100644 engines/wintermute/Base/particles/PartParticle.cpp create mode 100644 engines/wintermute/Base/particles/PartParticle.h diff --git a/engines/wintermute/Ad/AdEntity.cpp b/engines/wintermute/Ad/AdEntity.cpp index 599afee626..3d9c7f5055 100644 --- a/engines/wintermute/Ad/AdEntity.cpp +++ b/engines/wintermute/Ad/AdEntity.cpp @@ -39,8 +39,8 @@ #include "engines/wintermute/Ad/AdScene.h" #include "engines/wintermute/Base/BSound.h" #include "engines/wintermute/Ad/AdWaypointGroup.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Ad/AdSentence.h" #include "engines/wintermute/Base/BRegion.h" #include "engines/wintermute/Base/BSprite.h" diff --git a/engines/wintermute/Ad/AdGame.cpp b/engines/wintermute/Ad/AdGame.cpp index ed31cd3acb..759c212de8 100644 --- a/engines/wintermute/Ad/AdGame.cpp +++ b/engines/wintermute/Ad/AdGame.cpp @@ -40,7 +40,7 @@ #include "engines/wintermute/Ad/AdSceneState.h" #include "engines/wintermute/Ad/AdSentence.h" #include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BObject.h" #include "engines/wintermute/Base/BParser.h" #include "engines/wintermute/Base/BSound.h" @@ -49,7 +49,7 @@ #include "engines/wintermute/Base/BTransitionMgr.h" #include "engines/wintermute/Base/BSprite.h" #include "engines/wintermute/Base/BViewport.h" -#include "engines/wintermute/Base/PartEmitter.h" +#include "engines/wintermute/Base/particles/PartEmitter.h" #include "engines/wintermute/Base/scriptables/ScEngine.h" #include "engines/wintermute/Base/scriptables/ScScript.h" #include "engines/wintermute/Base/scriptables/ScStack.h" diff --git a/engines/wintermute/Ad/AdItem.cpp b/engines/wintermute/Ad/AdItem.cpp index e8c32607dc..a728a8d048 100644 --- a/engines/wintermute/Ad/AdItem.cpp +++ b/engines/wintermute/Ad/AdItem.cpp @@ -30,8 +30,8 @@ #include "engines/wintermute/Ad/AdItem.h" #include "engines/wintermute/Ad/AdGame.h" #include "engines/wintermute/Ad/AdSentence.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BFileManager.h" #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BParser.h" diff --git a/engines/wintermute/Ad/AdObject.cpp b/engines/wintermute/Ad/AdObject.cpp index 06c63a4d1b..4dd6f4ce4b 100644 --- a/engines/wintermute/Ad/AdObject.cpp +++ b/engines/wintermute/Ad/AdObject.cpp @@ -41,8 +41,8 @@ #include "engines/wintermute/Base/BSound.h" #include "engines/wintermute/Base/BSurfaceStorage.h" #include "engines/wintermute/Base/BSubFrame.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" #include "engines/wintermute/Base/BSprite.h" #include "engines/wintermute/Base/BStringTable.h" #include "engines/wintermute/Base/scriptables/ScEngine.h" diff --git a/engines/wintermute/Ad/AdObject.h b/engines/wintermute/Ad/AdObject.h index c71efce1a5..546089bada 100644 --- a/engines/wintermute/Ad/AdObject.h +++ b/engines/wintermute/Ad/AdObject.h @@ -30,7 +30,7 @@ #define WINTERMUTE_ADOBJECT_H #include "engines/wintermute/Ad/AdTypes.h" -#include "engines/wintermute/Base/PartEmitter.h" +#include "engines/wintermute/Base/particles/PartEmitter.h" namespace WinterMute { diff --git a/engines/wintermute/Ad/AdResponse.cpp b/engines/wintermute/Ad/AdResponse.cpp index 7c6d3f56c9..0b0bea2f57 100644 --- a/engines/wintermute/Ad/AdResponse.cpp +++ b/engines/wintermute/Ad/AdResponse.cpp @@ -29,7 +29,7 @@ #include "engines/wintermute/dcgf.h" #include "engines/wintermute/Ad/AdResponse.h" #include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFontStorage.h" #include "engines/wintermute/Base/BSprite.h" #include "engines/wintermute/utils/utils.h" diff --git a/engines/wintermute/Ad/AdResponseBox.cpp b/engines/wintermute/Ad/AdResponseBox.cpp index cb9a0496d1..c055c2f363 100644 --- a/engines/wintermute/Ad/AdResponseBox.cpp +++ b/engines/wintermute/Ad/AdResponseBox.cpp @@ -34,8 +34,8 @@ #include "engines/wintermute/UI/UIButton.h" #include "engines/wintermute/UI/UIWindow.h" #include "engines/wintermute/Base/BDynBuffer.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Ad/AdResponse.h" #include "engines/wintermute/Base/scriptables/ScScript.h" #include "engines/wintermute/Base/scriptables/ScStack.h" diff --git a/engines/wintermute/Ad/AdScene.cpp b/engines/wintermute/Ad/AdScene.cpp index 41b413cc14..b338232c98 100644 --- a/engines/wintermute/Ad/AdScene.cpp +++ b/engines/wintermute/Ad/AdScene.cpp @@ -43,7 +43,7 @@ #include "engines/wintermute/Ad/AdWaypointGroup.h" #include "engines/wintermute/Base/BDynBuffer.h" #include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BObject.h" #include "engines/wintermute/Base/BParser.h" diff --git a/engines/wintermute/Ad/AdSentence.cpp b/engines/wintermute/Ad/AdSentence.cpp index ed43630e0c..7d37efce49 100644 --- a/engines/wintermute/Ad/AdSentence.cpp +++ b/engines/wintermute/Ad/AdSentence.cpp @@ -35,7 +35,7 @@ #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BSound.h" #include "engines/wintermute/Ad/AdScene.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BSprite.h" #include "engines/wintermute/Base/BFileManager.h" diff --git a/engines/wintermute/Base/BFont.cpp b/engines/wintermute/Base/BFont.cpp deleted file mode 100644 index 1849401e53..0000000000 --- a/engines/wintermute/Base/BFont.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BFontBitmap.h" -#include "engines/wintermute/Base/BParser.h" -#include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/Base/BFontTT.h" -#include "engines/wintermute/Base/BGame.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFont, false) - -////////////////////////////////////////////////////////////////////// -CBFont::CBFont(CBGame *inGame): CBObject(inGame) { - -} - - -////////////////////////////////////////////////////////////////////// -CBFont::~CBFont() { -} - - -////////////////////////////////////////////////////////////////////// -void CBFont::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { -} - - -////////////////////////////////////////////////////////////////////// -int CBFont::getTextHeight(byte *text, int width) { - return 0; -} - - -////////////////////////////////////////////////////////////////////// -int CBFont::getTextWidth(byte *text, int maxLength) { - return 0; -} - -/* -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFont::loadFile(const char * Filename) -{ - BYTE* Buffer = Game->_fileManager->readWholeFile(filename); - if(Buffer==NULL){ - Game->LOG(0, "CBFont::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - ERRORCODE ret; - - _filename = new char [strlen(filename)+1]; - strcpy(_filename, filename); - - if(DID_FAIL(ret = loadBuffer(Buffer))) Game->LOG(0, "Error parsing FONT file '%s'", filename); - - delete [] Buffer; - - return ret; -} - - -TOKEN_DEF_START - TOKEN_DEF (FONT) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFont::loadBuffer(byte * Buffer) -{ - TOKEN_TABLE_START(commands) - TOKEN_TABLE (FONT) - TOKEN_TABLE_END - - char* params; - int cmd; - CBParser parser(Game); - - if(parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)!=TOKEN_FONT){ - Game->LOG(0, "'FONT' keyword expected."); - return STATUS_FAILED; - } - Buffer = (byte *)params; - - while ((cmd = parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)) > 0) - { - switch (cmd) - { - case TOKEN_IMAGE: - surface_file = (char*)params; - break; - - case TOKEN_TRANSPARENT: - parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custo_trans = true; - break; - } - - - } - if (cmd == PARSERR_TOKENNOTFOUND){ - Game->LOG(0, "Syntax error in FONT definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} -*/ - -////////////////////////////////////////////////////////////////////////// -int CBFont::getLetterHeight() { - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFont::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBFont *CBFont::createFromFile(CBGame *Game, const char *filename) { - if (isTrueType(Game, filename)) { - CBFontTT *font = new CBFontTT(Game); - if (font) { - if (DID_FAIL(font->loadFile(filename))) { - delete font; - return NULL; - } - } - return font; - } else { - CBFontBitmap *font = new CBFontBitmap(Game); - if (font) { - if (DID_FAIL(font->loadFile(filename))) { - delete font; - return NULL; - } - } - return font; - } -} - - -TOKEN_DEF_START -TOKEN_DEF(FONT) -TOKEN_DEF(TTFONT) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool CBFont::isTrueType(CBGame *Game, const char *filename) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TTFONT) - TOKEN_TABLE_END - - - byte *buffer = Game->_fileManager->readWholeFile(filename); - if (buffer == NULL) return false; - - byte *WorkBuffer = buffer; - - char *params; - CBParser parser(Game); - - bool ret = false; - if (parser.getCommand((char **)&WorkBuffer, commands, (char **)¶ms) == TOKEN_TTFONT) - ret = true; - - delete [] buffer; - return ret; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/BFont.h b/engines/wintermute/Base/BFont.h deleted file mode 100644 index ac5a79299d..0000000000 --- a/engines/wintermute/Base/BFont.h +++ /dev/null @@ -1,61 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONT_H -#define WINTERMUTE_BFONT_H - -#include "engines/wintermute/Base/BObject.h" - -#define NUM_CHARACTERS 256 - -namespace WinterMute { - -class CBFont: public CBObject { -public: - DECLARE_PERSISTENT(CBFont, CBObject) - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); - virtual int getLetterHeight(); - - virtual void initLoop() {}; - virtual void afterLoad() {}; - CBFont(CBGame *inGame); - virtual ~CBFont(); - - static CBFont *createFromFile(CBGame *game, const char *filename); - -private: - //ERRORCODE loadBuffer(byte * Buffer); - //ERRORCODE loadFile(const char* Filename); - static bool isTrueType(CBGame *game, const char *filename); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/BFontBitmap.cpp b/engines/wintermute/Base/BFontBitmap.cpp deleted file mode 100644 index b913eea3ee..0000000000 --- a/engines/wintermute/Base/BFontBitmap.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/BFontBitmap.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/Base/BParser.h" -#include "engines/wintermute/Base/BFrame.h" -#include "engines/wintermute/Base/BSurface.h" -#include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/Base/BSubFrame.h" -#include "engines/wintermute/Base/BFrame.h" -#include "engines/wintermute/Base/BSprite.h" -#include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/PlatformSDL.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFontBitmap, false) - -////////////////////////////////////////////////////////////////////// -CBFontBitmap::CBFontBitmap(CBGame *inGame): CBFont(inGame) { - _subframe = NULL; - _sprite = NULL; - _widthsFrame = 0; - memset(_widths, 0, NUM_CHARACTERS); - _tileWidth = _tileHeight = _numColumns = 0; - _fontextFix = false; - _freezable = false; - _wholeCell = false; -} - - -////////////////////////////////////////////////////////////////////// -CBFontBitmap::~CBFontBitmap() { - delete _subframe; - delete _sprite; - _subframe = NULL; - _sprite = NULL; -} - - -////////////////////////////////////////////////////////////////////// -void CBFontBitmap::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { - textHeightDraw(text, x, y, width, align, true, max_height, maxLength); -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getTextHeight(byte *text, int width) { - return textHeightDraw(text, 0, 0, width, TAL_LEFT, false); -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getTextWidth(byte *text, int maxLength) { - AnsiString str; - - if (Game->_textEncoding == TEXT_UTF8) { - WideString wstr = StringUtil::utf8ToWide(Utf8String((char *)text)); - str = StringUtil::wideToAnsi(wstr); - } else { - str = AnsiString((char *)text); - } - - if (maxLength >= 0 && str.size() > (uint32)maxLength) - str = Common::String(str.c_str(), (uint32)maxLength); - //str.substr(0, maxLength); // TODO: Remove - - int textWidth = 0; - for (size_t i = 0; i < str.size(); i++) { - textWidth += getCharWidth(str[i]); - } - - return textWidth; -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::textHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int maxHeight, int maxLength) { - if (maxLength == 0) return 0; - - if (text == NULL || text[0] == '\0') return _tileHeight; - - AnsiString str; - - if (Game->_textEncoding == TEXT_UTF8) { - WideString wstr = StringUtil::utf8ToWide(Utf8String((char *)text)); - str = StringUtil::wideToAnsi(wstr); - } else { - str = AnsiString((char *)text); - } - if (str.empty()) return 0; - - int LineLength = 0; - int RealLength = 0; - int NumLines = 0; - - int i; - - int index = -1; - int start = 0; - int end = 0; - int last_end = 0; - - bool done = false; - bool new_line = false; - bool long_line = false; - - if (draw) Game->_renderer->startSpriteBatch(); - - while (!done) { - if (maxHeight > 0 && (NumLines + 1)*_tileHeight > maxHeight) { - if (draw) Game->_renderer->endSpriteBatch(); - return NumLines * _tileHeight; - } - - index++; - - if (str[index] == ' ' && (maxHeight < 0 || maxHeight / _tileHeight > 1)) { - end = index - 1; - RealLength = LineLength; - } - - if (str[index] == '\n') { - end = index - 1; - RealLength = LineLength; - new_line = true; - } - - if (LineLength + getCharWidth(str[index]) > width && last_end == end) { - end = index - 1; - RealLength = LineLength; - new_line = true; - long_line = true; - } - - if (str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) { - done = true; - if (!new_line) { - end = index; - LineLength += getCharWidth(str[index]); - RealLength = LineLength; - } - } else LineLength += getCharWidth(str[index]); - - if ((LineLength > width) || done || new_line) { - if (end < 0) done = true; - int StartX; - switch (align) { - case TAL_CENTER: - StartX = x + (width - RealLength) / 2; - break; - case TAL_RIGHT: - StartX = x + width - RealLength; - break; - case TAL_LEFT: - StartX = x; - break; - default: - error("CBFontBitmap::TextHeightDraw - Unhandled enum"); - break; - } - for (i = start; i < end + 1; i++) { - if (draw) drawChar(str[i], StartX, y); - StartX += getCharWidth(str[i]); - } - y += _tileHeight; - last_end = end; - if (long_line) end--; - start = end + 2; - index = end + 1; - LineLength = 0; - new_line = false; - long_line = false; - NumLines++; - } - } - - if (draw) Game->_renderer->endSpriteBatch(); - - return NumLines * _tileHeight; -} - - -////////////////////////////////////////////////////////////////////// -void CBFontBitmap::drawChar(byte c, int x, int y) { - if (_fontextFix) c--; - - int row, col; - - row = c / _numColumns; - col = c % _numColumns; - - Rect32 rect; - /* l t r b */ - int tileWidth; - if (_wholeCell) tileWidth = _tileWidth; - else tileWidth = _widths[c]; - - CBPlatform::setRect(&rect, col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1)*_tileHeight); - bool handled = false; - if (_sprite) { - _sprite->GetCurrentFrame(); - if (_sprite->_currentFrame >= 0 && _sprite->_currentFrame < _sprite->_frames.getSize() && _sprite->_frames[_sprite->_currentFrame]) { - if (_sprite->_frames[_sprite->_currentFrame]->_subframes.getSize() > 0) { - _sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect); - } - handled = true; - } - } - if (!handled && _subframe) _subframe->_surface->displayTrans(x, y, rect); -} - - -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontBitmap::loadFile(const char *filename) { - byte *buffer = Game->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - Game->LOG(0, "CBFontBitmap::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - ERRORCODE ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - if (DID_FAIL(ret = loadBuffer(buffer))) Game->LOG(0, "Error parsing FONT file '%s'", filename); - - delete [] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(FONTEXT_FIX) -TOKEN_DEF(FONT) -TOKEN_DEF(IMAGE) -TOKEN_DEF(TRANSPARENT) -TOKEN_DEF(COLUMNS) -TOKEN_DEF(TILE_WIDTH) -TOKEN_DEF(TILE_HEIGHT) -TOKEN_DEF(DEFAULT_WIDTH) -TOKEN_DEF(WIDTHS) -TOKEN_DEF(AUTO_WIDTH) -TOKEN_DEF(SPACE_WIDTH) -TOKEN_DEF(EXPAND_WIDTH) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(SPRITE) -TOKEN_DEF(WIDTHS_FRAME) -TOKEN_DEF(PAINT_WHOLE_CELL) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontBitmap::loadBuffer(byte *buffer) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(FONTEXT_FIX) - TOKEN_TABLE(FONT) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(TRANSPARENT) - TOKEN_TABLE(COLUMNS) - TOKEN_TABLE(TILE_WIDTH) - TOKEN_TABLE(TILE_HEIGHT) - TOKEN_TABLE(DEFAULT_WIDTH) - TOKEN_TABLE(WIDTHS) - TOKEN_TABLE(AUTO_WIDTH) - TOKEN_TABLE(SPACE_WIDTH) - TOKEN_TABLE(EXPAND_WIDTH) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(SPRITE) - TOKEN_TABLE(WIDTHS_FRAME) - TOKEN_TABLE(PAINT_WHOLE_CELL) - TOKEN_TABLE_END - - char *params; - int cmd; - CBParser parser(Game); - - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_FONT) { - Game->LOG(0, "'FONT' keyword expected."); - return STATUS_FAILED; - } - buffer = (byte *)params; - - int widths[300]; - int num = 0, default_width = 8; - int lastWidth = 0; - int i; - int r = 255, g = 255, b = 255; - bool custoTrans = false; - char *surfaceFile = NULL; - char *spriteFile = NULL; - - bool autoWidth = false; - int spaceWidth = 0; - int expandWidth = 0; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - - switch (cmd) { - case TOKEN_IMAGE: - surfaceFile = (char *)params; - break; - - case TOKEN_SPRITE: - spriteFile = (char *)params; - break; - - case TOKEN_TRANSPARENT: - parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custoTrans = true; - break; - - case TOKEN_WIDTHS: - parser.scanStr(params, "%D", widths, &num); - for (i = 0; lastWidth < NUM_CHARACTERS, num > 0; lastWidth++, num--, i++) { - _widths[lastWidth] = (byte)widths[i]; - } - break; - - case TOKEN_DEFAULT_WIDTH: - parser.scanStr(params, "%d", &default_width); - break; - - case TOKEN_WIDTHS_FRAME: - parser.scanStr(params, "%d", &_widthsFrame); - break; - - case TOKEN_COLUMNS: - parser.scanStr(params, "%d", &_numColumns); - break; - - case TOKEN_TILE_WIDTH: - parser.scanStr(params, "%d", &_tileWidth); - break; - - case TOKEN_TILE_HEIGHT: - parser.scanStr(params, "%d", &_tileHeight); - break; - - case TOKEN_AUTO_WIDTH: - parser.scanStr(params, "%b", &autoWidth); - break; - - case TOKEN_FONTEXT_FIX: - parser.scanStr(params, "%b", &_fontextFix); - break; - - case TOKEN_PAINT_WHOLE_CELL: - parser.scanStr(params, "%b", &_wholeCell); - break; - - case TOKEN_SPACE_WIDTH: - parser.scanStr(params, "%d", &spaceWidth); - break; - - case TOKEN_EXPAND_WIDTH: - parser.scanStr(params, "%d", &expandWidth); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty((byte *)params, false); - break; - } - - } - if (cmd == PARSERR_TOKENNOTFOUND) { - Game->LOG(0, "Syntax error in FONT definition"); - return STATUS_FAILED; - } - - if (spriteFile != NULL) { - delete _sprite; - _sprite = new CBSprite(Game, this); - if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) { - delete _sprite; - _sprite = NULL; - } - } - - if (surfaceFile != NULL && !_sprite) { - _subframe = new CBSubFrame(Game); - if (custoTrans) _subframe->setSurface(surfaceFile, false, r, g, b); - else _subframe->setSurface(surfaceFile); - } - - - if (((_subframe == NULL || _subframe->_surface == NULL) && _sprite == NULL) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) { - Game->LOG(0, "Incomplete font definition"); - return STATUS_FAILED; - } - - if (autoWidth) { - // calculate characters width - getWidths(); - - // do we need to modify widths? - if (expandWidth != 0) { - for (i = 0; i < NUM_CHARACTERS; i++) { - int NewWidth = (int)_widths[i] + expandWidth; - if (NewWidth < 0) NewWidth = 0; - - _widths[i] = (byte)NewWidth; - } - } - - // handle space character - uint32 spaceChar = ' '; - if (_fontextFix) spaceChar--; - - if (spaceWidth != 0) _widths[spaceChar] = spaceWidth; - else { - if (_widths[spaceChar] == expandWidth || _widths[spaceChar] == 0) { - _widths[spaceChar] = (_widths['m'] + _widths['i']) / 2; - } - } - } else { - for (i = lastWidth; i < NUM_CHARACTERS; i++) _widths[i] = default_width; - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontBitmap::persist(CBPersistMgr *persistMgr) { - - CBFont::persist(persistMgr); - persistMgr->transfer(TMEMBER(_numColumns)); - - persistMgr->transfer(TMEMBER(_subframe)); - persistMgr->transfer(TMEMBER(_tileHeight)); - persistMgr->transfer(TMEMBER(_tileWidth)); - persistMgr->transfer(TMEMBER(_sprite)); - persistMgr->transfer(TMEMBER(_widthsFrame)); - - if (persistMgr->_saving) - persistMgr->putBytes(_widths, sizeof(_widths)); - else - persistMgr->getBytes(_widths, sizeof(_widths)); - - - persistMgr->transfer(TMEMBER(_fontextFix)); - persistMgr->transfer(TMEMBER(_wholeCell)); - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getCharWidth(byte index) { - if (_fontextFix) index--; - return _widths[index]; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontBitmap::getWidths() { - CBSurface *surf = NULL; - - if (_sprite) { - if (_widthsFrame >= 0 && _widthsFrame < _sprite->_frames.getSize()) { - if (_sprite->_frames[_widthsFrame] && _sprite->_frames[_widthsFrame]->_subframes.getSize() > 0) { - surf = _sprite->_frames[_widthsFrame]->_subframes[0]->_surface; - } - } - } - if (surf == NULL && _subframe) surf = _subframe->_surface; - if (!surf || DID_FAIL(surf->startPixelOp())) return STATUS_FAILED; - - - for (int i = 0; i < NUM_CHARACTERS; i++) { - int xxx = (i % _numColumns) * _tileWidth; - int yyy = (i / _numColumns) * _tileHeight; - - - int minCol = -1; - for (int row = 0; row < _tileHeight; row++) { - for (int col = _tileWidth - 1; col >= minCol + 1; col--) { - if (xxx + col < 0 || xxx + col >= surf->getWidth() || yyy + row < 0 || yyy + row >= surf->getHeight()) continue; - if (!surf->isTransparentAtLite(xxx + col, yyy + row)) { - //min_col = col; - minCol = MAX(col, minCol); - break; - } - } - if (minCol == _tileWidth - 1) break; - } - - _widths[i] = minCol + 1; - } - surf->endPixelOp(); - /* - Game->LOG(0, "----- %s ------", _filename); - for(int j=0; j<16; j++) - { - Game->LOG(0, "%02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d", _widths[j*16+0], _widths[j*16+1], _widths[j*16+2], _widths[j*16+3], _widths[j*16+4], _widths[j*16+5], _widths[j*16+6], _widths[j*16+7], _widths[j*16+8], _widths[j*16+9], _widths[j*16+10], _widths[j*16+11], _widths[j*16+12], _widths[j*16+13], _widths[j*16+14], _widths[j*16+15]); - } - */ - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getLetterHeight() { - return _tileHeight; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/BFontBitmap.h b/engines/wintermute/Base/BFontBitmap.h deleted file mode 100644 index 3cd0d91e77..0000000000 --- a/engines/wintermute/Base/BFontBitmap.h +++ /dev/null @@ -1,72 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTBITMAP_H -#define WINTERMUTE_BFONTBITMAP_H - - -#include "engines/wintermute/Base/BFont.h" - -namespace WinterMute { -class CBSubFrame; -class CBFontBitmap : public CBFont { -public: - DECLARE_PERSISTENT(CBFontBitmap, CBFont) - ERRORCODE loadBuffer(byte *Buffer); - ERRORCODE loadFile(const char *filename); - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); - virtual int getLetterHeight(); - - CBFontBitmap(CBGame *inGame); - virtual ~CBFontBitmap(); - - - ERRORCODE getWidths(); - CBSprite *_sprite; - int _widthsFrame; - bool _fontextFix; - int _numColumns; - int _tileHeight; - int _tileWidth; - byte _widths[NUM_CHARACTERS]; - CBSubFrame *_subframe; - bool _wholeCell; - -private: - int getCharWidth(byte index); - void drawChar(byte c, int x, int y); - - int textHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int MaxLength = -1); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/BFontStorage.cpp b/engines/wintermute/Base/BFontStorage.cpp deleted file mode 100644 index 8b43510708..0000000000 --- a/engines/wintermute/Base/BFontStorage.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/PlatformSDL.h" -#include "common/str.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFontStorage, true) - -////////////////////////////////////////////////////////////////////////// -CBFontStorage::CBFontStorage(CBGame *inGame): CBBase(inGame) { -} - -////////////////////////////////////////////////////////////////////////// -CBFontStorage::~CBFontStorage() { - cleanup(true); -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontStorage::cleanup(bool warn) { - for (int i = 0; i < _fonts.getSize(); i++) { - if (warn) Game->LOG(0, "Removing orphan font '%s'", _fonts[i]->_filename); - delete _fonts[i]; - } - _fonts.removeAll(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontStorage::initLoop() { - for (int i = 0; i < _fonts.getSize(); i++) { - _fonts[i]->initLoop(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CBFont *CBFontStorage::addFont(const char *filename) { - if (!filename) return NULL; - - for (int i = 0; i < _fonts.getSize(); i++) { - if (scumm_stricmp(_fonts[i]->_filename, filename) == 0) { - _fonts[i]->_refCount++; - return _fonts[i]; - } - } - - /* - CBFont* font = new CBFont(Game); - if (!font) return NULL; - - if (DID_FAIL(font->loadFile(filename))) { - delete font; - return NULL; - } - else { - font->_refCount = 1; - _fonts.add(font); - return font; - } - */ - CBFont *font = CBFont::createFromFile(Game, filename); - if (font) { - font->_refCount = 1; - _fonts.add(font); - } - return font; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontStorage::removeFont(CBFont *font) { - if (!font) return STATUS_FAILED; - - for (int i = 0; i < _fonts.getSize(); i++) { - if (_fonts[i] == font) { - _fonts[i]->_refCount--; - if (_fonts[i]->_refCount <= 0) { - delete _fonts[i]; - _fonts.removeAt(i); - } - break; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontStorage::persist(CBPersistMgr *persistMgr) { - - if (!persistMgr->_saving) cleanup(false); - - persistMgr->transfer(TMEMBER(Game)); - _fonts.persist(persistMgr); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/BFontStorage.h b/engines/wintermute/Base/BFontStorage.h deleted file mode 100644 index 33a1bb056f..0000000000 --- a/engines/wintermute/Base/BFontStorage.h +++ /dev/null @@ -1,55 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTSTORAGE_H -#define WINTERMUTE_BFONTSTORAGE_H - - -#include "engines/wintermute/Base/BBase.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/coll_templ.h" - -namespace WinterMute { - -class CBFont; - -class CBFontStorage : public CBBase { -public: - DECLARE_PERSISTENT(CBFontStorage, CBBase) - ERRORCODE cleanup(bool warn = false); - ERRORCODE removeFont(CBFont *font); - CBFont *addFont(const char *filename); - CBFontStorage(CBGame *inGame); - virtual ~CBFontStorage(); - CBArray _fonts; - ERRORCODE initLoop(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/BFontTT.cpp b/engines/wintermute/Base/BFontTT.cpp deleted file mode 100644 index 10d552d4e2..0000000000 --- a/engines/wintermute/Base/BFontTT.cpp +++ /dev/null @@ -1,758 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/file/BFile.h" -#include "engines/wintermute/Base/BFontTT.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/math/MathUtil.h" -#include "engines/wintermute/Base/BRenderer.h" -#include "engines/wintermute/Base/BSurface.h" -#include "engines/wintermute/Base/BParser.h" -#include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/PlatformSDL.h" -#include "graphics/fonts/ttf.h" -#include "graphics/fontman.h" -#include - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBFontTT, false) - -////////////////////////////////////////////////////////////////////////// -CBFontTT::CBFontTT(CBGame *inGame): CBFont(inGame) { - _fontHeight = 12; - _isBold = _isItalic = _isUnderline = _isStriked = false; - - _fontFile = NULL; - _font = NULL; - _fallbackFont = NULL; - _deletableFont = NULL; - - for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; - -#if 0 - _fTFace = NULL; - _fTStream = NULL; -#endif - - _ascender = _descender = _lineHeight = _pointSize = _underlinePos = 0; - _horDpi = _vertDpi = 0; - _maxCharWidth = _maxCharHeight = 0; -} - -////////////////////////////////////////////////////////////////////////// -CBFontTT::~CBFontTT(void) { - clearCache(); - - for (int i = 0; i < _layers.getSize(); i++) { - delete _layers[i]; - } - _layers.removeAll(); - - delete[] _fontFile; - _fontFile = NULL; - - delete _deletableFont; - _font = NULL; - -#if 0 - if (_fTFace) { - FT_Done_Face(_fTFace); - _fTFace = NULL; - } - delete[] _fTStream; - _fTStream = NULL; -#endif -} - - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::clearCache() { - for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i]) delete _cachedTexts[i]; - _cachedTexts[i] = NULL; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::initLoop() { - // we need more aggressive cache management on iOS not to waste too much memory on fonts - if (Game->_constrainedMemory) { - // purge all cached images not used in the last frame - for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i] == NULL) continue; - - if (!_cachedTexts[i]->_marked) { - delete _cachedTexts[i]; - _cachedTexts[i] = NULL; - } else _cachedTexts[i]->_marked = false; - } - } -} - -////////////////////////////////////////////////////////////////////////// -int CBFontTT::getTextWidth(byte *text, int maxLength) { - WideString textStr; - - if (Game->_textEncoding == TEXT_UTF8) textStr = StringUtil::utf8ToWide((char *)text); - else textStr = StringUtil::ansiToWide((char *)text); - - if (maxLength >= 0 && textStr.size() > (uint32)maxLength) - textStr = Common::String(textStr.c_str(), (uint32)maxLength); - //text = text.substr(0, MaxLength); // TODO: Remove - - int textWidth, textHeight; - measureText(textStr, -1, -1, textWidth, textHeight); - - return textWidth; -} - -////////////////////////////////////////////////////////////////////////// -int CBFontTT::getTextHeight(byte *text, int width) { - WideString textStr; - - if (Game->_textEncoding == TEXT_UTF8) textStr = StringUtil::utf8ToWide((char *)text); - else textStr = StringUtil::ansiToWide((char *)text); - - - int textWidth, textHeight; - measureText(textStr, width, -1, textWidth, textHeight); - - return textHeight; -} - - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::drawText(byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { - if (text == NULL || strcmp((char *)text, "") == 0) return; - - WideString textStr = (char *)text; - - // TODO: Why do we still insist on Widestrings everywhere? - /* if (Game->_textEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); - else text = StringUtil::AnsiToWide((char *)Text);*/ - - if (maxLength >= 0 && textStr.size() > (uint32)maxLength) - textStr = Common::String(textStr.c_str(), (uint32)maxLength); - //text = text.substr(0, MaxLength); // TODO: Remove - - CBRenderer *renderer = Game->_renderer; - - // find cached surface, if exists - int minPriority = INT_MAX; - int minIndex = -1; - CBSurface *surface = NULL; - int textOffset = 0; - - for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i] == NULL) { - minPriority = 0; - minIndex = i; - } else { - if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) { - surface = _cachedTexts[i]->_surface; - textOffset = _cachedTexts[i]->_textOffset; - _cachedTexts[i]->_priority++; - _cachedTexts[i]->_marked = true; - break; - } else { - if (_cachedTexts[i]->_priority < minPriority) { - minPriority = _cachedTexts[i]->_priority; - minIndex = i; - } - } - } - } - - // not found, create one - if (!surface) { - warning("Draw text: %s", text); - surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset); - if (surface) { - // write surface to cache - if (_cachedTexts[minIndex] != NULL) delete _cachedTexts[minIndex]; - _cachedTexts[minIndex] = new CBCachedTTFontText; - - _cachedTexts[minIndex]->_surface = surface; - _cachedTexts[minIndex]->_align = align; - _cachedTexts[minIndex]->_width = width; - _cachedTexts[minIndex]->_maxHeight = maxHeight; - _cachedTexts[minIndex]->_maxLength = maxLength; - _cachedTexts[minIndex]->_priority = 1; - _cachedTexts[minIndex]->_text = textStr; - _cachedTexts[minIndex]->_textOffset = textOffset; - _cachedTexts[minIndex]->_marked = true; - } - } - - - // and paint it - if (surface) { - Rect32 rc; - CBPlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight()); - for (int i = 0; i < _layers.getSize(); i++) { - uint32 color = _layers[i]->_color; - uint32 origForceAlpha = renderer->_forceAlphaColor; - if (renderer->_forceAlphaColor != 0) { - color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor)); - renderer->_forceAlphaColor = 0; - } - surface->displayTransOffset(x, y - textOffset, rc, color, BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY); - - renderer->_forceAlphaColor = origForceAlpha; - } - } - - -} - -////////////////////////////////////////////////////////////////////////// -CBSurface *CBFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { - //TextLineList lines; - // TODO - //WrapText(text, width, maxHeight, lines); - Common::Array lines; - _font->wordWrapText(text, width, lines); - - Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; - if (align == TAL_LEFT) { - alignment = Graphics::kTextAlignLeft; - } else if (align == TAL_CENTER) { - alignment = Graphics::kTextAlignCenter; - } else if (align == TAL_RIGHT) { - alignment = Graphics::kTextAlignRight; - } - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("CBFontTT::RenderTextToTexture - Not fully ported yet"); - } - warning("%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); -// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; - Graphics::Surface *surface = new Graphics::Surface(); - surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15)); - - uint16 useColor = 0xffff; - Common::Array::iterator it; - int heightOffset = 0; - for (it = lines.begin(); it != lines.end(); it++) { - _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); - heightOffset += (int)_lineHeight; - } - - CBSurface *retSurface = Game->_renderer->createSurface(); - Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8 , 0)); - retSurface->putSurface(*convertedSurface, true); - convertedSurface->free(); - surface->free(); - delete surface; - delete convertedSurface; - return retSurface; -#if 0 //TODO - int textHeight = lines.size() * (_maxCharHeight + _ascender); - SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); - - SDL_LockSurface(surface); - - int posY = (int)GetLineHeight() - (int)_descender; - - for (it = lines.begin(); it != lines.end(); ++it) { - TextLine *line = (*it); - int posX = 0; - - switch (align) { - case TAL_CENTER: - posX += (width - line->GetWidth()) / 2; - break; - - case TAL_RIGHT: - posX += width - line->GetWidth(); - break; - } - - - textOffset = 0; - for (size_t i = 0; i < line->GetText().size(); i++) { - wchar_t ch = line->GetText()[i]; - - GlyphInfo *glyph = _glyphCache->GetGlyph(ch); - if (!glyph) continue; - - textOffset = MAX(textOffset, glyph->GetBearingY()); - } - - - int origPosX = posX; - - wchar_t prevChar = L'\0'; - for (size_t i = 0; i < line->GetText().size(); i++) { - wchar_t ch = line->GetText()[i]; - - GlyphInfo *glyph = _glyphCache->GetGlyph(ch); - if (!glyph) continue; - - float kerning = 0; - if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); - posX += (int)kerning; - - - if (glyph->GetBearingY() > 0) { - int i = 10; - } - - SDL_Rect rect; - rect.x = posX + glyph->GetBearingX(); - rect.y = posY - glyph->GetBearingY() + textOffset; - rect.w = glyph->GetImage()->w; - rect.h = glyph->GetImage()->h; - - BlitSurface(glyph->GetImage(), surface, &rect); - - prevChar = ch; - posX += (int)(glyph->GetAdvanceX()); - posY += (int)(glyph->GetAdvanceY()); - } - - if (_isUnderline) { - for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { - Uint8 *buf = (Uint8 *)surface->pixels + (int)(_underlinePos + _ascender) * surface->pitch; - Uint32 *buf32 = (Uint32 *)buf; - - buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); - } - } - - SDL_UnlockSurface(surface); - - delete line; - line = NULL; - posY += GetLineHeight(); - } - - CBSurfaceSDL *wmeSurface = new CBSurfaceSDL(Game); - if (DID_SUCCEED(wmeSurface->CreateFromSDLSurface(surface))) { - SDL_FreeSurface(surface); - return wmeSurface; - } else { - SDL_FreeSurface(surface); - delete wmeSurface; - return NULL; - } -#endif - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect) { - //SDL_BlitSurface(src, NULL, target, targetRect); - warning("CBFontTT::BlitSurface - not ported yet"); -#if 0 - for (int y = 0; y < src->h; y++) { - if (targetRect->y + y < 0 || targetRect->y + y >= target->h) continue; - - - uint8 *srcBuf = (uint8 *)src->pixels + y * src->pitch; - uint8 *tgtBuf = (uint8 *)target->pixels + (y + targetRect->y) * target->pitch; - - uint32 *srcBuf32 = (uint32 *)srcBuf; - uint32 *tgtBuf32 = (uint32 *)tgtBuf; - - for (int x = 0; x < src->w; x++) { - if (targetRect->x + x < 0 || targetRect->x + x >= target->w) continue; - - tgtBuf32[x + targetRect->x] = srcBuf32[x]; - } - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -int CBFontTT::getLetterHeight() { - return (int)getLineHeight(); -} - - -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontTT::loadFile(const char *filename) { - byte *buffer = Game->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - Game->LOG(0, "CBFontTT::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - ERRORCODE ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - if (DID_FAIL(ret = loadBuffer(buffer))) Game->LOG(0, "Error parsing TTFONT file '%s'", filename); - - delete [] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(TTFONT) -TOKEN_DEF(SIZE) -TOKEN_DEF(FACE) -TOKEN_DEF(FILENAME) -TOKEN_DEF(BOLD) -TOKEN_DEF(ITALIC) -TOKEN_DEF(UNDERLINE) -TOKEN_DEF(STRIKE) -TOKEN_DEF(CHARSET) -TOKEN_DEF(COLOR) -TOKEN_DEF(ALPHA) -TOKEN_DEF(LAYER) -TOKEN_DEF(OFFSET_X) -TOKEN_DEF(OFFSET_Y) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontTT::loadBuffer(byte *buffer) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(TTFONT) - TOKEN_TABLE(SIZE) - TOKEN_TABLE(FACE) - TOKEN_TABLE(FILENAME) - TOKEN_TABLE(BOLD) - TOKEN_TABLE(ITALIC) - TOKEN_TABLE(UNDERLINE) - TOKEN_TABLE(STRIKE) - TOKEN_TABLE(CHARSET) - TOKEN_TABLE(COLOR) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(LAYER) - TOKEN_TABLE_END - - char *params; - int cmd; - CBParser parser(Game); - - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TTFONT) { - Game->LOG(0, "'TTFONT' keyword expected."); - return STATUS_FAILED; - } - buffer = (byte *)params; - - uint32 BaseColor = 0x00000000; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_SIZE: - parser.scanStr(params, "%d", &_fontHeight); - break; - - case TOKEN_FACE: - // we don't need this anymore - break; - - case TOKEN_FILENAME: - CBUtils::setString(&_fontFile, params); - break; - - case TOKEN_BOLD: - parser.scanStr(params, "%b", &_isBold); - break; - - case TOKEN_ITALIC: - parser.scanStr(params, "%b", &_isItalic); - break; - - case TOKEN_UNDERLINE: - parser.scanStr(params, "%b", &_isUnderline); - break; - - case TOKEN_STRIKE: - parser.scanStr(params, "%b", &_isStriked); - break; - - case TOKEN_CHARSET: - // we don't need this anymore - break; - - case TOKEN_COLOR: { - int r, g, b; - parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - BaseColor = BYTETORGBA(r, g, b, RGBCOLGetA(BaseColor)); - } - break; - - case TOKEN_ALPHA: { - int a; - parser.scanStr(params, "%d", &a); - BaseColor = BYTETORGBA(RGBCOLGetR(BaseColor), RGBCOLGetG(BaseColor), RGBCOLGetB(BaseColor), a); - } - break; - - case TOKEN_LAYER: { - CBTTFontLayer *Layer = new CBTTFontLayer; - if (Layer && DID_SUCCEED(parseLayer(Layer, (byte *)params))) _layers.add(Layer); - else { - delete Layer; - Layer = NULL; - cmd = PARSERR_TOKENNOTFOUND; - } - } - break; - - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - Game->LOG(0, "Syntax error in TTFONT definition"); - return STATUS_FAILED; - } - - // create at least one layer - if (_layers.getSize() == 0) { - CBTTFontLayer *Layer = new CBTTFontLayer; - Layer->_color = BaseColor; - _layers.add(Layer); - } - - if (!_fontFile) CBUtils::setString(&_fontFile, "arial.ttf"); - - return initFont(); -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontTT::parseLayer(CBTTFontLayer *layer, byte *buffer) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(OFFSET_X) - TOKEN_TABLE(OFFSET_Y) - TOKEN_TABLE(COLOR) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE_END - - char *params; - int cmd; - CBParser parser(Game); - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_OFFSET_X: - parser.scanStr(params, "%d", &layer->_offsetX); - break; - - case TOKEN_OFFSET_Y: - parser.scanStr(params, "%d", &layer->_offsetY); - break; - - case TOKEN_COLOR: { - int r, g, b; - parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - layer->_color = BYTETORGBA(r, g, b, RGBCOLGetA(layer->_color)); - } - break; - - case TOKEN_ALPHA: { - int a; - parser.scanStr(params, "%d", &a); - layer->_color = BYTETORGBA(RGBCOLGetR(layer->_color), RGBCOLGetG(layer->_color), RGBCOLGetB(layer->_color), a); - } - break; - } - } - if (cmd != PARSERR_EOF) return STATUS_FAILED; - else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontTT::persist(CBPersistMgr *persistMgr) { - CBFont::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_isBold)); - persistMgr->transfer(TMEMBER(_isItalic)); - persistMgr->transfer(TMEMBER(_isUnderline)); - persistMgr->transfer(TMEMBER(_isStriked)); - persistMgr->transfer(TMEMBER(_fontHeight)); - persistMgr->transfer(TMEMBER(_fontFile)); - - - // persist layers - int numLayers; - if (persistMgr->_saving) { - numLayers = _layers.getSize(); - persistMgr->transfer(TMEMBER(numLayers)); - for (int i = 0; i < numLayers; i++) _layers[i]->persist(persistMgr); - } else { - numLayers = _layers.getSize(); - persistMgr->transfer(TMEMBER(numLayers)); - for (int i = 0; i < numLayers; i++) { - CBTTFontLayer *layer = new CBTTFontLayer; - layer->persist(persistMgr); - _layers.add(layer); - } - } - - if (!persistMgr->_saving) { - for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; - _fallbackFont = _font = _deletableFont = NULL; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::afterLoad() { - initFont(); -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CBFontTT::initFont() { - if (!_fontFile) return STATUS_FAILED; - - Common::SeekableReadStream *file = Game->_fileManager->openFile(_fontFile); - if (!file) { - // the requested font file is not in wme file space; try loading a system font - AnsiString fontFileName = PathUtil::combine(CBPlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile)); - file = Game->_fileManager->openFile(fontFileName.c_str(), false); - if (!file) { - Game->LOG(0, "Error loading TrueType font '%s'", _fontFile); - //return STATUS_FAILED; - } - } - - if (file) { -#ifdef USE_FREETYPE2 - _deletableFont = Graphics::loadTTFFont(*file, _fontHeight * 4 / 3); // Compensate for the difference in dpi (96 vs 72). - _font = _deletableFont; -#endif - } - if (!_font) { - _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - warning("BFontTT::InitFont - Couldn't load %s", _fontFile); - } - _lineHeight = _font->getFontHeight(); - return STATUS_OK; -#if 0 - FT_Error error; - - float vertDpi = 96.0; - float horDpi = 96.0; - - - _fTStream = (FT_Stream)new byte[sizeof(*_fTStream)]; - memset(_fTStream, 0, sizeof(*_fTStream)); - - _fTStream->read = CBFontTT::FTReadSeekProc; - _fTStream->close = CBFontTT::FTCloseProc; - _fTStream->descriptor.pointer = file; - _fTStream->size = file->GetSize(); - - FT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = _fTStream; - - error = FT_Open_Face(Game->_fontStorage->GetFTLibrary(), &args, 0, &_fTFace); - if (error) { - SAFE_DELETE_ARRAY(_fTStream); - Game->_fileManager->closeFile(file); - return STATUS_FAILED; - } - - error = FT_Set_Char_Size(_fTFace, 0, (FT_F26Dot6)(_fontHeight * 64), (FT_UInt)horDpi, (FT_UInt)vertDpi); - if (error) { - FT_Done_Face(_fTFace); - _fTFace = NULL; - return STATUS_FAILED; - } - - // http://en.wikipedia.org/wiki/E_(typography) - float pixelsPerEm = (_fontHeight / 72.f) * vertDpi; // Size in inches * dpi - float EmsPerUnit = 1.0f / _fTFace->units_per_EM; - float pixelsPerUnit = pixelsPerEm * EmsPerUnit; - - // bounding box in pixels - float xMin = _fTFace->bbox.xMin * pixelsPerUnit; - float xMax = _fTFace->bbox.xMax * pixelsPerUnit; - float yMin = _fTFace->bbox.yMin * pixelsPerUnit; - float yMax = _fTFace->bbox.yMax * pixelsPerUnit; - - // metrics in pixels - _ascender = _fTFace->ascender * pixelsPerUnit; - _descender = - _fTFace->descender * pixelsPerUnit; - _lineHeight = MathUtil::RoundUp(_fTFace->height * pixelsPerUnit) + 2; - _underlinePos = - _fTFace->underline_position * pixelsPerUnit; - - // max character size (used for texture grid) - _maxCharWidth = (size_t)MathUtil::RoundUp(xMax - xMin); - _maxCharHeight = (size_t)MathUtil::RoundUp(yMax - yMin); - - _glyphCache = new FontGlyphCache(); - _glyphCache->Initialize(); - -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) { - //TextLineList lines; - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("Todo: Test Mesuretext"); - } - if (maxWidth >= 0) { - Common::Array lines; - _font->wordWrapText(text, maxWidth, lines); - Common::Array::iterator it; - textWidth = 0; - for (it = lines.begin(); it != lines.end(); it++) { - textWidth = MAX(textWidth, _font->getStringWidth(*it)); - } - - //WrapText(text, maxWidth, maxHeight, lines); - - textHeight = (int)(lines.size() * getLineHeight()); - } else { - textWidth = _font->getStringWidth(text); - textHeight = _fontHeight; - } - /* - TextLineList::iterator it; - for (it = lines.begin(); it != lines.end(); ++it) { - TextLine *line = (*it); - textWidth = MAX(textWidth, line->GetWidth()); - delete line; - line = NULL; - }*/ -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/BFontTT.h b/engines/wintermute/Base/BFontTT.h deleted file mode 100644 index c585ca2070..0000000000 --- a/engines/wintermute/Base/BFontTT.h +++ /dev/null @@ -1,180 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTTT_H -#define WINTERMUTE_BFONTTT_H - -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BSurface.h" -#include "common/rect.h" -#include "graphics/surface.h" -#include "graphics/font.h" - -#define NUM_CACHED_TEXTS 30 - -namespace WinterMute { - -class CBFontTT : public CBFont { -private: - ////////////////////////////////////////////////////////////////////////// - class CBCachedTTFontText { - public: - WideString _text; - int _width; - TTextAlign _align; - int _maxHeight; - int _maxLength; - CBSurface *_surface; - int _priority; - int _textOffset; - bool _marked; - - CBCachedTTFontText() { - //_text = L""; - _text = ""; - _width = _maxHeight = _maxLength = -1; - _align = TAL_LEFT; - _surface = NULL; - _priority = -1; - _textOffset = 0; - _marked = false; - } - - virtual ~CBCachedTTFontText() { - if (_surface) delete _surface; - } - }; - -public: - ////////////////////////////////////////////////////////////////////////// - class CBTTFontLayer { - public: - CBTTFontLayer() { - _offsetX = _offsetY = 0; - _color = 0x00000000; - } - - ERRORCODE persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_offsetX)); - persistMgr->transfer(TMEMBER(_offsetY)); - persistMgr->transfer(TMEMBER(_color)); - return STATUS_OK; - } - - int _offsetX; - int _offsetY; - uint32 _color; - }; - - ////////////////////////////////////////////////////////////////////////// - class TextLine { - public: - TextLine(const WideString &text, int width) { - _text = text; - _width = width; - } - - const WideString getText() const { - return _text; - } - int getWidth() const { - return _width; - } - private: - WideString _text; - int _width; - }; - typedef Common::List TextLineList; - - -public: - DECLARE_PERSISTENT(CBFontTT, CBFont) - CBFontTT(CBGame *inGame); - virtual ~CBFontTT(void); - - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); - virtual int getLetterHeight(); - - ERRORCODE loadBuffer(byte *buffer); - ERRORCODE loadFile(const char *filename); - - float getLineHeight() const { - return _lineHeight; - } - - void afterLoad(); - void initLoop(); - -private: - ERRORCODE parseLayer(CBTTFontLayer *layer, byte *buffer); - - void wrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines); - void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight); - - CBSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset); - void blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect); - - - CBCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS]; - - ERRORCODE initFont(); - - Graphics::Font *_deletableFont; - const Graphics::Font *_font; - const Graphics::Font *_fallbackFont; - - float _ascender; - float _descender; - float _lineHeight; - float _underlinePos; - float _pointSize; - float _vertDpi; - float _horDpi; - - size_t _maxCharWidth; - size_t _maxCharHeight; - -public: - bool _isBold; - bool _isItalic; - bool _isUnderline; - bool _isStriked; - int _fontHeight; - char *_fontFile; - - CBArray _layers; - void clearCache(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/BGame.cpp b/engines/wintermute/Base/BGame.cpp index bf1bc5c34b..cd7dc07925 100644 --- a/engines/wintermute/Base/BGame.cpp +++ b/engines/wintermute/Base/BGame.cpp @@ -30,8 +30,8 @@ #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BFader.h" #include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" #include "engines/wintermute/Base/BImage.h" #include "engines/wintermute/Base/BKeyboardState.h" #include "engines/wintermute/Base/BParser.h" diff --git a/engines/wintermute/Base/PartEmitter.cpp b/engines/wintermute/Base/PartEmitter.cpp deleted file mode 100644 index c3efc74eec..0000000000 --- a/engines/wintermute/Base/PartEmitter.cpp +++ /dev/null @@ -1,1199 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/PartEmitter.h" -#include "engines/wintermute/Base/PartParticle.h" -#include "engines/wintermute/math/Vector2.h" -#include "engines/wintermute/math/Matrix4.h" -#include "engines/wintermute/Base/scriptables/ScValue.h" -#include "engines/wintermute/Base/scriptables/ScStack.h" -#include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/Base/BRegion.h" -#include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/PlatformSDL.h" -#include "common/str.h" -#include "common/math.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CPartEmitter, false) - -////////////////////////////////////////////////////////////////////////// -CPartEmitter::CPartEmitter(CBGame *inGame, CBScriptHolder *Owner) : CBObject(inGame) { - _width = _height = 0; - - CBPlatform::setRectEmpty(&_border); - _borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0; - - _angle1 = _angle2 = 0; - - _velocity1 = _velocity2 = 0.0f; - _velocityZBased = false; - - _scale1 = _scale2 = 100.0f; - _scaleZBased = false; - - _maxParticles = 100; - - _lifeTime1 = _lifeTime2 = 1000; - _lifeTimeZBased = false; - - _lastGenTime = 0; - _genInterval = 0; - _genAmount = 1; - - _overheadTime = 0; - _running = false; - - _maxBatches = 0; - _batchesGenerated = 0; - - _fadeInTime = _fadeOutTime = 0; - - _alpha1 = _alpha2 = 255; - _alphaTimeBased = false; - - _rotation1 = _rotation2 = 0.0f; - _angVelocity1 = _angVelocity2 = 0.0f; - - _growthRate1 = _growthRate2 = 0.0f; - _exponentialGrowth = false; - - _useRegion = false; - - _emitEvent = NULL; - _owner = Owner; -} - - -////////////////////////////////////////////////////////////////////////// -CPartEmitter::~CPartEmitter(void) { - for (int i = 0; i < _particles.getSize(); i++) { - delete _particles[i]; - } - _particles.removeAll(); - - for (int i = 0; i < _forces.getSize(); i++) { - delete _forces[i]; - } - _forces.removeAll(); - - - for (int i = 0; i < _sprites.getSize(); i++) { - delete [] _sprites[i]; - } - _sprites.removeAll(); - - delete[] _emitEvent; - _emitEvent = NULL; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::addSprite(const char *filename) { - if (!filename) return STATUS_FAILED; - - // do we already have the file? - for (int i = 0; i < _sprites.getSize(); i++) { - if (scumm_stricmp(filename, _sprites[i]) == 0) return STATUS_OK; - } - - // check if file exists - Common::SeekableReadStream *File = Game->_fileManager->openFile(filename); - if (!File) { - Game->LOG(0, "Sprite '%s' not found", filename); - return STATUS_FAILED; - } else Game->_fileManager->closeFile(File); - - char *Str = new char[strlen(filename) + 1]; - strcpy(Str, filename); - _sprites.add(Str); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::removeSprite(const char *filename) { - for (int i = 0; i < _sprites.getSize(); i++) { - if (scumm_stricmp(filename, _sprites[i]) == 0) { - delete [] _sprites[i]; - _sprites.removeAt(i); - return STATUS_OK; - } - } - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta) { - if (!particle) return STATUS_FAILED; - if (_sprites.getSize() == 0) return STATUS_FAILED; - - int posX = CBUtils::randomInt(_posX, _posX + _width); - int posY = CBUtils::randomInt(_posY, _posY + _height); - float posZ = CBUtils::randomFloat(0.0f, 100.0f); - - float velocity; - if (_velocityZBased) velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100; - else velocity = CBUtils::randomFloat(_velocity1, _velocity2); - - float scale; - if (_scaleZBased) scale = _scale1 + posZ * (_scale2 - _scale1) / 100; - else scale = CBUtils::randomFloat(_scale1, _scale2); - - int lifeTime; - if (_lifeTimeZBased) lifeTime = _lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100; - else lifeTime = CBUtils::randomInt(_lifeTime1, _lifeTime2); - - float angle = CBUtils::randomAngle(_angle1, _angle2); - int spriteIndex = CBUtils::randomInt(0, _sprites.getSize() - 1); - - float rotation = CBUtils::randomAngle(_rotation1, _rotation2); - float angVelocity = CBUtils::randomFloat(_angVelocity1, _angVelocity2); - float growthRate = CBUtils::randomFloat(_growthRate1, _growthRate2); - - if (!CBPlatform::isRectEmpty(&_border)) { - int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f); - int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f); - int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f); - int thicknessBottom = (int)(_borderThicknessBottom - (float)_borderThicknessBottom * posZ / 100.0f); - - particle->_border = _border; - particle->_border.left += thicknessLeft; - particle->_border.right -= thicknessRight; - particle->_border.top += thicknessTop; - particle->_border.bottom -= thicknessBottom; - } - - Vector2 vecPos((float)posX, (float)posY); - Vector2 vecVel(0, velocity); - - Matrix4 matRot; - matRot.rotationZ(Common::deg2rad(CBUtils::normalizeAngle(angle - 180))); - matRot.transformVector2(vecVel); - - if (_alphaTimeBased) { - particle->_alpha1 = _alpha1; - particle->_alpha2 = _alpha2; - } else { - int alpha = CBUtils::randomInt(_alpha1, _alpha2); - particle->_alpha1 = alpha; - particle->_alpha2 = alpha; - } - - particle->_creationTime = currentTime; - particle->_pos = vecPos; - particle->_posZ = posZ; - particle->_velocity = vecVel; - particle->_scale = scale; - particle->_lifeTime = lifeTime; - particle->_rotation = rotation; - particle->_angVelocity = angVelocity; - particle->_growthRate = growthRate; - particle->_exponentialGrowth = _exponentialGrowth; - particle->_isDead = DID_FAIL(particle->setSprite(_sprites[spriteIndex])); - particle->fadeIn(currentTime, _fadeInTime); - - - if (particle->_isDead) return STATUS_FAILED; - else return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::update() { - if (!_running) return STATUS_OK; - else return updateInternal(Game->_timer, Game->_timerDelta); -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) { - int numLive = 0; - - for (int i = 0; i < _particles.getSize(); i++) { - _particles[i]->update(this, currentTime, timerDelta); - - if (!_particles[i]->_isDead) numLive++; - } - - - // we're understaffed - if (numLive < _maxParticles) { - bool needsSort = false; - if ((int)(currentTime - _lastGenTime) > _genInterval) { - _lastGenTime = currentTime; - _batchesGenerated++; - - if (_maxBatches > 0 && _batchesGenerated > _maxBatches) { - return STATUS_OK; - } - - int toGen = MIN(_genAmount, _maxParticles - numLive); - while (toGen > 0) { - int firstDeadIndex = -1; - for (int i = 0; i < _particles.getSize(); i++) { - if (_particles[i]->_isDead) { - firstDeadIndex = i; - break; - } - } - - CPartParticle *particle; - if (firstDeadIndex >= 0) particle = _particles[firstDeadIndex]; - else { - particle = new CPartParticle(Game); - _particles.add(particle); - } - initParticle(particle, currentTime, timerDelta); - needsSort = true; - - toGen--; - } - } - if (needsSort && (_scaleZBased || _velocityZBased || _lifeTimeZBased)) - sortParticlesByZ(); - - // we actually generated some particles and we're not in fast-forward mode - if (needsSort && _overheadTime == 0) { - if (_owner && _emitEvent) _owner->applyEvent(_emitEvent); - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::display(CBRegion *region) { - if (_sprites.getSize() <= 1) Game->_renderer->startSpriteBatch(); - - for (int i = 0; i < _particles.getSize(); i++) { - if (region != NULL && _useRegion) { - if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) continue; - } - - _particles[i]->display(this); - } - - if (_sprites.getSize() <= 1) Game->_renderer->endSpriteBatch(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::start() { - for (int i = 0; i < _particles.getSize(); i++) { - _particles[i]->_isDead = true; - } - _running = true; - _batchesGenerated = 0; - - - if (_overheadTime > 0) { - uint32 delta = 500; - int steps = _overheadTime / delta; - uint32 currentTime = Game->_timer - _overheadTime; - - for (int i = 0; i < steps; i++) { - updateInternal(currentTime, delta); - currentTime += delta; - } - _overheadTime = 0; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::sortParticlesByZ() { - // sort particles by _posY - qsort(_particles.getData(), _particles.getSize(), sizeof(CPartParticle *), CPartEmitter::compareZ); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -int CPartEmitter::compareZ(const void *obj1, const void *obj2) { - CPartParticle *p1 = *(CPartParticle **)obj1; - CPartParticle *p2 = *(CPartParticle **)obj2; - - if (p1->_posZ < p2->_posZ) return -1; - else if (p1->_posZ > p2->_posZ) return 1; - else return 0; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::setBorder(int x, int y, int width, int height) { - CBPlatform::setRect(&_border, x, y, x + width, y + height); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) { - _borderThicknessLeft = thicknessLeft; - _borderThicknessRight = thicknessRight; - _borderThicknessTop = thicknessTop; - _borderThicknessBottom = thicknessBottom; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CPartForce *CPartEmitter::addForceByName(const char *name) { - CPartForce *force = NULL; - - for (int i = 0; i < _forces.getSize(); i++) { - if (scumm_stricmp(name, _forces[i]->_name) == 0) { - force = _forces[i]; - break; - } - } - if (!force) { - force = new CPartForce(Game); - if (force) { - force->setName(name); - _forces.add(force); - } - } - return force; -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength) { - CPartForce *force = addForceByName(name); - if (!force) return STATUS_FAILED; - - force->_type = type; - force->_pos = Vector2(posX, posY); - - force->_direction = Vector2(0, strength); - Matrix4 matRot; - matRot.rotationZ(Common::deg2rad(CBUtils::normalizeAngle(angle - 180))); - matRot.transformVector2(force->_direction); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::removeForce(const char *name) { - for (int i = 0; i < _forces.getSize(); i++) { - if (scumm_stricmp(name, _forces[i]->_name) == 0) { - delete _forces[i]; - _forces.removeAt(i); - return STATUS_OK; - } - } - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetBorder - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetBorder") == 0) { - stack->correctParams(4); - int borderX = stack->pop()->getInt(); - int borderY = stack->pop()->getInt(); - int borderWidth = stack->pop()->getInt(); - int borderHeight = stack->pop()->getInt(); - - stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight))); - - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // SetBorderThickness - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetBorderThickness") == 0) { - stack->correctParams(4); - int left = stack->pop()->getInt(); - int right = stack->pop()->getInt(); - int top = stack->pop()->getInt(); - int bottom = stack->pop()->getInt(); - - stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom))); - - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // AddSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddSprite") == 0) { - stack->correctParams(1); - const char *spriteFile = stack->pop()->getString(); - stack->pushBool(DID_SUCCEED(addSprite(spriteFile))); - - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // RemoveSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "RemoveSprite") == 0) { - stack->correctParams(1); - const char *spriteFile = stack->pop()->getString(); - stack->pushBool(DID_SUCCEED(removeSprite(spriteFile))); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Start - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Start") == 0) { - stack->correctParams(1); - _overheadTime = stack->pop()->getInt(); - stack->pushBool(DID_SUCCEED(start())); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Stop - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Stop") == 0) { - stack->correctParams(0); - - for (int i = 0; i < _particles.getSize(); i++) { - delete _particles[i]; - } - _particles.removeAll(); - - _running = false; - stack->pushBool(true); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Pause - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Pause") == 0) { - stack->correctParams(0); - _running = false; - stack->pushBool(true); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Resume - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Resume") == 0) { - stack->correctParams(0); - _running = true; - stack->pushBool(true); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddGlobalForce - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddGlobalForce") == 0) { - stack->correctParams(3); - const char *forceName = stack->pop()->getString(); - float angle = stack->pop()->getFloat(); - float strength = stack->pop()->getFloat(); - - stack->pushBool(DID_SUCCEED(addForce(forceName, CPartForce::FORCE_GLOBAL, 0, 0, angle, strength))); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddPointForce - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddPointForce") == 0) { - stack->correctParams(5); - const char *forceName = stack->pop()->getString(); - int posX = stack->pop()->getInt(); - int posY = stack->pop()->getInt(); - float angle = stack->pop()->getFloat(); - float strength = stack->pop()->getFloat(); - - stack->pushBool(DID_SUCCEED(addForce(forceName, CPartForce::FORCE_GLOBAL, posX, posY, angle, strength))); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // RemoveForce - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "RemoveForce") == 0) { - stack->correctParams(1); - const char *forceName = stack->pop()->getString(); - - stack->pushBool(DID_SUCCEED(removeForce(forceName))); - - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - -////////////////////////////////////////////////////////////////////////// -CScValue *CPartEmitter::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("particle-emitter"); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // X - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "X") == 0) { - _scValue->setInt(_posX); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Y - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Y") == 0) { - _scValue->setInt(_posY); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Width - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Width") == 0) { - _scValue->setInt(_width); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Height - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Height") == 0) { - _scValue->setInt(_height); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Scale1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale1") == 0) { - _scValue->setFloat(_scale1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Scale2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale2") == 0) { - _scValue->setFloat(_scale2); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // ScaleZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScaleZBased") == 0) { - _scValue->setBool(_scaleZBased); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Velocity1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Velocity1") == 0) { - _scValue->setFloat(_velocity1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Velocity2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Velocity2") == 0) { - _scValue->setFloat(_velocity2); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // VelocityZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "VelocityZBased") == 0) { - _scValue->setBool(_velocityZBased); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // LifeTime1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTime1") == 0) { - _scValue->setInt(_lifeTime1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // LifeTime2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTime2") == 0) { - _scValue->setInt(_lifeTime2); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // LifeTimeZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTimeZBased") == 0) { - _scValue->setBool(_lifeTimeZBased); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Angle1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Angle1") == 0) { - _scValue->setInt(_angle1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Angle2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Angle2") == 0) { - _scValue->setInt(_angle2); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AngVelocity1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AngVelocity1") == 0) { - _scValue->setFloat(_angVelocity1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // AngVelocity2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AngVelocity2") == 0) { - _scValue->setFloat(_angVelocity2); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Rotation1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Rotation1") == 0) { - _scValue->setFloat(_rotation1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Rotation2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Rotation2") == 0) { - _scValue->setFloat(_rotation2); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Alpha1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Alpha1") == 0) { - _scValue->setInt(_alpha1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Alpha2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Alpha2") == 0) { - _scValue->setInt(_alpha2); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // AlphaTimeBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AlphaTimeBased") == 0) { - _scValue->setBool(_alphaTimeBased); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // MaxParticles - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxParticles") == 0) { - _scValue->setInt(_maxParticles); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // NumLiveParticles (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumLiveParticles") == 0) { - int numAlive = 0; - for (int i = 0; i < _particles.getSize(); i++) { - if (_particles[i] && !_particles[i]->_isDead) numAlive++; - } - _scValue->setInt(numAlive); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // GenerationInterval - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GenerationInterval") == 0) { - _scValue->setInt(_genInterval); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // GenerationAmount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GenerationAmount") == 0) { - _scValue->setInt(_genAmount); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // MaxBatches - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxBatches") == 0) { - _scValue->setInt(_maxBatches); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeInTime - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeInTime") == 0) { - _scValue->setInt(_fadeInTime); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // FadeOutTime - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeOutTime") == 0) { - _scValue->setInt(_fadeOutTime); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // GrowthRate1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GrowthRate1") == 0) { - _scValue->setFloat(_growthRate1); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // GrowthRate2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GrowthRate2") == 0) { - _scValue->setFloat(_growthRate2); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // ExponentialGrowth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ExponentialGrowth") == 0) { - _scValue->setBool(_exponentialGrowth); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // UseRegion - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "UseRegion") == 0) { - _scValue->setBool(_useRegion); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // EmitEvent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "EmitEvent") == 0) { - if (!_emitEvent) _scValue->setNULL(); - else _scValue->setString(_emitEvent); - return _scValue; - } - - else return CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // X - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "X") == 0) { - _posX = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Y - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Y") == 0) { - _posY = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Width - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Width") == 0) { - _width = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Height - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Height") == 0) { - _height = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Scale1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale1") == 0) { - _scale1 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Scale2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale2") == 0) { - _scale2 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // ScaleZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScaleZBased") == 0) { - _scaleZBased = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Velocity1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Velocity1") == 0) { - _velocity1 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Velocity2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Velocity2") == 0) { - _velocity2 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // VelocityZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "VelocityZBased") == 0) { - _velocityZBased = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LifeTime1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTime1") == 0) { - _lifeTime1 = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // LifeTime2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTime2") == 0) { - _lifeTime2 = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // LifeTimeZBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LifeTimeZBased") == 0) { - _lifeTimeZBased = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Angle1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Angle1") == 0) { - _angle1 = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Angle2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Angle2") == 0) { - _angle2 = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AngVelocity1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AngVelocity1") == 0) { - _angVelocity1 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // AngVelocity2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AngVelocity2") == 0) { - _angVelocity2 = value->getFloat(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Rotation1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Rotation1") == 0) { - _rotation1 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Rotation2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Rotation2") == 0) { - _rotation2 = value->getFloat(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Alpha1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Alpha1") == 0) { - _alpha1 = value->getInt(); - if (_alpha1 < 0) _alpha1 = 0; - if (_alpha1 > 255) _alpha1 = 255; - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Alpha2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Alpha2") == 0) { - _alpha2 = value->getInt(); - if (_alpha2 < 0) _alpha2 = 0; - if (_alpha2 > 255) _alpha2 = 255; - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // AlphaTimeBased - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AlphaTimeBased") == 0) { - _alphaTimeBased = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MaxParticles - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxParticles") == 0) { - _maxParticles = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GenerationInterval - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GenerationInterval") == 0) { - _genInterval = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // GenerationAmount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GenerationAmount") == 0) { - _genAmount = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // MaxBatches - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxBatches") == 0) { - _maxBatches = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeInTime - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeInTime") == 0) { - _fadeInTime = value->getInt(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // FadeOutTime - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeOutTime") == 0) { - _fadeOutTime = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GrowthRate1 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GrowthRate1") == 0) { - _growthRate1 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // GrowthRate2 - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GrowthRate2") == 0) { - _growthRate2 = value->getFloat(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // ExponentialGrowth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ExponentialGrowth") == 0) { - _exponentialGrowth = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // UseRegion - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "UseRegion") == 0) { - _useRegion = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // EmitEvent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "EmitEvent") == 0) { - delete[] _emitEvent; - _emitEvent = NULL; - if (!value->isNULL()) CBUtils::setString(&_emitEvent, value->getString()); - return STATUS_OK; - } - - else return CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CPartEmitter::scToString() { - return "[particle emitter]"; -} - - - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartEmitter::persist(CBPersistMgr *persistMgr) { - CBObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_width)); - persistMgr->transfer(TMEMBER(_height)); - - persistMgr->transfer(TMEMBER(_angle1)); - persistMgr->transfer(TMEMBER(_angle2)); - - persistMgr->transfer(TMEMBER(_velocity1)); - persistMgr->transfer(TMEMBER(_velocity2)); - persistMgr->transfer(TMEMBER(_velocityZBased)); - - persistMgr->transfer(TMEMBER(_scale1)); - persistMgr->transfer(TMEMBER(_scale2)); - persistMgr->transfer(TMEMBER(_scaleZBased)); - - persistMgr->transfer(TMEMBER(_maxParticles)); - - persistMgr->transfer(TMEMBER(_lifeTime1)); - persistMgr->transfer(TMEMBER(_lifeTime2)); - persistMgr->transfer(TMEMBER(_lifeTimeZBased)); - - persistMgr->transfer(TMEMBER(_genInterval)); - persistMgr->transfer(TMEMBER(_genAmount)); - - persistMgr->transfer(TMEMBER(_running)); - persistMgr->transfer(TMEMBER(_overheadTime)); - - persistMgr->transfer(TMEMBER(_border)); - persistMgr->transfer(TMEMBER(_borderThicknessLeft)); - persistMgr->transfer(TMEMBER(_borderThicknessRight)); - persistMgr->transfer(TMEMBER(_borderThicknessTop)); - persistMgr->transfer(TMEMBER(_borderThicknessBottom)); - - persistMgr->transfer(TMEMBER(_fadeInTime)); - persistMgr->transfer(TMEMBER(_fadeOutTime)); - - persistMgr->transfer(TMEMBER(_alpha1)); - persistMgr->transfer(TMEMBER(_alpha2)); - persistMgr->transfer(TMEMBER(_alphaTimeBased)); - - persistMgr->transfer(TMEMBER(_angVelocity1)); - persistMgr->transfer(TMEMBER(_angVelocity2)); - - persistMgr->transfer(TMEMBER(_rotation1)); - persistMgr->transfer(TMEMBER(_rotation2)); - - persistMgr->transfer(TMEMBER(_growthRate1)); - persistMgr->transfer(TMEMBER(_growthRate2)); - persistMgr->transfer(TMEMBER(_exponentialGrowth)); - - persistMgr->transfer(TMEMBER(_useRegion)); - - persistMgr->transfer(TMEMBER_INT(_maxBatches)); - persistMgr->transfer(TMEMBER_INT(_batchesGenerated)); - - persistMgr->transfer(TMEMBER(_emitEvent)); - persistMgr->transfer(TMEMBER(_owner)); - - - _sprites.persist(persistMgr); - - int numForces; - if (persistMgr->_saving) { - numForces = _forces.getSize(); - persistMgr->transfer(TMEMBER(numForces)); - for (int i = 0; i < _forces.getSize(); i++) { - _forces[i]->persist(persistMgr); - } - } else { - persistMgr->transfer(TMEMBER(numForces)); - for (int i = 0; i < numForces; i++) { - CPartForce *force = new CPartForce(Game); - force->persist(persistMgr); - _forces.add(force); - } - } - - int numParticles; - if (persistMgr->_saving) { - numParticles = _particles.getSize(); - persistMgr->transfer(TMEMBER(numParticles)); - for (int i = 0; i < _particles.getSize(); i++) { - _particles[i]->persist(persistMgr); - } - } else { - persistMgr->transfer(TMEMBER(numParticles)); - for (int i = 0; i < numParticles; i++) { - CPartParticle *particle = new CPartParticle(Game); - particle->persist(persistMgr); - _particles.add(particle); - } - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/PartEmitter.h b/engines/wintermute/Base/PartEmitter.h deleted file mode 100644 index e2de466e42..0000000000 --- a/engines/wintermute/Base/PartEmitter.h +++ /dev/null @@ -1,139 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_PARTEMITTER_H -#define WINTERMUTE_PARTEMITTER_H - - -#include "engines/wintermute/Base/BObject.h" -#include "engines/wintermute/Base/PartForce.h" - -namespace WinterMute { -class CBRegion; -class CPartParticle; -class CPartEmitter : public CBObject { -public: - DECLARE_PERSISTENT(CPartEmitter, CBObject) - - CPartEmitter(CBGame *inGame, CBScriptHolder *Owner); - virtual ~CPartEmitter(void); - - int _width; - int _height; - - int _angle1; - int _angle2; - - float _rotation1; - float _rotation2; - - float _angVelocity1; - float _angVelocity2; - - float _growthRate1; - float _growthRate2; - bool _exponentialGrowth; - - float _velocity1; - float _velocity2; - bool _velocityZBased; - - float _scale1; - float _scale2; - bool _scaleZBased; - - int _maxParticles; - - int _lifeTime1; - int _lifeTime2; - bool _lifeTimeZBased; - - int _genInterval; - int _genAmount; - - bool _running; - int _overheadTime; - - int _maxBatches; - int _batchesGenerated; - - Rect32 _border; - int _borderThicknessLeft; - int _borderThicknessRight; - int _borderThicknessTop; - int _borderThicknessBottom; - - int _fadeInTime; - int _fadeOutTime; - - int _alpha1; - int _alpha2; - bool _alphaTimeBased; - - bool _useRegion; - - char *_emitEvent; - CBScriptHolder *_owner; - - ERRORCODE start(); - - ERRORCODE update(); - ERRORCODE display() { return display(NULL); } // To avoid shadowing the inherited display-function. - ERRORCODE display(CBRegion *region); - - ERRORCODE sortParticlesByZ(); - ERRORCODE addSprite(const char *filename); - ERRORCODE removeSprite(const char *filename); - ERRORCODE setBorder(int x, int y, int width, int height); - ERRORCODE setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom); - - ERRORCODE addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength); - ERRORCODE removeForce(const char *name); - - CBArray _forces; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual ERRORCODE scSetProperty(const char *name, CScValue *value); - virtual ERRORCODE scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - - -private: - CPartForce *addForceByName(const char *name); - int static compareZ(const void *obj1, const void *obj2); - ERRORCODE initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta); - ERRORCODE updateInternal(uint32 currentTime, uint32 timerDelta); - uint32 _lastGenTime; - CBArray _particles; - CBArray _sprites; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/PartForce.cpp b/engines/wintermute/Base/PartForce.cpp deleted file mode 100644 index b60d5447d9..0000000000 --- a/engines/wintermute/Base/PartForce.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/Base/PartForce.h" -#include "engines/wintermute/Base/BPersistMgr.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CPartForce::CPartForce(CBGame *inGame) : CBNamedObject(inGame) { - _pos = Vector2(0.0f, 0.0f); - _direction = Vector2(0.0f, 0.0f); - _type = FORCE_POINT; -} - - -////////////////////////////////////////////////////////////////////////// -CPartForce::~CPartForce(void) { -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartForce::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_name)); - persistMgr->transfer(TMEMBER(_pos)); - persistMgr->transfer(TMEMBER(_direction)); - persistMgr->transfer(TMEMBER_INT(_type)); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/PartForce.h b/engines/wintermute/Base/PartForce.h deleted file mode 100644 index cf5d697a79..0000000000 --- a/engines/wintermute/Base/PartForce.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_PARTFORCE_H -#define WINTERMUTE_PARTFORCE_H - - -#include "engines/wintermute/Base/BBase.h" -#include "engines/wintermute/Base/BNamedObject.h" -#include "engines/wintermute/math/Vector2.h" - -namespace WinterMute { - -class CPartForce : public CBNamedObject { -public: - enum TForceType { - FORCE_POINT, FORCE_GLOBAL - }; - - CPartForce(CBGame *inGame); - virtual ~CPartForce(void); - - Vector2 _pos; - Vector2 _direction; - TForceType _type; - - ERRORCODE persist(CBPersistMgr *PersistMgr); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/PartParticle.cpp b/engines/wintermute/Base/PartParticle.cpp deleted file mode 100644 index f3a8de9ece..0000000000 --- a/engines/wintermute/Base/PartParticle.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/dcgf.h" -#include "engines/wintermute/Base/PartParticle.h" -#include "engines/wintermute/Base/PartEmitter.h" -#include "engines/wintermute/Base/BSprite.h" -#include "engines/wintermute/Base/BGame.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/PlatformSDL.h" -#include "common/str.h" -#include - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CPartParticle::CPartParticle(CBGame *inGame) : CBBase(inGame) { - _pos = Vector2(0.0f, 0.0f); - _posZ = 0.0f; - _velocity = Vector2(0.0f, 0.0f); - _scale = 100.0f; - _sprite = NULL; - _creationTime = 0; - _lifeTime = 0; - _isDead = true; - CBPlatform::setRectEmpty(&_border); - - _state = PARTICLE_NORMAL; - _fadeStart = 0; - _fadeTime = 0; - _currentAlpha = 255; - - _alpha1 = _alpha2 = 255; - - _rotation = 0.0f; - _angVelocity = 0.0f; - - _growthRate = 0.0f; - _exponentialGrowth = false; -} - - -////////////////////////////////////////////////////////////////////////// -CPartParticle::~CPartParticle(void) { - delete _sprite; - _sprite = NULL; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::setSprite(const char *filename) { - if (_sprite && _sprite->_filename && scumm_stricmp(filename, _sprite->_filename) == 0) { - _sprite->reset(); - return STATUS_OK; - } - - delete _sprite; - _sprite = NULL; - - CSysClassRegistry::getInstance()->_disabled = true; - _sprite = new CBSprite(Game, Game); - if (_sprite && DID_SUCCEED(_sprite->loadFile(filename))) { - CSysClassRegistry::getInstance()->_disabled = false; - return STATUS_OK; - } else { - delete _sprite; - _sprite = NULL; - CSysClassRegistry::getInstance()->_disabled = false; - return STATUS_FAILED; - } - -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta) { - if (_state == PARTICLE_FADEIN) { - if (currentTime - _fadeStart >= (uint32)_fadeTime) { - _state = PARTICLE_NORMAL; - _currentAlpha = _alpha1; - } else _currentAlpha = (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _alpha1); - - return STATUS_OK; - } else if (_state == PARTICLE_FADEOUT) { - if (currentTime - _fadeStart >= (uint32)_fadeTime) { - _isDead = true; - return STATUS_OK; - } else _currentAlpha = _fadeStartAlpha - (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _fadeStartAlpha); - - return STATUS_OK; - } else { - // time is up - if (_lifeTime > 0) { - if (currentTime - _creationTime >= (uint32)_lifeTime) { - if (emitter->_fadeOutTime > 0) - fadeOut(currentTime, emitter->_fadeOutTime); - else - _isDead = true; - } - } - - // particle hit the border - if (!_isDead && !CBPlatform::isRectEmpty(&_border)) { - Point32 p; - p.x = (int32)_pos.x; - p.y = (int32)_pos.y; - if (!CBPlatform::ptInRect(&_border, p)) - fadeOut(currentTime, emitter->_fadeOutTime); - } - if (_state != PARTICLE_NORMAL) return STATUS_OK; - - // update alpha - if (_lifeTime > 0) { - int age = (int)(currentTime - _creationTime); - int alphaDelta = (int)(_alpha2 - _alpha1); - - _currentAlpha = _alpha1 + (int)(((float)alphaDelta / (float)_lifeTime * (float)age)); - } - - // update position - float elapsedTime = (float)timerDelta / 1000.f; - - for (int i = 0; i < emitter->_forces.getSize(); i++) { - CPartForce *force = emitter->_forces[i]; - switch (force->_type) { - case CPartForce::FORCE_GLOBAL: - _velocity += force->_direction * elapsedTime; - break; - - case CPartForce::FORCE_POINT: { - Vector2 vecDist = force->_pos - _pos; - float dist = fabs(vecDist.length()); - - dist = 100.0f / dist; - - _velocity += force->_direction * dist * elapsedTime; - } - break; - } - } - _pos += _velocity * elapsedTime; - - // update rotation - _rotation += _angVelocity * elapsedTime; - _rotation = CBUtils::normalizeAngle(_rotation); - - // update scale - if (_exponentialGrowth) - _scale += _scale / 100.0f * _growthRate * elapsedTime; - else - _scale += _growthRate * elapsedTime; - - if (_scale <= 0.0f) - _isDead = true; - - - return STATUS_OK; - } -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::display(CPartEmitter *emitter) { - if (!_sprite) return STATUS_FAILED; - if (_isDead) return STATUS_OK; - - _sprite->GetCurrentFrame(); - return _sprite->display(_pos.x, _pos.y, - NULL, - _scale, _scale, - BYTETORGBA(255, 255, 255, _currentAlpha), - _rotation, - emitter->_blendMode); -} - - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::fadeIn(uint32 currentTime, int fadeTime) { - _currentAlpha = 0; - _fadeStart = currentTime; - _fadeTime = fadeTime; - _state = PARTICLE_FADEIN; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::fadeOut(uint32 currentTime, int fadeTime) { - //_currentAlpha = 255; - _fadeStartAlpha = _currentAlpha; - _fadeStart = currentTime; - _fadeTime = fadeTime; - _state = PARTICLE_FADEOUT; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -ERRORCODE CPartParticle::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_alpha1)); - persistMgr->transfer(TMEMBER(_alpha2)); - persistMgr->transfer(TMEMBER(_border)); - persistMgr->transfer(TMEMBER(_pos)); - persistMgr->transfer(TMEMBER(_posZ)); - persistMgr->transfer(TMEMBER(_velocity)); - persistMgr->transfer(TMEMBER(_scale)); - persistMgr->transfer(TMEMBER(_creationTime)); - persistMgr->transfer(TMEMBER(_lifeTime)); - persistMgr->transfer(TMEMBER(_isDead)); - persistMgr->transfer(TMEMBER_INT(_state)); - persistMgr->transfer(TMEMBER(_fadeStart)); - persistMgr->transfer(TMEMBER(_fadeTime)); - persistMgr->transfer(TMEMBER(_currentAlpha)); - persistMgr->transfer(TMEMBER(_angVelocity)); - persistMgr->transfer(TMEMBER(_rotation)); - persistMgr->transfer(TMEMBER(_growthRate)); - persistMgr->transfer(TMEMBER(_exponentialGrowth)); - persistMgr->transfer(TMEMBER(_fadeStartAlpha)); - - if (persistMgr->_saving) { - persistMgr->transfer(TMEMBER(_sprite->_filename)); - } else { - char *filename; - persistMgr->transfer(TMEMBER(filename)); - CSysClassRegistry::getInstance()->_disabled = true; - setSprite(filename); - CSysClassRegistry::getInstance()->_disabled = false; - delete[] filename; - filename = NULL; - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/Base/PartParticle.h b/engines/wintermute/Base/PartParticle.h deleted file mode 100644 index aed559d337..0000000000 --- a/engines/wintermute/Base/PartParticle.h +++ /dev/null @@ -1,90 +0,0 @@ -/* 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. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_PARTPARTICLE_H -#define WINTERMUTE_PARTPARTICLE_H - - -#include "engines/wintermute/Base/BBase.h" -#include "engines/wintermute/Math/Rect32.h" -#include "engines/wintermute/math/Vector2.h" - -namespace WinterMute { - -class CPartEmitter; -class CBSprite; -class CBPersistMgr; - -class CPartParticle : public CBBase { -public: - enum TParticleState { - PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT - }; - - CPartParticle(CBGame *inGame); - virtual ~CPartParticle(void); - - float _growthRate; - bool _exponentialGrowth; - - float _rotation; - float _angVelocity; - - int _alpha1; - int _alpha2; - - Rect32 _border; - Vector2 _pos; - float _posZ; - Vector2 _velocity; - float _scale; - CBSprite *_sprite; - uint32 _creationTime; - int _lifeTime; - bool _isDead; - TParticleState _state; - - ERRORCODE update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta); - ERRORCODE display(CPartEmitter *emitter); - - ERRORCODE setSprite(const char *filename); - - ERRORCODE fadeIn(uint32 currentTime, int fadeTime); - ERRORCODE fadeOut(uint32 currentTime, int fadeTime); - - ERRORCODE persist(CBPersistMgr *PersistMgr); -private: - uint32 _fadeStart; - int _fadeTime; - int _currentAlpha; - int _fadeStartAlpha; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/Base/font/BFont.cpp b/engines/wintermute/Base/font/BFont.cpp new file mode 100644 index 0000000000..b59188d0c1 --- /dev/null +++ b/engines/wintermute/Base/font/BFont.cpp @@ -0,0 +1,206 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/font/BFontBitmap.h" +#include "engines/wintermute/Base/font/BFontTT.h" +#include "engines/wintermute/Base/BParser.h" +#include "engines/wintermute/Base/BFileManager.h" +#include "engines/wintermute/Base/BGame.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFont, false) + +////////////////////////////////////////////////////////////////////// +CBFont::CBFont(CBGame *inGame): CBObject(inGame) { + +} + + +////////////////////////////////////////////////////////////////////// +CBFont::~CBFont() { +} + + +////////////////////////////////////////////////////////////////////// +void CBFont::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::getTextHeight(byte *text, int width) { + return 0; +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::getTextWidth(byte *text, int maxLength) { + return 0; +} + +/* +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFont::loadFile(const char * Filename) +{ + BYTE* Buffer = Game->_fileManager->readWholeFile(filename); + if(Buffer==NULL){ + Game->LOG(0, "CBFont::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + ERRORCODE ret; + + _filename = new char [strlen(filename)+1]; + strcpy(_filename, filename); + + if(DID_FAIL(ret = loadBuffer(Buffer))) Game->LOG(0, "Error parsing FONT file '%s'", filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START + TOKEN_DEF (FONT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFont::loadBuffer(byte * Buffer) +{ + TOKEN_TABLE_START(commands) + TOKEN_TABLE (FONT) + TOKEN_TABLE_END + + char* params; + int cmd; + CBParser parser(Game); + + if(parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)!=TOKEN_FONT){ + Game->LOG(0, "'FONT' keyword expected."); + return STATUS_FAILED; + } + Buffer = (byte *)params; + + while ((cmd = parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)) > 0) + { + switch (cmd) + { + case TOKEN_IMAGE: + surface_file = (char*)params; + break; + + case TOKEN_TRANSPARENT: + parser.scanStr(params, "%d,%d,%d", &r, &g, &b); + custo_trans = true; + break; + } + + + } + if (cmd == PARSERR_TOKENNOTFOUND){ + Game->LOG(0, "Syntax error in FONT definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} +*/ + +////////////////////////////////////////////////////////////////////////// +int CBFont::getLetterHeight() { + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFont::persist(CBPersistMgr *persistMgr) { + + CBObject::persist(persistMgr); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFont::createFromFile(CBGame *Game, const char *filename) { + if (isTrueType(Game, filename)) { + CBFontTT *font = new CBFontTT(Game); + if (font) { + if (DID_FAIL(font->loadFile(filename))) { + delete font; + return NULL; + } + } + return font; + } else { + CBFontBitmap *font = new CBFontBitmap(Game); + if (font) { + if (DID_FAIL(font->loadFile(filename))) { + delete font; + return NULL; + } + } + return font; + } +} + + +TOKEN_DEF_START +TOKEN_DEF(FONT) +TOKEN_DEF(TTFONT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool CBFont::isTrueType(CBGame *Game, const char *filename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TTFONT) + TOKEN_TABLE_END + + + byte *buffer = Game->_fileManager->readWholeFile(filename); + if (buffer == NULL) return false; + + byte *WorkBuffer = buffer; + + char *params; + CBParser parser(Game); + + bool ret = false; + if (parser.getCommand((char **)&WorkBuffer, commands, (char **)¶ms) == TOKEN_TTFONT) + ret = true; + + delete [] buffer; + return ret; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/font/BFont.h b/engines/wintermute/Base/font/BFont.h new file mode 100644 index 0000000000..ac5a79299d --- /dev/null +++ b/engines/wintermute/Base/font/BFont.h @@ -0,0 +1,61 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONT_H +#define WINTERMUTE_BFONT_H + +#include "engines/wintermute/Base/BObject.h" + +#define NUM_CHARACTERS 256 + +namespace WinterMute { + +class CBFont: public CBObject { +public: + DECLARE_PERSISTENT(CBFont, CBObject) + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); + virtual int getLetterHeight(); + + virtual void initLoop() {}; + virtual void afterLoad() {}; + CBFont(CBGame *inGame); + virtual ~CBFont(); + + static CBFont *createFromFile(CBGame *game, const char *filename); + +private: + //ERRORCODE loadBuffer(byte * Buffer); + //ERRORCODE loadFile(const char* Filename); + static bool isTrueType(CBGame *game, const char *filename); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/font/BFontBitmap.cpp b/engines/wintermute/Base/font/BFontBitmap.cpp new file mode 100644 index 0000000000..681f2580bf --- /dev/null +++ b/engines/wintermute/Base/font/BFontBitmap.cpp @@ -0,0 +1,540 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/font/BFontBitmap.h" +#include "engines/wintermute/utils/StringUtil.h" +#include "engines/wintermute/Base/BParser.h" +#include "engines/wintermute/Base/BFrame.h" +#include "engines/wintermute/Base/BSurface.h" +#include "engines/wintermute/Base/BGame.h" +#include "engines/wintermute/Base/BSubFrame.h" +#include "engines/wintermute/Base/BFrame.h" +#include "engines/wintermute/Base/BSprite.h" +#include "engines/wintermute/Base/BFileManager.h" +#include "engines/wintermute/PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFontBitmap, false) + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::CBFontBitmap(CBGame *inGame): CBFont(inGame) { + _subframe = NULL; + _sprite = NULL; + _widthsFrame = 0; + memset(_widths, 0, NUM_CHARACTERS); + _tileWidth = _tileHeight = _numColumns = 0; + _fontextFix = false; + _freezable = false; + _wholeCell = false; +} + + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::~CBFontBitmap() { + delete _subframe; + delete _sprite; + _subframe = NULL; + _sprite = NULL; +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { + textHeightDraw(text, x, y, width, align, true, max_height, maxLength); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getTextHeight(byte *text, int width) { + return textHeightDraw(text, 0, 0, width, TAL_LEFT, false); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getTextWidth(byte *text, int maxLength) { + AnsiString str; + + if (Game->_textEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::utf8ToWide(Utf8String((char *)text)); + str = StringUtil::wideToAnsi(wstr); + } else { + str = AnsiString((char *)text); + } + + if (maxLength >= 0 && str.size() > (uint32)maxLength) + str = Common::String(str.c_str(), (uint32)maxLength); + //str.substr(0, maxLength); // TODO: Remove + + int textWidth = 0; + for (size_t i = 0; i < str.size(); i++) { + textWidth += getCharWidth(str[i]); + } + + return textWidth; +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::textHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int maxHeight, int maxLength) { + if (maxLength == 0) return 0; + + if (text == NULL || text[0] == '\0') return _tileHeight; + + AnsiString str; + + if (Game->_textEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::utf8ToWide(Utf8String((char *)text)); + str = StringUtil::wideToAnsi(wstr); + } else { + str = AnsiString((char *)text); + } + if (str.empty()) return 0; + + int LineLength = 0; + int RealLength = 0; + int NumLines = 0; + + int i; + + int index = -1; + int start = 0; + int end = 0; + int last_end = 0; + + bool done = false; + bool new_line = false; + bool long_line = false; + + if (draw) Game->_renderer->startSpriteBatch(); + + while (!done) { + if (maxHeight > 0 && (NumLines + 1)*_tileHeight > maxHeight) { + if (draw) Game->_renderer->endSpriteBatch(); + return NumLines * _tileHeight; + } + + index++; + + if (str[index] == ' ' && (maxHeight < 0 || maxHeight / _tileHeight > 1)) { + end = index - 1; + RealLength = LineLength; + } + + if (str[index] == '\n') { + end = index - 1; + RealLength = LineLength; + new_line = true; + } + + if (LineLength + getCharWidth(str[index]) > width && last_end == end) { + end = index - 1; + RealLength = LineLength; + new_line = true; + long_line = true; + } + + if (str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) { + done = true; + if (!new_line) { + end = index; + LineLength += getCharWidth(str[index]); + RealLength = LineLength; + } + } else LineLength += getCharWidth(str[index]); + + if ((LineLength > width) || done || new_line) { + if (end < 0) done = true; + int StartX; + switch (align) { + case TAL_CENTER: + StartX = x + (width - RealLength) / 2; + break; + case TAL_RIGHT: + StartX = x + width - RealLength; + break; + case TAL_LEFT: + StartX = x; + break; + default: + error("CBFontBitmap::TextHeightDraw - Unhandled enum"); + break; + } + for (i = start; i < end + 1; i++) { + if (draw) drawChar(str[i], StartX, y); + StartX += getCharWidth(str[i]); + } + y += _tileHeight; + last_end = end; + if (long_line) end--; + start = end + 2; + index = end + 1; + LineLength = 0; + new_line = false; + long_line = false; + NumLines++; + } + } + + if (draw) Game->_renderer->endSpriteBatch(); + + return NumLines * _tileHeight; +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::drawChar(byte c, int x, int y) { + if (_fontextFix) c--; + + int row, col; + + row = c / _numColumns; + col = c % _numColumns; + + Rect32 rect; + /* l t r b */ + int tileWidth; + if (_wholeCell) tileWidth = _tileWidth; + else tileWidth = _widths[c]; + + CBPlatform::setRect(&rect, col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1)*_tileHeight); + bool handled = false; + if (_sprite) { + _sprite->GetCurrentFrame(); + if (_sprite->_currentFrame >= 0 && _sprite->_currentFrame < _sprite->_frames.getSize() && _sprite->_frames[_sprite->_currentFrame]) { + if (_sprite->_frames[_sprite->_currentFrame]->_subframes.getSize() > 0) { + _sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect); + } + handled = true; + } + } + if (!handled && _subframe) _subframe->_surface->displayTrans(x, y, rect); +} + + +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontBitmap::loadFile(const char *filename) { + byte *buffer = Game->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + Game->LOG(0, "CBFontBitmap::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + ERRORCODE ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + if (DID_FAIL(ret = loadBuffer(buffer))) Game->LOG(0, "Error parsing FONT file '%s'", filename); + + delete [] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(FONTEXT_FIX) +TOKEN_DEF(FONT) +TOKEN_DEF(IMAGE) +TOKEN_DEF(TRANSPARENT) +TOKEN_DEF(COLUMNS) +TOKEN_DEF(TILE_WIDTH) +TOKEN_DEF(TILE_HEIGHT) +TOKEN_DEF(DEFAULT_WIDTH) +TOKEN_DEF(WIDTHS) +TOKEN_DEF(AUTO_WIDTH) +TOKEN_DEF(SPACE_WIDTH) +TOKEN_DEF(EXPAND_WIDTH) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(SPRITE) +TOKEN_DEF(WIDTHS_FRAME) +TOKEN_DEF(PAINT_WHOLE_CELL) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontBitmap::loadBuffer(byte *buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(FONTEXT_FIX) + TOKEN_TABLE(FONT) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(TRANSPARENT) + TOKEN_TABLE(COLUMNS) + TOKEN_TABLE(TILE_WIDTH) + TOKEN_TABLE(TILE_HEIGHT) + TOKEN_TABLE(DEFAULT_WIDTH) + TOKEN_TABLE(WIDTHS) + TOKEN_TABLE(AUTO_WIDTH) + TOKEN_TABLE(SPACE_WIDTH) + TOKEN_TABLE(EXPAND_WIDTH) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(WIDTHS_FRAME) + TOKEN_TABLE(PAINT_WHOLE_CELL) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_FONT) { + Game->LOG(0, "'FONT' keyword expected."); + return STATUS_FAILED; + } + buffer = (byte *)params; + + int widths[300]; + int num = 0, default_width = 8; + int lastWidth = 0; + int i; + int r = 255, g = 255, b = 255; + bool custoTrans = false; + char *surfaceFile = NULL; + char *spriteFile = NULL; + + bool autoWidth = false; + int spaceWidth = 0; + int expandWidth = 0; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + + switch (cmd) { + case TOKEN_IMAGE: + surfaceFile = (char *)params; + break; + + case TOKEN_SPRITE: + spriteFile = (char *)params; + break; + + case TOKEN_TRANSPARENT: + parser.scanStr(params, "%d,%d,%d", &r, &g, &b); + custoTrans = true; + break; + + case TOKEN_WIDTHS: + parser.scanStr(params, "%D", widths, &num); + for (i = 0; lastWidth < NUM_CHARACTERS, num > 0; lastWidth++, num--, i++) { + _widths[lastWidth] = (byte)widths[i]; + } + break; + + case TOKEN_DEFAULT_WIDTH: + parser.scanStr(params, "%d", &default_width); + break; + + case TOKEN_WIDTHS_FRAME: + parser.scanStr(params, "%d", &_widthsFrame); + break; + + case TOKEN_COLUMNS: + parser.scanStr(params, "%d", &_numColumns); + break; + + case TOKEN_TILE_WIDTH: + parser.scanStr(params, "%d", &_tileWidth); + break; + + case TOKEN_TILE_HEIGHT: + parser.scanStr(params, "%d", &_tileHeight); + break; + + case TOKEN_AUTO_WIDTH: + parser.scanStr(params, "%b", &autoWidth); + break; + + case TOKEN_FONTEXT_FIX: + parser.scanStr(params, "%b", &_fontextFix); + break; + + case TOKEN_PAINT_WHOLE_CELL: + parser.scanStr(params, "%b", &_wholeCell); + break; + + case TOKEN_SPACE_WIDTH: + parser.scanStr(params, "%d", &spaceWidth); + break; + + case TOKEN_EXPAND_WIDTH: + parser.scanStr(params, "%d", &expandWidth); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty((byte *)params, false); + break; + } + + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in FONT definition"); + return STATUS_FAILED; + } + + if (spriteFile != NULL) { + delete _sprite; + _sprite = new CBSprite(Game, this); + if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) { + delete _sprite; + _sprite = NULL; + } + } + + if (surfaceFile != NULL && !_sprite) { + _subframe = new CBSubFrame(Game); + if (custoTrans) _subframe->setSurface(surfaceFile, false, r, g, b); + else _subframe->setSurface(surfaceFile); + } + + + if (((_subframe == NULL || _subframe->_surface == NULL) && _sprite == NULL) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) { + Game->LOG(0, "Incomplete font definition"); + return STATUS_FAILED; + } + + if (autoWidth) { + // calculate characters width + getWidths(); + + // do we need to modify widths? + if (expandWidth != 0) { + for (i = 0; i < NUM_CHARACTERS; i++) { + int NewWidth = (int)_widths[i] + expandWidth; + if (NewWidth < 0) NewWidth = 0; + + _widths[i] = (byte)NewWidth; + } + } + + // handle space character + uint32 spaceChar = ' '; + if (_fontextFix) spaceChar--; + + if (spaceWidth != 0) _widths[spaceChar] = spaceWidth; + else { + if (_widths[spaceChar] == expandWidth || _widths[spaceChar] == 0) { + _widths[spaceChar] = (_widths['m'] + _widths['i']) / 2; + } + } + } else { + for (i = lastWidth; i < NUM_CHARACTERS; i++) _widths[i] = default_width; + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontBitmap::persist(CBPersistMgr *persistMgr) { + + CBFont::persist(persistMgr); + persistMgr->transfer(TMEMBER(_numColumns)); + + persistMgr->transfer(TMEMBER(_subframe)); + persistMgr->transfer(TMEMBER(_tileHeight)); + persistMgr->transfer(TMEMBER(_tileWidth)); + persistMgr->transfer(TMEMBER(_sprite)); + persistMgr->transfer(TMEMBER(_widthsFrame)); + + if (persistMgr->_saving) + persistMgr->putBytes(_widths, sizeof(_widths)); + else + persistMgr->getBytes(_widths, sizeof(_widths)); + + + persistMgr->transfer(TMEMBER(_fontextFix)); + persistMgr->transfer(TMEMBER(_wholeCell)); + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getCharWidth(byte index) { + if (_fontextFix) index--; + return _widths[index]; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontBitmap::getWidths() { + CBSurface *surf = NULL; + + if (_sprite) { + if (_widthsFrame >= 0 && _widthsFrame < _sprite->_frames.getSize()) { + if (_sprite->_frames[_widthsFrame] && _sprite->_frames[_widthsFrame]->_subframes.getSize() > 0) { + surf = _sprite->_frames[_widthsFrame]->_subframes[0]->_surface; + } + } + } + if (surf == NULL && _subframe) surf = _subframe->_surface; + if (!surf || DID_FAIL(surf->startPixelOp())) return STATUS_FAILED; + + + for (int i = 0; i < NUM_CHARACTERS; i++) { + int xxx = (i % _numColumns) * _tileWidth; + int yyy = (i / _numColumns) * _tileHeight; + + + int minCol = -1; + for (int row = 0; row < _tileHeight; row++) { + for (int col = _tileWidth - 1; col >= minCol + 1; col--) { + if (xxx + col < 0 || xxx + col >= surf->getWidth() || yyy + row < 0 || yyy + row >= surf->getHeight()) continue; + if (!surf->isTransparentAtLite(xxx + col, yyy + row)) { + //min_col = col; + minCol = MAX(col, minCol); + break; + } + } + if (minCol == _tileWidth - 1) break; + } + + _widths[i] = minCol + 1; + } + surf->endPixelOp(); + /* + Game->LOG(0, "----- %s ------", _filename); + for(int j=0; j<16; j++) + { + Game->LOG(0, "%02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d", _widths[j*16+0], _widths[j*16+1], _widths[j*16+2], _widths[j*16+3], _widths[j*16+4], _widths[j*16+5], _widths[j*16+6], _widths[j*16+7], _widths[j*16+8], _widths[j*16+9], _widths[j*16+10], _widths[j*16+11], _widths[j*16+12], _widths[j*16+13], _widths[j*16+14], _widths[j*16+15]); + } + */ + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getLetterHeight() { + return _tileHeight; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/font/BFontBitmap.h b/engines/wintermute/Base/font/BFontBitmap.h new file mode 100644 index 0000000000..b834f919b9 --- /dev/null +++ b/engines/wintermute/Base/font/BFontBitmap.h @@ -0,0 +1,72 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTBITMAP_H +#define WINTERMUTE_BFONTBITMAP_H + + +#include "engines/wintermute/Base/font/BFont.h" + +namespace WinterMute { +class CBSubFrame; +class CBFontBitmap : public CBFont { +public: + DECLARE_PERSISTENT(CBFontBitmap, CBFont) + ERRORCODE loadBuffer(byte *Buffer); + ERRORCODE loadFile(const char *filename); + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); + virtual int getLetterHeight(); + + CBFontBitmap(CBGame *inGame); + virtual ~CBFontBitmap(); + + + ERRORCODE getWidths(); + CBSprite *_sprite; + int _widthsFrame; + bool _fontextFix; + int _numColumns; + int _tileHeight; + int _tileWidth; + byte _widths[NUM_CHARACTERS]; + CBSubFrame *_subframe; + bool _wholeCell; + +private: + int getCharWidth(byte index); + void drawChar(byte c, int x, int y); + + int textHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int MaxLength = -1); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/font/BFontStorage.cpp b/engines/wintermute/Base/font/BFontStorage.cpp new file mode 100644 index 0000000000..5a0a1e327f --- /dev/null +++ b/engines/wintermute/Base/font/BFontStorage.cpp @@ -0,0 +1,135 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/BGame.h" +#include "engines/wintermute/PlatformSDL.h" +#include "common/str.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFontStorage, true) + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::CBFontStorage(CBGame *inGame): CBBase(inGame) { +} + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::~CBFontStorage() { + cleanup(true); +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontStorage::cleanup(bool warn) { + for (int i = 0; i < _fonts.getSize(); i++) { + if (warn) Game->LOG(0, "Removing orphan font '%s'", _fonts[i]->_filename); + delete _fonts[i]; + } + _fonts.removeAll(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontStorage::initLoop() { + for (int i = 0; i < _fonts.getSize(); i++) { + _fonts[i]->initLoop(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFontStorage::addFont(const char *filename) { + if (!filename) return NULL; + + for (int i = 0; i < _fonts.getSize(); i++) { + if (scumm_stricmp(_fonts[i]->_filename, filename) == 0) { + _fonts[i]->_refCount++; + return _fonts[i]; + } + } + + /* + CBFont* font = new CBFont(Game); + if (!font) return NULL; + + if (DID_FAIL(font->loadFile(filename))) { + delete font; + return NULL; + } + else { + font->_refCount = 1; + _fonts.add(font); + return font; + } + */ + CBFont *font = CBFont::createFromFile(Game, filename); + if (font) { + font->_refCount = 1; + _fonts.add(font); + } + return font; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontStorage::removeFont(CBFont *font) { + if (!font) return STATUS_FAILED; + + for (int i = 0; i < _fonts.getSize(); i++) { + if (_fonts[i] == font) { + _fonts[i]->_refCount--; + if (_fonts[i]->_refCount <= 0) { + delete _fonts[i]; + _fonts.removeAt(i); + } + break; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontStorage::persist(CBPersistMgr *persistMgr) { + + if (!persistMgr->_saving) cleanup(false); + + persistMgr->transfer(TMEMBER(Game)); + _fonts.persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/font/BFontStorage.h b/engines/wintermute/Base/font/BFontStorage.h new file mode 100644 index 0000000000..33a1bb056f --- /dev/null +++ b/engines/wintermute/Base/font/BFontStorage.h @@ -0,0 +1,55 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTSTORAGE_H +#define WINTERMUTE_BFONTSTORAGE_H + + +#include "engines/wintermute/Base/BBase.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/coll_templ.h" + +namespace WinterMute { + +class CBFont; + +class CBFontStorage : public CBBase { +public: + DECLARE_PERSISTENT(CBFontStorage, CBBase) + ERRORCODE cleanup(bool warn = false); + ERRORCODE removeFont(CBFont *font); + CBFont *addFont(const char *filename); + CBFontStorage(CBGame *inGame); + virtual ~CBFontStorage(); + CBArray _fonts; + ERRORCODE initLoop(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/font/BFontTT.cpp b/engines/wintermute/Base/font/BFontTT.cpp new file mode 100644 index 0000000000..ec20c0e393 --- /dev/null +++ b/engines/wintermute/Base/font/BFontTT.cpp @@ -0,0 +1,758 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/file/BFile.h" +#include "engines/wintermute/Base/font/BFontTT.h" +#include "engines/wintermute/utils/PathUtil.h" +#include "engines/wintermute/utils/StringUtil.h" +#include "engines/wintermute/math/MathUtil.h" +#include "engines/wintermute/Base/BRenderer.h" +#include "engines/wintermute/Base/BSurface.h" +#include "engines/wintermute/Base/BParser.h" +#include "engines/wintermute/Base/BGame.h" +#include "engines/wintermute/Base/BFileManager.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/PlatformSDL.h" +#include "graphics/fonts/ttf.h" +#include "graphics/fontman.h" +#include + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBFontTT, false) + +////////////////////////////////////////////////////////////////////////// +CBFontTT::CBFontTT(CBGame *inGame): CBFont(inGame) { + _fontHeight = 12; + _isBold = _isItalic = _isUnderline = _isStriked = false; + + _fontFile = NULL; + _font = NULL; + _fallbackFont = NULL; + _deletableFont = NULL; + + for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; + +#if 0 + _fTFace = NULL; + _fTStream = NULL; +#endif + + _ascender = _descender = _lineHeight = _pointSize = _underlinePos = 0; + _horDpi = _vertDpi = 0; + _maxCharWidth = _maxCharHeight = 0; +} + +////////////////////////////////////////////////////////////////////////// +CBFontTT::~CBFontTT(void) { + clearCache(); + + for (int i = 0; i < _layers.getSize(); i++) { + delete _layers[i]; + } + _layers.removeAll(); + + delete[] _fontFile; + _fontFile = NULL; + + delete _deletableFont; + _font = NULL; + +#if 0 + if (_fTFace) { + FT_Done_Face(_fTFace); + _fTFace = NULL; + } + delete[] _fTStream; + _fTStream = NULL; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::clearCache() { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (_cachedTexts[i]) delete _cachedTexts[i]; + _cachedTexts[i] = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::initLoop() { + // we need more aggressive cache management on iOS not to waste too much memory on fonts + if (Game->_constrainedMemory) { + // purge all cached images not used in the last frame + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (_cachedTexts[i] == NULL) continue; + + if (!_cachedTexts[i]->_marked) { + delete _cachedTexts[i]; + _cachedTexts[i] = NULL; + } else _cachedTexts[i]->_marked = false; + } + } +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::getTextWidth(byte *text, int maxLength) { + WideString textStr; + + if (Game->_textEncoding == TEXT_UTF8) textStr = StringUtil::utf8ToWide((char *)text); + else textStr = StringUtil::ansiToWide((char *)text); + + if (maxLength >= 0 && textStr.size() > (uint32)maxLength) + textStr = Common::String(textStr.c_str(), (uint32)maxLength); + //text = text.substr(0, MaxLength); // TODO: Remove + + int textWidth, textHeight; + measureText(textStr, -1, -1, textWidth, textHeight); + + return textWidth; +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::getTextHeight(byte *text, int width) { + WideString textStr; + + if (Game->_textEncoding == TEXT_UTF8) textStr = StringUtil::utf8ToWide((char *)text); + else textStr = StringUtil::ansiToWide((char *)text); + + + int textWidth, textHeight; + measureText(textStr, width, -1, textWidth, textHeight); + + return textHeight; +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::drawText(byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { + if (text == NULL || strcmp((char *)text, "") == 0) return; + + WideString textStr = (char *)text; + + // TODO: Why do we still insist on Widestrings everywhere? + /* if (Game->_textEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); + else text = StringUtil::AnsiToWide((char *)Text);*/ + + if (maxLength >= 0 && textStr.size() > (uint32)maxLength) + textStr = Common::String(textStr.c_str(), (uint32)maxLength); + //text = text.substr(0, MaxLength); // TODO: Remove + + CBRenderer *renderer = Game->_renderer; + + // find cached surface, if exists + int minPriority = INT_MAX; + int minIndex = -1; + CBSurface *surface = NULL; + int textOffset = 0; + + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (_cachedTexts[i] == NULL) { + minPriority = 0; + minIndex = i; + } else { + if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) { + surface = _cachedTexts[i]->_surface; + textOffset = _cachedTexts[i]->_textOffset; + _cachedTexts[i]->_priority++; + _cachedTexts[i]->_marked = true; + break; + } else { + if (_cachedTexts[i]->_priority < minPriority) { + minPriority = _cachedTexts[i]->_priority; + minIndex = i; + } + } + } + } + + // not found, create one + if (!surface) { + warning("Draw text: %s", text); + surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset); + if (surface) { + // write surface to cache + if (_cachedTexts[minIndex] != NULL) delete _cachedTexts[minIndex]; + _cachedTexts[minIndex] = new CBCachedTTFontText; + + _cachedTexts[minIndex]->_surface = surface; + _cachedTexts[minIndex]->_align = align; + _cachedTexts[minIndex]->_width = width; + _cachedTexts[minIndex]->_maxHeight = maxHeight; + _cachedTexts[minIndex]->_maxLength = maxLength; + _cachedTexts[minIndex]->_priority = 1; + _cachedTexts[minIndex]->_text = textStr; + _cachedTexts[minIndex]->_textOffset = textOffset; + _cachedTexts[minIndex]->_marked = true; + } + } + + + // and paint it + if (surface) { + Rect32 rc; + CBPlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight()); + for (int i = 0; i < _layers.getSize(); i++) { + uint32 color = _layers[i]->_color; + uint32 origForceAlpha = renderer->_forceAlphaColor; + if (renderer->_forceAlphaColor != 0) { + color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor)); + renderer->_forceAlphaColor = 0; + } + surface->displayTransOffset(x, y - textOffset, rc, color, BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY); + + renderer->_forceAlphaColor = origForceAlpha; + } + } + + +} + +////////////////////////////////////////////////////////////////////////// +CBSurface *CBFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { + //TextLineList lines; + // TODO + //WrapText(text, width, maxHeight, lines); + Common::Array lines; + _font->wordWrapText(text, width, lines); + + Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; + if (align == TAL_LEFT) { + alignment = Graphics::kTextAlignLeft; + } else if (align == TAL_CENTER) { + alignment = Graphics::kTextAlignCenter; + } else if (align == TAL_RIGHT) { + alignment = Graphics::kTextAlignRight; + } + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("CBFontTT::RenderTextToTexture - Not fully ported yet"); + } + warning("%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); +// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; + Graphics::Surface *surface = new Graphics::Surface(); + surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15)); + + uint16 useColor = 0xffff; + Common::Array::iterator it; + int heightOffset = 0; + for (it = lines.begin(); it != lines.end(); it++) { + _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); + heightOffset += (int)_lineHeight; + } + + CBSurface *retSurface = Game->_renderer->createSurface(); + Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8 , 0)); + retSurface->putSurface(*convertedSurface, true); + convertedSurface->free(); + surface->free(); + delete surface; + delete convertedSurface; + return retSurface; +#if 0 //TODO + int textHeight = lines.size() * (_maxCharHeight + _ascender); + SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); + + SDL_LockSurface(surface); + + int posY = (int)GetLineHeight() - (int)_descender; + + for (it = lines.begin(); it != lines.end(); ++it) { + TextLine *line = (*it); + int posX = 0; + + switch (align) { + case TAL_CENTER: + posX += (width - line->GetWidth()) / 2; + break; + + case TAL_RIGHT: + posX += width - line->GetWidth(); + break; + } + + + textOffset = 0; + for (size_t i = 0; i < line->GetText().size(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = _glyphCache->GetGlyph(ch); + if (!glyph) continue; + + textOffset = MAX(textOffset, glyph->GetBearingY()); + } + + + int origPosX = posX; + + wchar_t prevChar = L'\0'; + for (size_t i = 0; i < line->GetText().size(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = _glyphCache->GetGlyph(ch); + if (!glyph) continue; + + float kerning = 0; + if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); + posX += (int)kerning; + + + if (glyph->GetBearingY() > 0) { + int i = 10; + } + + SDL_Rect rect; + rect.x = posX + glyph->GetBearingX(); + rect.y = posY - glyph->GetBearingY() + textOffset; + rect.w = glyph->GetImage()->w; + rect.h = glyph->GetImage()->h; + + BlitSurface(glyph->GetImage(), surface, &rect); + + prevChar = ch; + posX += (int)(glyph->GetAdvanceX()); + posY += (int)(glyph->GetAdvanceY()); + } + + if (_isUnderline) { + for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { + Uint8 *buf = (Uint8 *)surface->pixels + (int)(_underlinePos + _ascender) * surface->pitch; + Uint32 *buf32 = (Uint32 *)buf; + + buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); + } + } + + SDL_UnlockSurface(surface); + + delete line; + line = NULL; + posY += GetLineHeight(); + } + + CBSurfaceSDL *wmeSurface = new CBSurfaceSDL(Game); + if (DID_SUCCEED(wmeSurface->CreateFromSDLSurface(surface))) { + SDL_FreeSurface(surface); + return wmeSurface; + } else { + SDL_FreeSurface(surface); + delete wmeSurface; + return NULL; + } +#endif + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect) { + //SDL_BlitSurface(src, NULL, target, targetRect); + warning("CBFontTT::BlitSurface - not ported yet"); +#if 0 + for (int y = 0; y < src->h; y++) { + if (targetRect->y + y < 0 || targetRect->y + y >= target->h) continue; + + + uint8 *srcBuf = (uint8 *)src->pixels + y * src->pitch; + uint8 *tgtBuf = (uint8 *)target->pixels + (y + targetRect->y) * target->pitch; + + uint32 *srcBuf32 = (uint32 *)srcBuf; + uint32 *tgtBuf32 = (uint32 *)tgtBuf; + + for (int x = 0; x < src->w; x++) { + if (targetRect->x + x < 0 || targetRect->x + x >= target->w) continue; + + tgtBuf32[x + targetRect->x] = srcBuf32[x]; + } + } +#endif +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::getLetterHeight() { + return (int)getLineHeight(); +} + + +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontTT::loadFile(const char *filename) { + byte *buffer = Game->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + Game->LOG(0, "CBFontTT::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + ERRORCODE ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + if (DID_FAIL(ret = loadBuffer(buffer))) Game->LOG(0, "Error parsing TTFONT file '%s'", filename); + + delete [] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(TTFONT) +TOKEN_DEF(SIZE) +TOKEN_DEF(FACE) +TOKEN_DEF(FILENAME) +TOKEN_DEF(BOLD) +TOKEN_DEF(ITALIC) +TOKEN_DEF(UNDERLINE) +TOKEN_DEF(STRIKE) +TOKEN_DEF(CHARSET) +TOKEN_DEF(COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(LAYER) +TOKEN_DEF(OFFSET_X) +TOKEN_DEF(OFFSET_Y) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontTT::loadBuffer(byte *buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(TTFONT) + TOKEN_TABLE(SIZE) + TOKEN_TABLE(FACE) + TOKEN_TABLE(FILENAME) + TOKEN_TABLE(BOLD) + TOKEN_TABLE(ITALIC) + TOKEN_TABLE(UNDERLINE) + TOKEN_TABLE(STRIKE) + TOKEN_TABLE(CHARSET) + TOKEN_TABLE(COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(LAYER) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TTFONT) { + Game->LOG(0, "'TTFONT' keyword expected."); + return STATUS_FAILED; + } + buffer = (byte *)params; + + uint32 BaseColor = 0x00000000; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_SIZE: + parser.scanStr(params, "%d", &_fontHeight); + break; + + case TOKEN_FACE: + // we don't need this anymore + break; + + case TOKEN_FILENAME: + CBUtils::setString(&_fontFile, params); + break; + + case TOKEN_BOLD: + parser.scanStr(params, "%b", &_isBold); + break; + + case TOKEN_ITALIC: + parser.scanStr(params, "%b", &_isItalic); + break; + + case TOKEN_UNDERLINE: + parser.scanStr(params, "%b", &_isUnderline); + break; + + case TOKEN_STRIKE: + parser.scanStr(params, "%b", &_isStriked); + break; + + case TOKEN_CHARSET: + // we don't need this anymore + break; + + case TOKEN_COLOR: { + int r, g, b; + parser.scanStr(params, "%d,%d,%d", &r, &g, &b); + BaseColor = BYTETORGBA(r, g, b, RGBCOLGetA(BaseColor)); + } + break; + + case TOKEN_ALPHA: { + int a; + parser.scanStr(params, "%d", &a); + BaseColor = BYTETORGBA(RGBCOLGetR(BaseColor), RGBCOLGetG(BaseColor), RGBCOLGetB(BaseColor), a); + } + break; + + case TOKEN_LAYER: { + CBTTFontLayer *Layer = new CBTTFontLayer; + if (Layer && DID_SUCCEED(parseLayer(Layer, (byte *)params))) _layers.add(Layer); + else { + delete Layer; + Layer = NULL; + cmd = PARSERR_TOKENNOTFOUND; + } + } + break; + + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in TTFONT definition"); + return STATUS_FAILED; + } + + // create at least one layer + if (_layers.getSize() == 0) { + CBTTFontLayer *Layer = new CBTTFontLayer; + Layer->_color = BaseColor; + _layers.add(Layer); + } + + if (!_fontFile) CBUtils::setString(&_fontFile, "arial.ttf"); + + return initFont(); +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontTT::parseLayer(CBTTFontLayer *layer, byte *buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(OFFSET_X) + TOKEN_TABLE(OFFSET_Y) + TOKEN_TABLE(COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_OFFSET_X: + parser.scanStr(params, "%d", &layer->_offsetX); + break; + + case TOKEN_OFFSET_Y: + parser.scanStr(params, "%d", &layer->_offsetY); + break; + + case TOKEN_COLOR: { + int r, g, b; + parser.scanStr(params, "%d,%d,%d", &r, &g, &b); + layer->_color = BYTETORGBA(r, g, b, RGBCOLGetA(layer->_color)); + } + break; + + case TOKEN_ALPHA: { + int a; + parser.scanStr(params, "%d", &a); + layer->_color = BYTETORGBA(RGBCOLGetR(layer->_color), RGBCOLGetG(layer->_color), RGBCOLGetB(layer->_color), a); + } + break; + } + } + if (cmd != PARSERR_EOF) return STATUS_FAILED; + else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontTT::persist(CBPersistMgr *persistMgr) { + CBFont::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_isBold)); + persistMgr->transfer(TMEMBER(_isItalic)); + persistMgr->transfer(TMEMBER(_isUnderline)); + persistMgr->transfer(TMEMBER(_isStriked)); + persistMgr->transfer(TMEMBER(_fontHeight)); + persistMgr->transfer(TMEMBER(_fontFile)); + + + // persist layers + int numLayers; + if (persistMgr->_saving) { + numLayers = _layers.getSize(); + persistMgr->transfer(TMEMBER(numLayers)); + for (int i = 0; i < numLayers; i++) _layers[i]->persist(persistMgr); + } else { + numLayers = _layers.getSize(); + persistMgr->transfer(TMEMBER(numLayers)); + for (int i = 0; i < numLayers; i++) { + CBTTFontLayer *layer = new CBTTFontLayer; + layer->persist(persistMgr); + _layers.add(layer); + } + } + + if (!persistMgr->_saving) { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; + _fallbackFont = _font = _deletableFont = NULL; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::afterLoad() { + initFont(); +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CBFontTT::initFont() { + if (!_fontFile) return STATUS_FAILED; + + Common::SeekableReadStream *file = Game->_fileManager->openFile(_fontFile); + if (!file) { + // the requested font file is not in wme file space; try loading a system font + AnsiString fontFileName = PathUtil::combine(CBPlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile)); + file = Game->_fileManager->openFile(fontFileName.c_str(), false); + if (!file) { + Game->LOG(0, "Error loading TrueType font '%s'", _fontFile); + //return STATUS_FAILED; + } + } + + if (file) { +#ifdef USE_FREETYPE2 + _deletableFont = Graphics::loadTTFFont(*file, _fontHeight * 4 / 3); // Compensate for the difference in dpi (96 vs 72). + _font = _deletableFont; +#endif + } + if (!_font) { + _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + warning("BFontTT::InitFont - Couldn't load %s", _fontFile); + } + _lineHeight = _font->getFontHeight(); + return STATUS_OK; +#if 0 + FT_Error error; + + float vertDpi = 96.0; + float horDpi = 96.0; + + + _fTStream = (FT_Stream)new byte[sizeof(*_fTStream)]; + memset(_fTStream, 0, sizeof(*_fTStream)); + + _fTStream->read = CBFontTT::FTReadSeekProc; + _fTStream->close = CBFontTT::FTCloseProc; + _fTStream->descriptor.pointer = file; + _fTStream->size = file->GetSize(); + + FT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = _fTStream; + + error = FT_Open_Face(Game->_fontStorage->GetFTLibrary(), &args, 0, &_fTFace); + if (error) { + SAFE_DELETE_ARRAY(_fTStream); + Game->_fileManager->closeFile(file); + return STATUS_FAILED; + } + + error = FT_Set_Char_Size(_fTFace, 0, (FT_F26Dot6)(_fontHeight * 64), (FT_UInt)horDpi, (FT_UInt)vertDpi); + if (error) { + FT_Done_Face(_fTFace); + _fTFace = NULL; + return STATUS_FAILED; + } + + // http://en.wikipedia.org/wiki/E_(typography) + float pixelsPerEm = (_fontHeight / 72.f) * vertDpi; // Size in inches * dpi + float EmsPerUnit = 1.0f / _fTFace->units_per_EM; + float pixelsPerUnit = pixelsPerEm * EmsPerUnit; + + // bounding box in pixels + float xMin = _fTFace->bbox.xMin * pixelsPerUnit; + float xMax = _fTFace->bbox.xMax * pixelsPerUnit; + float yMin = _fTFace->bbox.yMin * pixelsPerUnit; + float yMax = _fTFace->bbox.yMax * pixelsPerUnit; + + // metrics in pixels + _ascender = _fTFace->ascender * pixelsPerUnit; + _descender = - _fTFace->descender * pixelsPerUnit; + _lineHeight = MathUtil::RoundUp(_fTFace->height * pixelsPerUnit) + 2; + _underlinePos = - _fTFace->underline_position * pixelsPerUnit; + + // max character size (used for texture grid) + _maxCharWidth = (size_t)MathUtil::RoundUp(xMax - xMin); + _maxCharHeight = (size_t)MathUtil::RoundUp(yMax - yMin); + + _glyphCache = new FontGlyphCache(); + _glyphCache->Initialize(); + +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) { + //TextLineList lines; + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("Todo: Test Mesuretext"); + } + if (maxWidth >= 0) { + Common::Array lines; + _font->wordWrapText(text, maxWidth, lines); + Common::Array::iterator it; + textWidth = 0; + for (it = lines.begin(); it != lines.end(); it++) { + textWidth = MAX(textWidth, _font->getStringWidth(*it)); + } + + //WrapText(text, maxWidth, maxHeight, lines); + + textHeight = (int)(lines.size() * getLineHeight()); + } else { + textWidth = _font->getStringWidth(text); + textHeight = _fontHeight; + } + /* + TextLineList::iterator it; + for (it = lines.begin(); it != lines.end(); ++it) { + TextLine *line = (*it); + textWidth = MAX(textWidth, line->GetWidth()); + delete line; + line = NULL; + }*/ +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/font/BFontTT.h b/engines/wintermute/Base/font/BFontTT.h new file mode 100644 index 0000000000..1ee9f1d105 --- /dev/null +++ b/engines/wintermute/Base/font/BFontTT.h @@ -0,0 +1,180 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTTT_H +#define WINTERMUTE_BFONTTT_H + +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/BSurface.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "graphics/font.h" + +#define NUM_CACHED_TEXTS 30 + +namespace WinterMute { + +class CBFontTT : public CBFont { +private: + ////////////////////////////////////////////////////////////////////////// + class CBCachedTTFontText { + public: + WideString _text; + int _width; + TTextAlign _align; + int _maxHeight; + int _maxLength; + CBSurface *_surface; + int _priority; + int _textOffset; + bool _marked; + + CBCachedTTFontText() { + //_text = L""; + _text = ""; + _width = _maxHeight = _maxLength = -1; + _align = TAL_LEFT; + _surface = NULL; + _priority = -1; + _textOffset = 0; + _marked = false; + } + + virtual ~CBCachedTTFontText() { + if (_surface) delete _surface; + } + }; + +public: + ////////////////////////////////////////////////////////////////////////// + class CBTTFontLayer { + public: + CBTTFontLayer() { + _offsetX = _offsetY = 0; + _color = 0x00000000; + } + + ERRORCODE persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_offsetX)); + persistMgr->transfer(TMEMBER(_offsetY)); + persistMgr->transfer(TMEMBER(_color)); + return STATUS_OK; + } + + int _offsetX; + int _offsetY; + uint32 _color; + }; + + ////////////////////////////////////////////////////////////////////////// + class TextLine { + public: + TextLine(const WideString &text, int width) { + _text = text; + _width = width; + } + + const WideString getText() const { + return _text; + } + int getWidth() const { + return _width; + } + private: + WideString _text; + int _width; + }; + typedef Common::List TextLineList; + + +public: + DECLARE_PERSISTENT(CBFontTT, CBFont) + CBFontTT(CBGame *inGame); + virtual ~CBFontTT(void); + + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); + virtual int getLetterHeight(); + + ERRORCODE loadBuffer(byte *buffer); + ERRORCODE loadFile(const char *filename); + + float getLineHeight() const { + return _lineHeight; + } + + void afterLoad(); + void initLoop(); + +private: + ERRORCODE parseLayer(CBTTFontLayer *layer, byte *buffer); + + void wrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines); + void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight); + + CBSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset); + void blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect); + + + CBCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS]; + + ERRORCODE initFont(); + + Graphics::Font *_deletableFont; + const Graphics::Font *_font; + const Graphics::Font *_fallbackFont; + + float _ascender; + float _descender; + float _lineHeight; + float _underlinePos; + float _pointSize; + float _vertDpi; + float _horDpi; + + size_t _maxCharWidth; + size_t _maxCharHeight; + +public: + bool _isBold; + bool _isItalic; + bool _isUnderline; + bool _isStriked; + int _fontHeight; + char *_fontFile; + + CBArray _layers; + void clearCache(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/particles/PartEmitter.cpp b/engines/wintermute/Base/particles/PartEmitter.cpp new file mode 100644 index 0000000000..9a92d2aa6e --- /dev/null +++ b/engines/wintermute/Base/particles/PartEmitter.cpp @@ -0,0 +1,1199 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/particles/PartEmitter.h" +#include "engines/wintermute/Base/particles/PartParticle.h" +#include "engines/wintermute/math/Vector2.h" +#include "engines/wintermute/math/Matrix4.h" +#include "engines/wintermute/Base/scriptables/ScValue.h" +#include "engines/wintermute/Base/scriptables/ScStack.h" +#include "engines/wintermute/Base/BGame.h" +#include "engines/wintermute/Base/BRegion.h" +#include "engines/wintermute/Base/BFileManager.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/PlatformSDL.h" +#include "common/str.h" +#include "common/math.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CPartEmitter, false) + +////////////////////////////////////////////////////////////////////////// +CPartEmitter::CPartEmitter(CBGame *inGame, CBScriptHolder *Owner) : CBObject(inGame) { + _width = _height = 0; + + CBPlatform::setRectEmpty(&_border); + _borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0; + + _angle1 = _angle2 = 0; + + _velocity1 = _velocity2 = 0.0f; + _velocityZBased = false; + + _scale1 = _scale2 = 100.0f; + _scaleZBased = false; + + _maxParticles = 100; + + _lifeTime1 = _lifeTime2 = 1000; + _lifeTimeZBased = false; + + _lastGenTime = 0; + _genInterval = 0; + _genAmount = 1; + + _overheadTime = 0; + _running = false; + + _maxBatches = 0; + _batchesGenerated = 0; + + _fadeInTime = _fadeOutTime = 0; + + _alpha1 = _alpha2 = 255; + _alphaTimeBased = false; + + _rotation1 = _rotation2 = 0.0f; + _angVelocity1 = _angVelocity2 = 0.0f; + + _growthRate1 = _growthRate2 = 0.0f; + _exponentialGrowth = false; + + _useRegion = false; + + _emitEvent = NULL; + _owner = Owner; +} + + +////////////////////////////////////////////////////////////////////////// +CPartEmitter::~CPartEmitter(void) { + for (int i = 0; i < _particles.getSize(); i++) { + delete _particles[i]; + } + _particles.removeAll(); + + for (int i = 0; i < _forces.getSize(); i++) { + delete _forces[i]; + } + _forces.removeAll(); + + + for (int i = 0; i < _sprites.getSize(); i++) { + delete [] _sprites[i]; + } + _sprites.removeAll(); + + delete[] _emitEvent; + _emitEvent = NULL; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::addSprite(const char *filename) { + if (!filename) return STATUS_FAILED; + + // do we already have the file? + for (int i = 0; i < _sprites.getSize(); i++) { + if (scumm_stricmp(filename, _sprites[i]) == 0) return STATUS_OK; + } + + // check if file exists + Common::SeekableReadStream *File = Game->_fileManager->openFile(filename); + if (!File) { + Game->LOG(0, "Sprite '%s' not found", filename); + return STATUS_FAILED; + } else Game->_fileManager->closeFile(File); + + char *Str = new char[strlen(filename) + 1]; + strcpy(Str, filename); + _sprites.add(Str); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::removeSprite(const char *filename) { + for (int i = 0; i < _sprites.getSize(); i++) { + if (scumm_stricmp(filename, _sprites[i]) == 0) { + delete [] _sprites[i]; + _sprites.removeAt(i); + return STATUS_OK; + } + } + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta) { + if (!particle) return STATUS_FAILED; + if (_sprites.getSize() == 0) return STATUS_FAILED; + + int posX = CBUtils::randomInt(_posX, _posX + _width); + int posY = CBUtils::randomInt(_posY, _posY + _height); + float posZ = CBUtils::randomFloat(0.0f, 100.0f); + + float velocity; + if (_velocityZBased) velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100; + else velocity = CBUtils::randomFloat(_velocity1, _velocity2); + + float scale; + if (_scaleZBased) scale = _scale1 + posZ * (_scale2 - _scale1) / 100; + else scale = CBUtils::randomFloat(_scale1, _scale2); + + int lifeTime; + if (_lifeTimeZBased) lifeTime = _lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100; + else lifeTime = CBUtils::randomInt(_lifeTime1, _lifeTime2); + + float angle = CBUtils::randomAngle(_angle1, _angle2); + int spriteIndex = CBUtils::randomInt(0, _sprites.getSize() - 1); + + float rotation = CBUtils::randomAngle(_rotation1, _rotation2); + float angVelocity = CBUtils::randomFloat(_angVelocity1, _angVelocity2); + float growthRate = CBUtils::randomFloat(_growthRate1, _growthRate2); + + if (!CBPlatform::isRectEmpty(&_border)) { + int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f); + int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f); + int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f); + int thicknessBottom = (int)(_borderThicknessBottom - (float)_borderThicknessBottom * posZ / 100.0f); + + particle->_border = _border; + particle->_border.left += thicknessLeft; + particle->_border.right -= thicknessRight; + particle->_border.top += thicknessTop; + particle->_border.bottom -= thicknessBottom; + } + + Vector2 vecPos((float)posX, (float)posY); + Vector2 vecVel(0, velocity); + + Matrix4 matRot; + matRot.rotationZ(Common::deg2rad(CBUtils::normalizeAngle(angle - 180))); + matRot.transformVector2(vecVel); + + if (_alphaTimeBased) { + particle->_alpha1 = _alpha1; + particle->_alpha2 = _alpha2; + } else { + int alpha = CBUtils::randomInt(_alpha1, _alpha2); + particle->_alpha1 = alpha; + particle->_alpha2 = alpha; + } + + particle->_creationTime = currentTime; + particle->_pos = vecPos; + particle->_posZ = posZ; + particle->_velocity = vecVel; + particle->_scale = scale; + particle->_lifeTime = lifeTime; + particle->_rotation = rotation; + particle->_angVelocity = angVelocity; + particle->_growthRate = growthRate; + particle->_exponentialGrowth = _exponentialGrowth; + particle->_isDead = DID_FAIL(particle->setSprite(_sprites[spriteIndex])); + particle->fadeIn(currentTime, _fadeInTime); + + + if (particle->_isDead) return STATUS_FAILED; + else return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::update() { + if (!_running) return STATUS_OK; + else return updateInternal(Game->_timer, Game->_timerDelta); +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) { + int numLive = 0; + + for (int i = 0; i < _particles.getSize(); i++) { + _particles[i]->update(this, currentTime, timerDelta); + + if (!_particles[i]->_isDead) numLive++; + } + + + // we're understaffed + if (numLive < _maxParticles) { + bool needsSort = false; + if ((int)(currentTime - _lastGenTime) > _genInterval) { + _lastGenTime = currentTime; + _batchesGenerated++; + + if (_maxBatches > 0 && _batchesGenerated > _maxBatches) { + return STATUS_OK; + } + + int toGen = MIN(_genAmount, _maxParticles - numLive); + while (toGen > 0) { + int firstDeadIndex = -1; + for (int i = 0; i < _particles.getSize(); i++) { + if (_particles[i]->_isDead) { + firstDeadIndex = i; + break; + } + } + + CPartParticle *particle; + if (firstDeadIndex >= 0) particle = _particles[firstDeadIndex]; + else { + particle = new CPartParticle(Game); + _particles.add(particle); + } + initParticle(particle, currentTime, timerDelta); + needsSort = true; + + toGen--; + } + } + if (needsSort && (_scaleZBased || _velocityZBased || _lifeTimeZBased)) + sortParticlesByZ(); + + // we actually generated some particles and we're not in fast-forward mode + if (needsSort && _overheadTime == 0) { + if (_owner && _emitEvent) _owner->applyEvent(_emitEvent); + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::display(CBRegion *region) { + if (_sprites.getSize() <= 1) Game->_renderer->startSpriteBatch(); + + for (int i = 0; i < _particles.getSize(); i++) { + if (region != NULL && _useRegion) { + if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) continue; + } + + _particles[i]->display(this); + } + + if (_sprites.getSize() <= 1) Game->_renderer->endSpriteBatch(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::start() { + for (int i = 0; i < _particles.getSize(); i++) { + _particles[i]->_isDead = true; + } + _running = true; + _batchesGenerated = 0; + + + if (_overheadTime > 0) { + uint32 delta = 500; + int steps = _overheadTime / delta; + uint32 currentTime = Game->_timer - _overheadTime; + + for (int i = 0; i < steps; i++) { + updateInternal(currentTime, delta); + currentTime += delta; + } + _overheadTime = 0; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::sortParticlesByZ() { + // sort particles by _posY + qsort(_particles.getData(), _particles.getSize(), sizeof(CPartParticle *), CPartEmitter::compareZ); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int CPartEmitter::compareZ(const void *obj1, const void *obj2) { + CPartParticle *p1 = *(CPartParticle **)obj1; + CPartParticle *p2 = *(CPartParticle **)obj2; + + if (p1->_posZ < p2->_posZ) return -1; + else if (p1->_posZ > p2->_posZ) return 1; + else return 0; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::setBorder(int x, int y, int width, int height) { + CBPlatform::setRect(&_border, x, y, x + width, y + height); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) { + _borderThicknessLeft = thicknessLeft; + _borderThicknessRight = thicknessRight; + _borderThicknessTop = thicknessTop; + _borderThicknessBottom = thicknessBottom; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CPartForce *CPartEmitter::addForceByName(const char *name) { + CPartForce *force = NULL; + + for (int i = 0; i < _forces.getSize(); i++) { + if (scumm_stricmp(name, _forces[i]->_name) == 0) { + force = _forces[i]; + break; + } + } + if (!force) { + force = new CPartForce(Game); + if (force) { + force->setName(name); + _forces.add(force); + } + } + return force; +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength) { + CPartForce *force = addForceByName(name); + if (!force) return STATUS_FAILED; + + force->_type = type; + force->_pos = Vector2(posX, posY); + + force->_direction = Vector2(0, strength); + Matrix4 matRot; + matRot.rotationZ(Common::deg2rad(CBUtils::normalizeAngle(angle - 180))); + matRot.transformVector2(force->_direction); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::removeForce(const char *name) { + for (int i = 0; i < _forces.getSize(); i++) { + if (scumm_stricmp(name, _forces[i]->_name) == 0) { + delete _forces[i]; + _forces.removeAt(i); + return STATUS_OK; + } + } + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetBorder + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetBorder") == 0) { + stack->correctParams(4); + int borderX = stack->pop()->getInt(); + int borderY = stack->pop()->getInt(); + int borderWidth = stack->pop()->getInt(); + int borderHeight = stack->pop()->getInt(); + + stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight))); + + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetBorderThickness + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetBorderThickness") == 0) { + stack->correctParams(4); + int left = stack->pop()->getInt(); + int right = stack->pop()->getInt(); + int top = stack->pop()->getInt(); + int bottom = stack->pop()->getInt(); + + stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom))); + + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // AddSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddSprite") == 0) { + stack->correctParams(1); + const char *spriteFile = stack->pop()->getString(); + stack->pushBool(DID_SUCCEED(addSprite(spriteFile))); + + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // RemoveSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveSprite") == 0) { + stack->correctParams(1); + const char *spriteFile = stack->pop()->getString(); + stack->pushBool(DID_SUCCEED(removeSprite(spriteFile))); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Start + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Start") == 0) { + stack->correctParams(1); + _overheadTime = stack->pop()->getInt(); + stack->pushBool(DID_SUCCEED(start())); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Stop + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Stop") == 0) { + stack->correctParams(0); + + for (int i = 0; i < _particles.getSize(); i++) { + delete _particles[i]; + } + _particles.removeAll(); + + _running = false; + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Pause + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Pause") == 0) { + stack->correctParams(0); + _running = false; + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Resume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Resume") == 0) { + stack->correctParams(0); + _running = true; + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddGlobalForce + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddGlobalForce") == 0) { + stack->correctParams(3); + const char *forceName = stack->pop()->getString(); + float angle = stack->pop()->getFloat(); + float strength = stack->pop()->getFloat(); + + stack->pushBool(DID_SUCCEED(addForce(forceName, CPartForce::FORCE_GLOBAL, 0, 0, angle, strength))); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddPointForce + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddPointForce") == 0) { + stack->correctParams(5); + const char *forceName = stack->pop()->getString(); + int posX = stack->pop()->getInt(); + int posY = stack->pop()->getInt(); + float angle = stack->pop()->getFloat(); + float strength = stack->pop()->getFloat(); + + stack->pushBool(DID_SUCCEED(addForce(forceName, CPartForce::FORCE_GLOBAL, posX, posY, angle, strength))); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveForce + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveForce") == 0) { + stack->correctParams(1); + const char *forceName = stack->pop()->getString(); + + stack->pushBool(DID_SUCCEED(removeForce(forceName))); + + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + +////////////////////////////////////////////////////////////////////////// +CScValue *CPartEmitter::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("particle-emitter"); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // X + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "X") == 0) { + _scValue->setInt(_posX); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Y + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Y") == 0) { + _scValue->setInt(_posY); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Width + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Width") == 0) { + _scValue->setInt(_width); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Height + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Height") == 0) { + _scValue->setInt(_height); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Scale1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale1") == 0) { + _scValue->setFloat(_scale1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Scale2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale2") == 0) { + _scValue->setFloat(_scale2); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // ScaleZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScaleZBased") == 0) { + _scValue->setBool(_scaleZBased); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Velocity1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Velocity1") == 0) { + _scValue->setFloat(_velocity1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Velocity2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Velocity2") == 0) { + _scValue->setFloat(_velocity2); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // VelocityZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "VelocityZBased") == 0) { + _scValue->setBool(_velocityZBased); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // LifeTime1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTime1") == 0) { + _scValue->setInt(_lifeTime1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // LifeTime2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTime2") == 0) { + _scValue->setInt(_lifeTime2); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // LifeTimeZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTimeZBased") == 0) { + _scValue->setBool(_lifeTimeZBased); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Angle1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Angle1") == 0) { + _scValue->setInt(_angle1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Angle2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Angle2") == 0) { + _scValue->setInt(_angle2); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AngVelocity1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AngVelocity1") == 0) { + _scValue->setFloat(_angVelocity1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // AngVelocity2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AngVelocity2") == 0) { + _scValue->setFloat(_angVelocity2); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Rotation1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Rotation1") == 0) { + _scValue->setFloat(_rotation1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Rotation2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Rotation2") == 0) { + _scValue->setFloat(_rotation2); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Alpha1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Alpha1") == 0) { + _scValue->setInt(_alpha1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Alpha2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Alpha2") == 0) { + _scValue->setInt(_alpha2); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // AlphaTimeBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AlphaTimeBased") == 0) { + _scValue->setBool(_alphaTimeBased); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MaxParticles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxParticles") == 0) { + _scValue->setInt(_maxParticles); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // NumLiveParticles (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumLiveParticles") == 0) { + int numAlive = 0; + for (int i = 0; i < _particles.getSize(); i++) { + if (_particles[i] && !_particles[i]->_isDead) numAlive++; + } + _scValue->setInt(numAlive); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // GenerationInterval + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GenerationInterval") == 0) { + _scValue->setInt(_genInterval); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // GenerationAmount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GenerationAmount") == 0) { + _scValue->setInt(_genAmount); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // MaxBatches + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxBatches") == 0) { + _scValue->setInt(_maxBatches); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeInTime + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeInTime") == 0) { + _scValue->setInt(_fadeInTime); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // FadeOutTime + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeOutTime") == 0) { + _scValue->setInt(_fadeOutTime); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // GrowthRate1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GrowthRate1") == 0) { + _scValue->setFloat(_growthRate1); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // GrowthRate2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GrowthRate2") == 0) { + _scValue->setFloat(_growthRate2); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // ExponentialGrowth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ExponentialGrowth") == 0) { + _scValue->setBool(_exponentialGrowth); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // UseRegion + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "UseRegion") == 0) { + _scValue->setBool(_useRegion); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // EmitEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "EmitEvent") == 0) { + if (!_emitEvent) _scValue->setNULL(); + else _scValue->setString(_emitEvent); + return _scValue; + } + + else return CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // X + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "X") == 0) { + _posX = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Y + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Y") == 0) { + _posY = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Width + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Width") == 0) { + _width = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Height + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Height") == 0) { + _height = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Scale1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale1") == 0) { + _scale1 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Scale2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale2") == 0) { + _scale2 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // ScaleZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScaleZBased") == 0) { + _scaleZBased = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Velocity1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Velocity1") == 0) { + _velocity1 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Velocity2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Velocity2") == 0) { + _velocity2 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // VelocityZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "VelocityZBased") == 0) { + _velocityZBased = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LifeTime1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTime1") == 0) { + _lifeTime1 = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // LifeTime2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTime2") == 0) { + _lifeTime2 = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // LifeTimeZBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LifeTimeZBased") == 0) { + _lifeTimeZBased = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Angle1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Angle1") == 0) { + _angle1 = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Angle2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Angle2") == 0) { + _angle2 = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AngVelocity1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AngVelocity1") == 0) { + _angVelocity1 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // AngVelocity2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AngVelocity2") == 0) { + _angVelocity2 = value->getFloat(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Rotation1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Rotation1") == 0) { + _rotation1 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Rotation2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Rotation2") == 0) { + _rotation2 = value->getFloat(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Alpha1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Alpha1") == 0) { + _alpha1 = value->getInt(); + if (_alpha1 < 0) _alpha1 = 0; + if (_alpha1 > 255) _alpha1 = 255; + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Alpha2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Alpha2") == 0) { + _alpha2 = value->getInt(); + if (_alpha2 < 0) _alpha2 = 0; + if (_alpha2 > 255) _alpha2 = 255; + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // AlphaTimeBased + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AlphaTimeBased") == 0) { + _alphaTimeBased = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MaxParticles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxParticles") == 0) { + _maxParticles = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GenerationInterval + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GenerationInterval") == 0) { + _genInterval = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GenerationAmount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GenerationAmount") == 0) { + _genAmount = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // MaxBatches + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxBatches") == 0) { + _maxBatches = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeInTime + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeInTime") == 0) { + _fadeInTime = value->getInt(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // FadeOutTime + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeOutTime") == 0) { + _fadeOutTime = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GrowthRate1 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GrowthRate1") == 0) { + _growthRate1 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GrowthRate2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GrowthRate2") == 0) { + _growthRate2 = value->getFloat(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // ExponentialGrowth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ExponentialGrowth") == 0) { + _exponentialGrowth = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // UseRegion + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "UseRegion") == 0) { + _useRegion = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // EmitEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "EmitEvent") == 0) { + delete[] _emitEvent; + _emitEvent = NULL; + if (!value->isNULL()) CBUtils::setString(&_emitEvent, value->getString()); + return STATUS_OK; + } + + else return CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CPartEmitter::scToString() { + return "[particle emitter]"; +} + + + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartEmitter::persist(CBPersistMgr *persistMgr) { + CBObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_width)); + persistMgr->transfer(TMEMBER(_height)); + + persistMgr->transfer(TMEMBER(_angle1)); + persistMgr->transfer(TMEMBER(_angle2)); + + persistMgr->transfer(TMEMBER(_velocity1)); + persistMgr->transfer(TMEMBER(_velocity2)); + persistMgr->transfer(TMEMBER(_velocityZBased)); + + persistMgr->transfer(TMEMBER(_scale1)); + persistMgr->transfer(TMEMBER(_scale2)); + persistMgr->transfer(TMEMBER(_scaleZBased)); + + persistMgr->transfer(TMEMBER(_maxParticles)); + + persistMgr->transfer(TMEMBER(_lifeTime1)); + persistMgr->transfer(TMEMBER(_lifeTime2)); + persistMgr->transfer(TMEMBER(_lifeTimeZBased)); + + persistMgr->transfer(TMEMBER(_genInterval)); + persistMgr->transfer(TMEMBER(_genAmount)); + + persistMgr->transfer(TMEMBER(_running)); + persistMgr->transfer(TMEMBER(_overheadTime)); + + persistMgr->transfer(TMEMBER(_border)); + persistMgr->transfer(TMEMBER(_borderThicknessLeft)); + persistMgr->transfer(TMEMBER(_borderThicknessRight)); + persistMgr->transfer(TMEMBER(_borderThicknessTop)); + persistMgr->transfer(TMEMBER(_borderThicknessBottom)); + + persistMgr->transfer(TMEMBER(_fadeInTime)); + persistMgr->transfer(TMEMBER(_fadeOutTime)); + + persistMgr->transfer(TMEMBER(_alpha1)); + persistMgr->transfer(TMEMBER(_alpha2)); + persistMgr->transfer(TMEMBER(_alphaTimeBased)); + + persistMgr->transfer(TMEMBER(_angVelocity1)); + persistMgr->transfer(TMEMBER(_angVelocity2)); + + persistMgr->transfer(TMEMBER(_rotation1)); + persistMgr->transfer(TMEMBER(_rotation2)); + + persistMgr->transfer(TMEMBER(_growthRate1)); + persistMgr->transfer(TMEMBER(_growthRate2)); + persistMgr->transfer(TMEMBER(_exponentialGrowth)); + + persistMgr->transfer(TMEMBER(_useRegion)); + + persistMgr->transfer(TMEMBER_INT(_maxBatches)); + persistMgr->transfer(TMEMBER_INT(_batchesGenerated)); + + persistMgr->transfer(TMEMBER(_emitEvent)); + persistMgr->transfer(TMEMBER(_owner)); + + + _sprites.persist(persistMgr); + + int numForces; + if (persistMgr->_saving) { + numForces = _forces.getSize(); + persistMgr->transfer(TMEMBER(numForces)); + for (int i = 0; i < _forces.getSize(); i++) { + _forces[i]->persist(persistMgr); + } + } else { + persistMgr->transfer(TMEMBER(numForces)); + for (int i = 0; i < numForces; i++) { + CPartForce *force = new CPartForce(Game); + force->persist(persistMgr); + _forces.add(force); + } + } + + int numParticles; + if (persistMgr->_saving) { + numParticles = _particles.getSize(); + persistMgr->transfer(TMEMBER(numParticles)); + for (int i = 0; i < _particles.getSize(); i++) { + _particles[i]->persist(persistMgr); + } + } else { + persistMgr->transfer(TMEMBER(numParticles)); + for (int i = 0; i < numParticles; i++) { + CPartParticle *particle = new CPartParticle(Game); + particle->persist(persistMgr); + _particles.add(particle); + } + } + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/particles/PartEmitter.h b/engines/wintermute/Base/particles/PartEmitter.h new file mode 100644 index 0000000000..6f517bf357 --- /dev/null +++ b/engines/wintermute/Base/particles/PartEmitter.h @@ -0,0 +1,139 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PARTEMITTER_H +#define WINTERMUTE_PARTEMITTER_H + + +#include "engines/wintermute/Base/BObject.h" +#include "engines/wintermute/Base/particles/PartForce.h" + +namespace WinterMute { +class CBRegion; +class CPartParticle; +class CPartEmitter : public CBObject { +public: + DECLARE_PERSISTENT(CPartEmitter, CBObject) + + CPartEmitter(CBGame *inGame, CBScriptHolder *Owner); + virtual ~CPartEmitter(void); + + int _width; + int _height; + + int _angle1; + int _angle2; + + float _rotation1; + float _rotation2; + + float _angVelocity1; + float _angVelocity2; + + float _growthRate1; + float _growthRate2; + bool _exponentialGrowth; + + float _velocity1; + float _velocity2; + bool _velocityZBased; + + float _scale1; + float _scale2; + bool _scaleZBased; + + int _maxParticles; + + int _lifeTime1; + int _lifeTime2; + bool _lifeTimeZBased; + + int _genInterval; + int _genAmount; + + bool _running; + int _overheadTime; + + int _maxBatches; + int _batchesGenerated; + + Rect32 _border; + int _borderThicknessLeft; + int _borderThicknessRight; + int _borderThicknessTop; + int _borderThicknessBottom; + + int _fadeInTime; + int _fadeOutTime; + + int _alpha1; + int _alpha2; + bool _alphaTimeBased; + + bool _useRegion; + + char *_emitEvent; + CBScriptHolder *_owner; + + ERRORCODE start(); + + ERRORCODE update(); + ERRORCODE display() { return display(NULL); } // To avoid shadowing the inherited display-function. + ERRORCODE display(CBRegion *region); + + ERRORCODE sortParticlesByZ(); + ERRORCODE addSprite(const char *filename); + ERRORCODE removeSprite(const char *filename); + ERRORCODE setBorder(int x, int y, int width, int height); + ERRORCODE setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom); + + ERRORCODE addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength); + ERRORCODE removeForce(const char *name); + + CBArray _forces; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual ERRORCODE scSetProperty(const char *name, CScValue *value); + virtual ERRORCODE scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + + +private: + CPartForce *addForceByName(const char *name); + int static compareZ(const void *obj1, const void *obj2); + ERRORCODE initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta); + ERRORCODE updateInternal(uint32 currentTime, uint32 timerDelta); + uint32 _lastGenTime; + CBArray _particles; + CBArray _sprites; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/particles/PartForce.cpp b/engines/wintermute/Base/particles/PartForce.cpp new file mode 100644 index 0000000000..2da74da14d --- /dev/null +++ b/engines/wintermute/Base/particles/PartForce.cpp @@ -0,0 +1,59 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/Base/particles/PartForce.h" +#include "engines/wintermute/Base/BPersistMgr.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CPartForce::CPartForce(CBGame *inGame) : CBNamedObject(inGame) { + _pos = Vector2(0.0f, 0.0f); + _direction = Vector2(0.0f, 0.0f); + _type = FORCE_POINT; +} + + +////////////////////////////////////////////////////////////////////////// +CPartForce::~CPartForce(void) { +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartForce::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_name)); + persistMgr->transfer(TMEMBER(_pos)); + persistMgr->transfer(TMEMBER(_direction)); + persistMgr->transfer(TMEMBER_INT(_type)); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/particles/PartForce.h b/engines/wintermute/Base/particles/PartForce.h new file mode 100644 index 0000000000..cf5d697a79 --- /dev/null +++ b/engines/wintermute/Base/particles/PartForce.h @@ -0,0 +1,57 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PARTFORCE_H +#define WINTERMUTE_PARTFORCE_H + + +#include "engines/wintermute/Base/BBase.h" +#include "engines/wintermute/Base/BNamedObject.h" +#include "engines/wintermute/math/Vector2.h" + +namespace WinterMute { + +class CPartForce : public CBNamedObject { +public: + enum TForceType { + FORCE_POINT, FORCE_GLOBAL + }; + + CPartForce(CBGame *inGame); + virtual ~CPartForce(void); + + Vector2 _pos; + Vector2 _direction; + TForceType _type; + + ERRORCODE persist(CBPersistMgr *PersistMgr); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/Base/particles/PartParticle.cpp b/engines/wintermute/Base/particles/PartParticle.cpp new file mode 100644 index 0000000000..10a8e6f51b --- /dev/null +++ b/engines/wintermute/Base/particles/PartParticle.cpp @@ -0,0 +1,257 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/Base/particles/PartParticle.h" +#include "engines/wintermute/Base/particles/PartEmitter.h" +#include "engines/wintermute/Base/BSprite.h" +#include "engines/wintermute/Base/BGame.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/PlatformSDL.h" +#include "common/str.h" +#include + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CPartParticle::CPartParticle(CBGame *inGame) : CBBase(inGame) { + _pos = Vector2(0.0f, 0.0f); + _posZ = 0.0f; + _velocity = Vector2(0.0f, 0.0f); + _scale = 100.0f; + _sprite = NULL; + _creationTime = 0; + _lifeTime = 0; + _isDead = true; + CBPlatform::setRectEmpty(&_border); + + _state = PARTICLE_NORMAL; + _fadeStart = 0; + _fadeTime = 0; + _currentAlpha = 255; + + _alpha1 = _alpha2 = 255; + + _rotation = 0.0f; + _angVelocity = 0.0f; + + _growthRate = 0.0f; + _exponentialGrowth = false; +} + + +////////////////////////////////////////////////////////////////////////// +CPartParticle::~CPartParticle(void) { + delete _sprite; + _sprite = NULL; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::setSprite(const char *filename) { + if (_sprite && _sprite->_filename && scumm_stricmp(filename, _sprite->_filename) == 0) { + _sprite->reset(); + return STATUS_OK; + } + + delete _sprite; + _sprite = NULL; + + CSysClassRegistry::getInstance()->_disabled = true; + _sprite = new CBSprite(Game, Game); + if (_sprite && DID_SUCCEED(_sprite->loadFile(filename))) { + CSysClassRegistry::getInstance()->_disabled = false; + return STATUS_OK; + } else { + delete _sprite; + _sprite = NULL; + CSysClassRegistry::getInstance()->_disabled = false; + return STATUS_FAILED; + } + +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta) { + if (_state == PARTICLE_FADEIN) { + if (currentTime - _fadeStart >= (uint32)_fadeTime) { + _state = PARTICLE_NORMAL; + _currentAlpha = _alpha1; + } else _currentAlpha = (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _alpha1); + + return STATUS_OK; + } else if (_state == PARTICLE_FADEOUT) { + if (currentTime - _fadeStart >= (uint32)_fadeTime) { + _isDead = true; + return STATUS_OK; + } else _currentAlpha = _fadeStartAlpha - (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _fadeStartAlpha); + + return STATUS_OK; + } else { + // time is up + if (_lifeTime > 0) { + if (currentTime - _creationTime >= (uint32)_lifeTime) { + if (emitter->_fadeOutTime > 0) + fadeOut(currentTime, emitter->_fadeOutTime); + else + _isDead = true; + } + } + + // particle hit the border + if (!_isDead && !CBPlatform::isRectEmpty(&_border)) { + Point32 p; + p.x = (int32)_pos.x; + p.y = (int32)_pos.y; + if (!CBPlatform::ptInRect(&_border, p)) + fadeOut(currentTime, emitter->_fadeOutTime); + } + if (_state != PARTICLE_NORMAL) return STATUS_OK; + + // update alpha + if (_lifeTime > 0) { + int age = (int)(currentTime - _creationTime); + int alphaDelta = (int)(_alpha2 - _alpha1); + + _currentAlpha = _alpha1 + (int)(((float)alphaDelta / (float)_lifeTime * (float)age)); + } + + // update position + float elapsedTime = (float)timerDelta / 1000.f; + + for (int i = 0; i < emitter->_forces.getSize(); i++) { + CPartForce *force = emitter->_forces[i]; + switch (force->_type) { + case CPartForce::FORCE_GLOBAL: + _velocity += force->_direction * elapsedTime; + break; + + case CPartForce::FORCE_POINT: { + Vector2 vecDist = force->_pos - _pos; + float dist = fabs(vecDist.length()); + + dist = 100.0f / dist; + + _velocity += force->_direction * dist * elapsedTime; + } + break; + } + } + _pos += _velocity * elapsedTime; + + // update rotation + _rotation += _angVelocity * elapsedTime; + _rotation = CBUtils::normalizeAngle(_rotation); + + // update scale + if (_exponentialGrowth) + _scale += _scale / 100.0f * _growthRate * elapsedTime; + else + _scale += _growthRate * elapsedTime; + + if (_scale <= 0.0f) + _isDead = true; + + + return STATUS_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::display(CPartEmitter *emitter) { + if (!_sprite) return STATUS_FAILED; + if (_isDead) return STATUS_OK; + + _sprite->GetCurrentFrame(); + return _sprite->display(_pos.x, _pos.y, + NULL, + _scale, _scale, + BYTETORGBA(255, 255, 255, _currentAlpha), + _rotation, + emitter->_blendMode); +} + + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::fadeIn(uint32 currentTime, int fadeTime) { + _currentAlpha = 0; + _fadeStart = currentTime; + _fadeTime = fadeTime; + _state = PARTICLE_FADEIN; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::fadeOut(uint32 currentTime, int fadeTime) { + //_currentAlpha = 255; + _fadeStartAlpha = _currentAlpha; + _fadeStart = currentTime; + _fadeTime = fadeTime; + _state = PARTICLE_FADEOUT; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +ERRORCODE CPartParticle::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_alpha1)); + persistMgr->transfer(TMEMBER(_alpha2)); + persistMgr->transfer(TMEMBER(_border)); + persistMgr->transfer(TMEMBER(_pos)); + persistMgr->transfer(TMEMBER(_posZ)); + persistMgr->transfer(TMEMBER(_velocity)); + persistMgr->transfer(TMEMBER(_scale)); + persistMgr->transfer(TMEMBER(_creationTime)); + persistMgr->transfer(TMEMBER(_lifeTime)); + persistMgr->transfer(TMEMBER(_isDead)); + persistMgr->transfer(TMEMBER_INT(_state)); + persistMgr->transfer(TMEMBER(_fadeStart)); + persistMgr->transfer(TMEMBER(_fadeTime)); + persistMgr->transfer(TMEMBER(_currentAlpha)); + persistMgr->transfer(TMEMBER(_angVelocity)); + persistMgr->transfer(TMEMBER(_rotation)); + persistMgr->transfer(TMEMBER(_growthRate)); + persistMgr->transfer(TMEMBER(_exponentialGrowth)); + persistMgr->transfer(TMEMBER(_fadeStartAlpha)); + + if (persistMgr->_saving) { + persistMgr->transfer(TMEMBER(_sprite->_filename)); + } else { + char *filename; + persistMgr->transfer(TMEMBER(filename)); + CSysClassRegistry::getInstance()->_disabled = true; + setSprite(filename); + CSysClassRegistry::getInstance()->_disabled = false; + delete[] filename; + filename = NULL; + } + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/Base/particles/PartParticle.h b/engines/wintermute/Base/particles/PartParticle.h new file mode 100644 index 0000000000..aed559d337 --- /dev/null +++ b/engines/wintermute/Base/particles/PartParticle.h @@ -0,0 +1,90 @@ +/* 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. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PARTPARTICLE_H +#define WINTERMUTE_PARTPARTICLE_H + + +#include "engines/wintermute/Base/BBase.h" +#include "engines/wintermute/Math/Rect32.h" +#include "engines/wintermute/math/Vector2.h" + +namespace WinterMute { + +class CPartEmitter; +class CBSprite; +class CBPersistMgr; + +class CPartParticle : public CBBase { +public: + enum TParticleState { + PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT + }; + + CPartParticle(CBGame *inGame); + virtual ~CPartParticle(void); + + float _growthRate; + bool _exponentialGrowth; + + float _rotation; + float _angVelocity; + + int _alpha1; + int _alpha2; + + Rect32 _border; + Vector2 _pos; + float _posZ; + Vector2 _velocity; + float _scale; + CBSprite *_sprite; + uint32 _creationTime; + int _lifeTime; + bool _isDead; + TParticleState _state; + + ERRORCODE update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta); + ERRORCODE display(CPartEmitter *emitter); + + ERRORCODE setSprite(const char *filename); + + ERRORCODE fadeIn(uint32 currentTime, int fadeTime); + ERRORCODE fadeOut(uint32 currentTime, int fadeTime); + + ERRORCODE persist(CBPersistMgr *PersistMgr); +private: + uint32 _fadeStart; + int _fadeTime; + int _currentAlpha; + int _fadeStartAlpha; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/UI/UIButton.cpp b/engines/wintermute/UI/UIButton.cpp index 65a643b9d3..85932ca603 100644 --- a/engines/wintermute/UI/UIButton.cpp +++ b/engines/wintermute/UI/UIButton.cpp @@ -33,8 +33,8 @@ #include "engines/wintermute/UI/UITiledImage.h" #include "engines/wintermute/Base/BParser.h" #include "engines/wintermute/Base/BActiveRect.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BStringTable.h" #include "engines/wintermute/Base/BSprite.h" #include "engines/wintermute/Base/BFileManager.h" diff --git a/engines/wintermute/UI/UIEdit.cpp b/engines/wintermute/UI/UIEdit.cpp index 778e084ab9..b47885b4dc 100644 --- a/engines/wintermute/UI/UIEdit.cpp +++ b/engines/wintermute/UI/UIEdit.cpp @@ -32,8 +32,8 @@ #include "engines/wintermute/utils/StringUtil.h" #include "engines/wintermute/Base/BActiveRect.h" #include "engines/wintermute/Base/BFileManager.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" #include "engines/wintermute/Base/BKeyboardState.h" #include "engines/wintermute/Base/BDynBuffer.h" #include "engines/wintermute/Base/BParser.h" diff --git a/engines/wintermute/UI/UIObject.cpp b/engines/wintermute/UI/UIObject.cpp index 668d4eb234..6c33bd9509 100644 --- a/engines/wintermute/UI/UIObject.cpp +++ b/engines/wintermute/UI/UIObject.cpp @@ -34,7 +34,7 @@ #include "engines/wintermute/PlatformSDL.h" #include "engines/wintermute/Base/scriptables/ScValue.h" #include "engines/wintermute/Base/scriptables/ScStack.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFontStorage.h" namespace WinterMute { diff --git a/engines/wintermute/UI/UIText.cpp b/engines/wintermute/UI/UIText.cpp index 44fb695687..ba8191c204 100644 --- a/engines/wintermute/UI/UIText.cpp +++ b/engines/wintermute/UI/UIText.cpp @@ -33,8 +33,8 @@ #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BParser.h" #include "engines/wintermute/Base/scriptables/ScValue.h" -#include "engines/wintermute/Base/BFont.h" -#include "engines/wintermute/Base/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" #include "engines/wintermute/Base/BStringTable.h" #include "engines/wintermute/Base/scriptables/ScScript.h" #include "engines/wintermute/Base/scriptables/ScStack.h" diff --git a/engines/wintermute/UI/UIWindow.cpp b/engines/wintermute/UI/UIWindow.cpp index de17966ac5..f16e3afba1 100644 --- a/engines/wintermute/UI/UIWindow.cpp +++ b/engines/wintermute/UI/UIWindow.cpp @@ -39,8 +39,8 @@ #include "engines/wintermute/UI/UIText.h" #include "engines/wintermute/UI/UITiledImage.h" #include "engines/wintermute/Base/BViewport.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFont.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFont.h" #include "engines/wintermute/Base/BStringTable.h" #include "engines/wintermute/Base/scriptables/ScScript.h" #include "engines/wintermute/Base/scriptables/ScStack.h" diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 8dbdd94b0a..a185f08e13 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -43,6 +43,13 @@ MODULE_OBJS := \ Base/file/BFile.o \ Base/file/BSaveThumbFile.o \ Base/file/BPkgFile.o \ + Base/font/BFontBitmap.o \ + Base/font/BFontTT.o \ + Base/font/BFont.o \ + Base/font/BFontStorage.o \ + Base/particles/PartParticle.o \ + Base/particles/PartEmitter.o \ + Base/particles/PartForce.o \ Base/BActiveRect.o \ Base/BBase.o \ Base/BDebugger.o \ @@ -51,10 +58,6 @@ MODULE_OBJS := \ Base/BFileEntry.o \ Base/BFileManager.o \ Base/BGame.o \ - Base/BFont.o \ - Base/BFontBitmap.o \ - Base/BFontStorage.o \ - Base/BFontTT.o \ Base/BFrame.o \ Base/BImage.o \ Base/BKeyboardState.o \ @@ -84,9 +87,6 @@ MODULE_OBJS := \ Base/BSurfaceStorage.o \ Base/BTransitionMgr.o \ Base/BViewport.o \ - Base/PartParticle.o \ - Base/PartEmitter.o \ - Base/PartForce.o \ detection.o \ graphics/transparentSurface.o \ graphics/tga.o \ diff --git a/engines/wintermute/persistent.cpp b/engines/wintermute/persistent.cpp index 8d451aad7b..b753b58d26 100644 --- a/engines/wintermute/persistent.cpp +++ b/engines/wintermute/persistent.cpp @@ -53,9 +53,9 @@ #include "engines/wintermute/Ad/AdTalkNode.h" #include "engines/wintermute/Ad/AdWaypointGroup.h" #include "engines/wintermute/Base/BFader.h" -#include "engines/wintermute/Base/BFontBitmap.h" -#include "engines/wintermute/Base/BFontStorage.h" -#include "engines/wintermute/Base/BFontTT.h" +#include "engines/wintermute/Base/font/BFontBitmap.h" +#include "engines/wintermute/Base/font/BFontStorage.h" +#include "engines/wintermute/Base/font/BFontTT.h" #include "engines/wintermute/Base/BFrame.h" #include "engines/wintermute/Base/BGame.h" #include "engines/wintermute/Base/BKeyboardState.h" -- cgit v1.2.3