scummvm/engines/wintermute/utils.cpp
2012-06-02 13:01:36 +02:00

343 lines
9.6 KiB
C++

/* 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 "dcgf.h"
#include "utils.h"
#include "PlatformSDL.h"
#include "wintypes.h"
#include "PathUtil.h"
#include "BGame.h"
#include "common/str.h"
#include "common/textconsole.h"
namespace WinterMute {
//////////////////////////////////////////////////////////////////////
static inline unsigned Sqr(int x) {
return (x * x);
}
//////////////////////////////////////////////////////////////////////////////////
void CBUtils::Clip(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect) {
// If it's partly off the right side of the screen
if (*DestX + (SrcRect->right - SrcRect->left) > DestRect->right)
SrcRect->right -= *DestX + (SrcRect->right - SrcRect->left) - DestRect->right;
if (SrcRect->right < 0) SrcRect->right = 0;
// Partly off the left side of the screen
if (*DestX < DestRect->left) {
SrcRect->left += DestRect->left - *DestX;
*DestX = DestRect->left;
}
// Partly off the top of the screen
if (*DestY < DestRect->top) {
SrcRect->top += DestRect->top - *DestY;
*DestY = DestRect->top;
}
// If it's partly off the bottom side of the screen
if (*DestY + (SrcRect->bottom - SrcRect->top) > DestRect->bottom)
SrcRect->bottom -= ((SrcRect->bottom - SrcRect->top) + *DestY) - DestRect->bottom;
if (SrcRect->bottom < 0) SrcRect->bottom = 0;
return;
}
//////////////////////////////////////////////////////////////////////////////////
// Swap - swaps two integers
//////////////////////////////////////////////////////////////////////////////////
void CBUtils::Swap(int *a, int *b) {
int Temp = *a;
*a = *b;
*b = Temp;
}
//////////////////////////////////////////////////////////////////////////
bool CBUtils::StrBeginsI(const char *String, const char *Fragment) {
return (scumm_strnicmp(String, Fragment, strlen(Fragment)) == 0);
}
//////////////////////////////////////////////////////////////////////////
float CBUtils::NormalizeAngle(float Angle) {
while (Angle > 360) Angle -= 360;
while (Angle < 0) Angle += 360;
return Angle;
}
////////////////////////////////////////////////////////////////////////////////
void CBUtils::CreatePath(const char *Path, bool PathOnly) {
AnsiString path;
if (!PathOnly) path = PathUtil::GetDirectoryName(Path);
else path = Path;
// try {
warning("CBUtils::CreatePath - not implemented: %s", Path);
// boost::filesystem::create_directories(path);
// } catch (...) {
return;
// }
}
//////////////////////////////////////////////////////////////////////////
void CBUtils::DebugMessage(HWND hWnd, const char *Text) {
//MessageBox(hWnd, Text, "WME", MB_OK|MB_ICONINFORMATION);
}
//////////////////////////////////////////////////////////////////////////
char *CBUtils::SetString(char **String, const char *Value) {
delete[] *String;
*String = new char[strlen(Value) + 1];
if (*String) strcpy(*String, Value);
return *String;
}
//////////////////////////////////////////////////////////////////////////
int CBUtils::StrNumEntries(const char *Str, const char Delim) {
int NumEntries = 1;
for (uint32 i = 0; i < strlen(Str); i++) {
if (Str[i] == Delim) NumEntries++;
}
return NumEntries;
}
//////////////////////////////////////////////////////////////////////////
char *CBUtils::StrEntry(int Entry, const char *Str, const char Delim) {
int NumEntries = 0;
const char *Start = NULL;
int Len = 0;
for (uint32 i = 0; i <= strlen(Str); i++) {
if (NumEntries == Entry) {
if (!Start) Start = Str + i;
else Len++;
}
if (Str[i] == Delim || Str[i] == '\0') {
NumEntries++;
if (Start) {
char *Ret = new char[Len + 1];
memset(Ret, 0, Len + 1);
strncpy(Ret, Start, Len);
return Ret;
}
}
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
int CBUtils::RandomInt(int From, int To) {
if (To < From) {
int i = To;
To = From;
From = i;
}
return (rand() % (To - From + 1)) + From;
}
//////////////////////////////////////////////////////////////////////////
float CBUtils::RandomFloat(float From, float To) {
float RandNum = (float)rand() / (float)RAND_MAX;
return From + (To - From) * RandNum;
}
//////////////////////////////////////////////////////////////////////////
float CBUtils::RandomAngle(float From, float To) {
while (To < From) {
To += 360;
}
return NormalizeAngle(RandomFloat(From, To));
}
//////////////////////////////////////////////////////////////////////////
bool CBUtils::MatchesPattern(const char *Pattern, const char *String) {
char stringc, patternc;
for (;; ++String) {
stringc = toupper(*String);
patternc = toupper(*Pattern++);
switch (patternc) {
case 0:
return (stringc == 0);
case '?':
if (stringc == 0) return false;
break;
case '*':
if (!*Pattern) return true;
if (*Pattern == '.') {
char *dot;
if (Pattern[1] == '*' && Pattern[2] == 0) return true;
dot = (char *)strchr(String, '.');
if (Pattern[1] == 0) return (dot == NULL || dot[1] == 0);
if (dot != NULL) {
String = dot;
if (strpbrk(Pattern, "*?[") == NULL && strchr(String + 1, '.') == NULL)
return(scumm_stricmp(Pattern + 1, String + 1) == 0);
}
}
while (*String)
if (CBUtils::MatchesPattern(Pattern, String++))
return true;
return false;
default:
if (patternc != stringc)
if (patternc == '.' && stringc == 0)
return(CBUtils::MatchesPattern(Pattern, String));
else
return false;
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
char *CBUtils::GetPath(const char *Filename) {
AnsiString path = PathUtil::GetDirectoryName(Filename);
//path = boost::filesystem::syste_complete(path).string();
warning("CBUtils::GetPath: (%s), not implemented", Filename);
char *ret = new char[path.size() + 1];
strcpy(ret, path.c_str());
return ret;
}
//////////////////////////////////////////////////////////////////////////
char *CBUtils::GetFilename(const char *Filename) {
AnsiString path = PathUtil::GetFileName(Filename);
char *ret = new char[path.size() + 1];
strcpy(ret, path.c_str());
return ret;
}
//////////////////////////////////////////////////////////////////////////
void CBUtils::RGBtoHSL(uint32 RGBColor, byte *OutH, byte *OutS, byte *OutL) {
float var_R = (D3DCOLGetR(RGBColor) / 255.0f);
float var_G = (D3DCOLGetG(RGBColor) / 255.0f);
float var_B = (D3DCOLGetB(RGBColor) / 255.0f);
//Min. value of RGB
float var_Min = MIN(var_R, var_G);
var_Min = MIN(var_Min, var_B);
//Max. value of RGB
float var_Max = MAX(var_R, var_G);
var_Max = MAX(var_Max, var_B);
//Delta RGB value
float del_Max = var_Max - var_Min;
float H, S, L;
L = (var_Max + var_Min) / 2.0f;
//This is a gray, no chroma...
if (del_Max == 0) {
H = 0;
S = 0;
}
//Chromatic data...
else {
if (L < 0.5f) S = del_Max / (var_Max + var_Min);
else S = del_Max / (2.0f - var_Max - var_Min);
float del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
float del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
float del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
if (var_R == var_Max) H = del_B - del_G;
else if (var_G == var_Max) H = (1.0f / 3.0f) + del_R - del_B;
else if (var_B == var_Max) H = (2.0f / 3.0f) + del_G - del_R;
if (H < 0) H += 1;
if (H > 1) H -= 1;
}
*OutH = (byte)(H * 255);
*OutS = (byte)(S * 255);
*OutL = (byte)(L * 255);
}
//////////////////////////////////////////////////////////////////////////
uint32 CBUtils::HSLtoRGB(byte InH, byte InS, byte InL) {
float H = InH / 255.0f;
float S = InS / 255.0f;
float L = InL / 255.0f;
byte R, G, B;
if (S == 0) {
R = (byte)(L * 255);
G = (byte)(L * 255);
B = (byte)(L * 255);
} else {
float var_1, var_2;
if (L < 0.5) var_2 = L * (1.0 + S);
else var_2 = (L + S) - (S * L);
var_1 = 2.0f * L - var_2;
R = (byte)(255 * Hue2RGB(var_1, var_2, H + (1.0f / 3.0f)));
G = (byte)(255 * Hue2RGB(var_1, var_2, H));
B = (byte)(255 * Hue2RGB(var_1, var_2, H - (1.0f / 3.0f)));
}
return DRGBA(255, R, G, B);
}
//////////////////////////////////////////////////////////////////////////
float CBUtils::Hue2RGB(float v1, float v2, float vH) {
if (vH < 0.0f) vH += 1.0f;
if (vH > 1.0f) vH -= 1.0f;
if ((6.0f * vH) < 1.0f) return (v1 + (v2 - v1) * 6.0f * vH);
if ((2.0f * vH) < 1.0f) return (v2);
if ((3.0f * vH) < 2.0f) return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
return (v1);
}
} // end of namespace WinterMute