Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,277 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_2_PASS_SCALE_H
#define QDENGINE_QDCORE_UTIL_2_PASS_SCALE_H
#include "qdengine/qdcore/util/Filters.h"
#define TRACE(a)
#define ASSERT(a)
namespace QDEngine {
namespace scl {
typedef struct {
double *weights; // Normalized weights of neighboring pixels
int left, right; // Bounds of source pixels window
} ContributionType; // Contirbution information for a single pixel
typedef struct {
ContributionType *contribRow; // Row (or column) of contribution weights
uint32 windowSize, // Filter window size (of affecting source pixels)
lineLength; // Length of line (no. or rows / cols)
} LineContribType; // Contribution information for an entire line (row or column)
template <class FilterClass>
class C2PassScale {
public:
C2PassScale() : _temp_buffer(65536, 0), _weights_buffer(16384, 0.0), _contribution_buffer(500) { }
virtual ~C2PassScale() { }
uint32 *scale(uint32 *pOrigImage, uint32 uOrigWidth, uint32 uOrigHeight, uint32 *pDstImage, uint32 uNewWidth, uint32 uNewHeight);
private:
Std::vector<uint32> _temp_buffer;
Std::vector<double> _weights_buffer;
Std::vector<ContributionType> _contribution_buffer;
LineContribType *allocContributions(uint32 uLineLength, uint32 uWindowSize);
LineContribType *calcContributions(uint32 uLineSize, uint32 uSrcSize, double dScale);
void scaleRow(uint32 *pSrc, uint32 uSrcWidth, uint32 *pRes, uint32 uResWidth, uint32 uRow, LineContribType *Contrib);
void horizScale(uint32 *pSrc, uint32 uSrcWidth, uint32 uSrcHeight, uint32 *pDst, uint32 uResWidth, uint32 uResHeight);
void scaleCol(uint32 *pSrc, uint32 uSrcWidth, uint32 *pRes, uint32 uResWidth, uint32 uResHeight, uint32 uCol, LineContribType *Contrib);
void vertScale(uint32 *pSrc, uint32 uSrcWidth, uint32 uSrcHeight, uint32 *pDst, uint32 uResWidth, uint32 uResHeight);
static inline byte make_r(uint32 col) {
return reinterpret_cast<byte *>(&col)[2];
}
static inline byte make_g(uint32 col) {
return reinterpret_cast<byte *>(&col)[1];
}
static inline byte make_b(uint32 col) {
return reinterpret_cast<byte *>(&col)[0];
}
static inline byte make_a(uint32 col) {
return reinterpret_cast<byte *>(&col)[3];
}
static inline uint32 make_rgba(byte r, byte g, byte b, byte a) {
return (r << 16) | (g << 8) | (b << 0) | (a << 24);
}
};
template<class FilterClass>
LineContribType *C2PassScale<FilterClass>::allocContributions(uint32 uLineLength, uint32 uWindowSize) {
static LineContribType line_ct;
line_ct.windowSize = uWindowSize;
line_ct.lineLength = uLineLength;
if (_contribution_buffer.size() < uLineLength)
_contribution_buffer.resize(uLineLength);
line_ct.contribRow = &*_contribution_buffer.begin();
if (_weights_buffer.size() < uLineLength * uWindowSize)
_weights_buffer.resize(uLineLength * uWindowSize);
double *p = &*_weights_buffer.begin();
for (uint32 u = 0; u < uLineLength; u++) {
line_ct.contribRow[u].weights = p;
p += uWindowSize;
}
return &line_ct;
}
template <class FilterClass>
LineContribType *C2PassScale<FilterClass>::calcContributions(uint32 uLineSize, uint32 uSrcSize, double dScale) {
FilterClass curFilter;
double dWidth;
double dFScale = 1.0;
double dFilterWidth = curFilter.getWidth();
if (dScale < 1.0) { // Minification
dWidth = dFilterWidth / dScale;
dFScale = dScale;
} else { // Magnification
dWidth = dFilterWidth;
}
// Window size is the number of sampled pixels
int iWindowSize = 2 * (int)ceil(dWidth) + 1;
// Allocate a new line contributions strucutre
LineContribType *res = allocContributions(uLineSize, iWindowSize);
for (uint32 u = 0; u < uLineSize; u++) {
// Scan through line of contributions
double dCenter = (double)u / dScale; // Reverse mapping
// Find the significant edge points that affect the pixel
int iLeft = MAX(0, (int)floor(dCenter - dWidth));
int iRight = MIN((int)ceil(dCenter + dWidth), int(uSrcSize) - 1);
// Cut edge points to fit in filter window in case of spill-off
if (iRight - iLeft + 1 > iWindowSize) {
if (iLeft < (int(uSrcSize) - 1 / 2)) {
iLeft++;
} else {
iRight--;
}
}
res->contribRow[u].left = iLeft;
res->contribRow[u].right = iRight;
double dTotalWeight = 0.0; // Zero sum of weights
for (int iSrc = iLeft; iSrc <= iRight; iSrc++) {
// Calculate weights
dTotalWeight += (res->contribRow[u].weights[iSrc - iLeft] = dFScale * curFilter.filter(dFScale * (dCenter - (double)iSrc)));
}
ASSERT(dTotalWeight >= 0.0); // An error in the filter function can cause this
if (dTotalWeight > 0.0) {
// Normalize weight of neighbouring points
for (int iSrc = iLeft; iSrc <= iRight; iSrc++) {
// Normalize point
res->contribRow[u].weights[iSrc - iLeft] /= dTotalWeight;
}
}
}
return res;
}
template <class FilterClass>
void C2PassScale<FilterClass>::scaleRow(uint32 *pSrc, uint32 uSrcWidth, uint32 *pRes, uint32 uResWidth, uint32 uRow, LineContribType *contrib) {
uint32 *pSrcRow = &(pSrc[uRow * uSrcWidth]);
uint32 *pDstRow = &(pRes[uRow * uResWidth]);
for (uint32 x = 0; x < uResWidth; x++) {
// Loop through row
double dr = 0.0;
double dg = 0.0;
double db = 0.0;
double da = 0.0;
int iLeft = contrib->contribRow[x].left; // Retrieve left boundries
int iRight = contrib->contribRow[x].right; // Retrieve right boundries
for (int i = iLeft; i <= iRight; i++) {
// Scan between boundries
// Accumulate weighted effect of each neighboring pixel
dr += contrib->contribRow[x].weights[i - iLeft] * (double)(make_r(pSrcRow[i]));
dg += contrib->contribRow[x].weights[i - iLeft] * (double)(make_g(pSrcRow[i]));
db += contrib->contribRow[x].weights[i - iLeft] * (double)(make_b(pSrcRow[i]));
da += contrib->contribRow[x].weights[i - iLeft] * (double)(make_a(pSrcRow[i]));
}
uint32 r = round(dr);
uint32 g = round(dg);
uint32 b = round(db);
uint32 a = round(da);
pDstRow[x] = make_rgba(r, g, b, a); // Place result in destination pixel
}
}
template <class FilterClass>
void C2PassScale<FilterClass>::horizScale(uint32 *pSrc, uint32 uSrcWidth, uint32 uSrcHeight, uint32 *pDst, uint32 uResWidth, uint32 uResHeight) {
TRACE("Performing horizontal scaling...\n");
if (uResWidth == uSrcWidth) {
// No scaling required, just copy
memcpy(pDst, pSrc, sizeof(uint32) * uSrcHeight * uSrcWidth);
return;
}
// Allocate and calculate the contributions
LineContribType *contrib = calcContributions(uResWidth, uSrcWidth, double(uResWidth) / double(uSrcWidth));
for (uint32 u = 0; u < uResHeight; u++)
scaleRow(pSrc, uSrcWidth, pDst, uResWidth, u, contrib); // Scale each row
}
template <class FilterClass>
void C2PassScale<FilterClass>::scaleCol(uint32 *pSrc, uint32 uSrcWidth, uint32 *pRes, uint32 uResWidth, uint32 uResHeight, uint32 uCol, LineContribType *contrib) {
for (uint32 y = 0; y < uResHeight; y++) {
// Loop through column
double dr = 0.0;
double dg = 0.0;
double db = 0.0;
double da = 0.0;
int iLeft = contrib->contribRow[y].left; // Retrieve left boundries
int iRight = contrib->contribRow[y].right; // Retrieve right boundries
for (int i = iLeft; i <= iRight; i++) {
// Scan between boundries
// Accumulate weighted effect of each neighboring pixel
uint32 pCurSrc = pSrc[i * uSrcWidth + uCol];
dr += contrib->contribRow[y].weights[i - iLeft] * (double)(make_r(pCurSrc));
dg += contrib->contribRow[y].weights[i - iLeft] * (double)(make_g(pCurSrc));
db += contrib->contribRow[y].weights[i - iLeft] * (double)(make_b(pCurSrc));
da += contrib->contribRow[y].weights[i - iLeft] * (double)(make_a(pCurSrc));
}
uint32 r = round(dr);
uint32 g = round(dg);
uint32 b = round(db);
uint32 a = round(da);
pRes[y * uResWidth + uCol] = make_rgba(r, g, b, a); // Place result in destination pixel
}
}
template <class FilterClass>
void C2PassScale<FilterClass>::vertScale(uint32 *pSrc, uint32 uSrcWidth, uint32 uSrcHeight, uint32 *pDst, uint32 uResWidth, uint32 uResHeight) {
TRACE("Performing vertical scaling...");
if (uSrcHeight == uResHeight) {
// No scaling required, just copy
memcpy(pDst, pSrc, sizeof(uint32) * uSrcHeight * uSrcWidth);
return;
}
// Allocate and calculate the contributions
LineContribType *Contrib = calcContributions(uResHeight, uSrcHeight, double(uResHeight) / double(uSrcHeight));
for (uint32 u = 0; u < uResWidth; u++)
scaleCol(pSrc, uSrcWidth, pDst, uResWidth, uResHeight, u, Contrib); // Scale each column
}
template <class FilterClass>
uint32 *C2PassScale<FilterClass>::scale(uint32 *pOrigImage, uint32 uOrigWidth, uint32 uOrigHeight, uint32 *pDstImage, uint32 uNewWidth, uint32 uNewHeight) {
if (_temp_buffer.size() < uNewWidth * uOrigHeight)
_temp_buffer.resize(uNewWidth * uOrigHeight);
uint32 *pTemp = reinterpret_cast<uint32 *>(&*_temp_buffer.begin());
horizScale(pOrigImage, uOrigWidth, uOrigHeight, pTemp, uNewWidth, uOrigHeight);
// Scale temporary image vertically into result image
vertScale(pTemp, uNewWidth, uOrigHeight, pDstImage, uNewWidth, uNewHeight);
return pDstImage;
}
} // namespace scl
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_2_PASS_SCALE_H

View File

@@ -0,0 +1,532 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//K-D Lab / Balmer
#pragma once
#include "common/multimap.h"
///////////////////////////AIAStar/////////////////////
//AIAStar::FindPath поиск пути из точки from
//в точку IsEndPoint.
//Боле-менее оптимизированный на случай квадратной сетки
/*
class Heuristic
{
float getH(int x,int y);//Предполагаемые затраты на продвижение из pos1 к окончанию
float getG(int x1,int y1,int x2,int y2);//Затраты на продвижение из pos1 в pos2
bool IsEndPoint(int x,int y);//Рекурсия должна окончиться здесь
//то есть класс AIAStar позволяет задавать несколько точек окончания поиска пути
};
*/
namespace QDEngine {
template<class Heuristic, class TypeH = float>
class AIAStar {
public:
typedef Common::MultiMap<TypeH, Vect2i> type_point_map;
struct OnePoint {
TypeH g;//Затраты на продвижение до этой точки
TypeH h;//Предполагаемые затраты на продвижение до финиша
int used;
OnePoint *parent;
bool is_open;
inline TypeH f() {
return g + h;
}
};
protected:
int _dx, _dy;
OnePoint *_chart;
type_point_map _open_map;
int _is_used_num;//Если _is_used_num==used, то ячейка используется
int _num_point_examine;//количество посещённых ячеек
int _num_find_erase;//Сколько суммарно искали ячейки для удаления
Heuristic *_heuristic;
public:
AIAStar();
~AIAStar();
void init(int dx, int dy);
bool findPath(Vect2i from, Heuristic *h, Std::vector<Vect2i> &path, int directions_count = 8);
void getStatistic(int *num_point_examine, int *num_find_erase);
//Debug
OnePoint *getInternalBuffer() {
return _chart;
};
int getUsedNum() {
return _is_used_num;
}
protected:
void clear();
inline Vect2i posBy(OnePoint *p) {
int offset = p - _chart;
Vect2i pos;
pos.x = offset % _dx;
pos.y = offset / _dx;
return pos;
}
};
template<class Heuristic, class TypeH>
AIAStar<Heuristic, TypeH>::AIAStar() {
_chart = NULL;
_heuristic = NULL;
_num_find_erase = 0;
_dx = _dy = 0;
_is_used_num = 0;
_num_point_examine = 0;
}
template<class Heuristic, class TypeH>
void AIAStar<Heuristic, TypeH>::init(int dx_, int dy_) {
_dx = dx_;
_dy = dy_;
int size = _dx * _dy;
_chart = new OnePoint[size];
clear();
}
template<class Heuristic, class TypeH>
void AIAStar<Heuristic, TypeH>::clear() {
int size = _dx * _dy;
_is_used_num = 0;
for (int i = 0; i < size; i++)
_chart[i].used = 0;
}
template<class Heuristic, class TypeH>
AIAStar<Heuristic, TypeH>::~AIAStar() {
delete[] _chart;
}
template<class Heuristic, class TypeH>
bool AIAStar<Heuristic, TypeH>::findPath(Vect2i from, Heuristic *hr, Std::vector<Vect2i> &path, int directions_count) {
_num_point_examine = 0;
_num_find_erase = 0;
_is_used_num++;
_open_map.clear();
path.clear();
if (_is_used_num == 0)
clear();//Для того, чтобы вызвалась эта строчка, необходимо гиганское время
assert(from.x >= 0 && from.x < _dx && from.y >= 0 && from.y < _dy);
_heuristic = hr;
OnePoint *p = _chart + from.y * _dx + from.x;
p->g = 0;
p->h = _heuristic->getH(from.x, from.y);
p->used = _is_used_num;
p->is_open = true;
p->parent = NULL;
_open_map.insert(typename type_point_map::value_type(p->f(), from));
const int sx[8] = { 0, -1, 0, +1, -1, +1, +1, -1,};
const int sy[8] = {-1, 0, +1, 0, -1, -1, +1, +1 };
// const int sx[size_child]={ 0,-1, 0,+1};
// const int sy[size_child]={-1, 0,+1, 0};
const int size_child = directions_count;
while (!_open_map.empty()) {
typename type_point_map::iterator low = _open_map.begin();
Vect2i pt = (*low).second;
OnePoint *parent = _chart + pt.y * _dx + pt.x;
parent->is_open = false;
_open_map.erase(low);
if (_heuristic->isEndPoint(pt.x, pt.y)) {
//сконструировать путь
Vect2i vp;
while (parent) {
vp = posBy(parent);;
path.push_back(vp);
if (parent->parent) {
Vect2i pp;
pp = posBy(parent->parent);
assert(abs(vp.x - pp.x) <= 1 &&
abs(vp.y - pp.y) <= 1);
}
parent = parent->parent;
}
assert(vp.x == from.x && vp.y == from.y);
Common::reverse(path.begin(), path.end());
return true;
}
//для каждого наследника child узла parent
for (int i = 0; i < size_child; i++) {
Vect2i child = Vect2i(pt.x + sx[i], pt.y + sy[i]);
_num_point_examine++;
if (child.x < 0 || child.y < 0 ||
child.x >= _dx || child.y >= _dy)continue;
p = _chart + child.y * _dx + child.x;
TypeH addg = _heuristic->getG(pt.x, pt.y, child.x, child.y);
TypeH newg = parent->g + addg;
if (p->used == _is_used_num) {
if (!p->is_open)continue;
if (p->g <= newg)continue;
//Удаляем элемент из _open_map
TypeH f = p->f();
typename type_point_map::iterator cur = _open_map.find(p->f());
bool erase = false;
while (cur != _open_map.end()) {
if ((*cur).first != f)break;
if ((*cur).second.x == child.x && (*cur).second.y == child.y) {
_open_map.erase(cur);
erase = true;
break;
}
_num_find_erase++;
cur++;
}
_num_find_erase++;
//assert(erase);
if (!erase)
continue;
}
p->parent = parent;
/*
{
Vect2i pp=posBy(parent);
Vect2i pc=posBy(p);
assert(abs(pc.x-pp.x)<=1 &&
abs(pc.y-pp.y)<=1);
}
*/
p->g = newg;
p->h = _heuristic->getH(child.x, child.y);
_open_map.insert(typename type_point_map::value_type(p->f(), child));
p->is_open = true;
p->used = _is_used_num;
}
}
return false;
}
template<class Heuristic, class TypeH>
void AIAStar<Heuristic, TypeH>::getStatistic(
int *p_num_point_examine, int *p_num_find_erase) {
if (p_num_point_examine)
*p_num_point_examine = _num_point_examine;
if (p_num_find_erase)
*p_num_find_erase = _num_find_erase;
}
///////////////////////AIAStarGraph/////////////
//AIAStarGraph - Так-же поиск пути, но ориентированный на поиск в произвольном графе
/*
class Node
{
typedef ... iterator;
iterator begin();//Работа со списком связанных с этой Node нод.
iterator end();
void* AIAStarPointer;//Используется в AIAStarGraph
};
class Heuristic
{
float getH(Node* pos);//Предполагаемые затраты на продвижение из pos1 к окончанию
float getG(Node* pos1,Node* pos2);//Затраты на продвижение из pos1 в pos2
bool IsEndPoint(Node* pos);//Рекурсия должна окончиться здесь
//то есть класс AIAStar позволяет задавать несколько точек окончания поиска пути
};
*/
template<class Heuristic, class Node, class TypeH = float>
class AIAStarGraph {
public:
struct OnePoint;
typedef Common::MultiMap<TypeH, OnePoint *> type_point_map;
struct OnePoint {
TypeH g;//Затраты на продвижение до этой точки
TypeH h;//Предполагаемые затраты на продвижение до финиша
int used;
OnePoint *parent;
bool is_open;
Node *node;
typename type_point_map::iterator self_it;
inline TypeH f() {
return g + h;
}
};
protected:
Std::vector<OnePoint> _chart;
type_point_map _open_map;
int _is_used_num;//Если _is_used_num==used, то ячейка используется
int _num_point_examine;//количество посещённых ячеек
int _num_find_erase;//Сколько суммарно искали ячейки для удаления
Heuristic *_heuristic;
public:
AIAStarGraph();
~AIAStarGraph();
//Общее количество узлов. Константа, которая не должна меняться,
//пока существует класс, указывающий на неё.
void init(Std::vector<Node> &all_node);
bool findPath(Node *from, Heuristic *h, Std::vector<Node *> &path);
void getStatistic(int *num_point_examine, int *num_find_erase);
//Debug
OnePoint *getInternalBuffer() {
return _chart;
};
int getUsedNum() {
return _is_used_num;
}
protected:
void clear();
inline Node *posBy(OnePoint *p) {
return p->node;
}
};
template<class Heuristic, class Node, class TypeH>
AIAStarGraph<Heuristic, Node, TypeH>::AIAStarGraph() {
_heuristic = NULL;
_is_used_num = 0;
_num_point_examine = 0;
_num_find_erase = 0;
}
template<class Heuristic, class Node, class TypeH>
void AIAStarGraph<Heuristic, Node, TypeH>::init(Std::vector<Node> &all_node) {
int size = all_node.size();
_chart.resize(size);
for (int i = 0; i < size; i++) {
OnePoint *c = &_chart[i];
c->node = &all_node[i];
c->node->AIAStarPointer = (void *)c;
}
clear();
}
template<class Heuristic, class Node, class TypeH>
void AIAStarGraph<Heuristic, Node, TypeH>::clear() {
_is_used_num = 0;
for (auto &it : _chart) {
it.used = 0;
}
}
template<class Heuristic, class Node, class TypeH>
AIAStarGraph<Heuristic, Node, TypeH>::~AIAStarGraph() {
}
template<class Heuristic, class Node, class TypeH>
bool AIAStarGraph<Heuristic, Node, TypeH>::findPath(Node *from, Heuristic *hr, Std::vector<Node *> &path) {
_num_point_examine = 0;
_num_find_erase = 0;
_is_used_num++;
_open_map.clear();
path.clear();
if (_is_used_num == 0)
clear();//Для того, чтобы вызвалась эта строчка, необходимо гиганское время
_heuristic = hr;
OnePoint *p = (OnePoint *)from->AIAStarPointer;
Node *from_node = p->node;
p->g = 0;
p->h = _heuristic->getH(p->node);
p->used = _is_used_num;
p->is_open = true;
p->parent = NULL;
p->self_it = _open_map.insert(type_point_map::value_type(p->f(), p));
while (!_open_map.empty()) {
typename type_point_map::iterator low = _open_map.begin();
OnePoint *parent = low->second;
Node *node = parent->node;
parent->is_open = false;
_open_map.erase(low);
if (_heuristic->IsEndPoint(node)) {
//сконструировать путь
Node *np;
while (parent) {
np = PosBy(parent);
assert(parent->used == _is_used_num);
path.push_back(np);
parent = parent->parent;
}
assert(np == from_node);
reverse(path.begin(), path.end());
return true;
}
//для каждого наследника child узла parent
for (auto &it : *node) {
Node *cur_node = *it;
OnePoint *op = (OnePoint *)cur_node->AIAStarPointer;
_num_point_examine++;
TypeH addg = _heuristic->getG(node, cur_node);
TypeH newg = parent->g + addg;
if (op->used == _is_used_num) {
if (!op->is_open)continue;
if (op->g <= newg)continue;
_open_map.erase(op->self_it);
_num_find_erase++;
}
op->parent = parent;
op->g = newg;
op->h = _heuristic->getH(cur_node);
op->self_it = _open_map.insert(type_point_map::value_type(op->f(), op));
op->is_open = true;
op->used = _is_used_num;
}
}
return false;
}
template<class Heuristic, class Node, class TypeH>
void AIAStarGraph<Heuristic, Node, TypeH>::getStatistic(
int *p_num_point_examine, int *p_num_find_erase) {
if (p_num_point_examine)
*p_num_point_examine = _num_point_examine;
if (p_num_find_erase)
*p_num_find_erase = _num_find_erase;
}
///////////////////////AIFindMaxium/////////////
/*
struct Maps
{
//Значение чего нибудь в точке (x,y)
TypeH get(int x,int y);
//Дальнейшие поиски можно прекратить
bool IsOptiumGood(TypeH optium,int x,int y);
};
*/
//Ищет минимальное значение, но не по всей карте
template<class Maps>
Vect2i AIFindMinium(int x, int y,
Maps &maps,
int dx, int dy) {
typename Maps::TypeH optium = maps.get(x, y);
int optiumx = x, optiumy = y;
int maxi = MAX(MAX(x, dx - x), MAX(y, dy - y));
for (int i = 1; i < maxi; i++) {
int curx, cury;
int xmin = MAX(0, x - i), xmax = MIN(dx - 1, x + i);
int ymin = MAX(0, y - i), ymax = MIN(dy - 1, y + i);
//up
cury = y - i;
if (cury >= 0)
for (curx = xmin; curx <= xmax; curx++) {
typename Maps::TypeH o = maps.get(curx, cury);
if (o < optium) {
optium = o;
optiumx = curx;
optiumy = cury;
}
}
//down
cury = y + i;
if (cury < dy)
for (curx = xmin; curx <= xmax; curx++) {
typename Maps::TypeH o = maps.get(curx, cury);
if (o < optium) {
optium = o;
optiumx = curx;
optiumy = cury;
}
}
//left
curx = x - i;
if (curx >= 0)
for (cury = ymin; cury <= ymax; cury++) {
typename Maps::TypeH o = maps.get(curx, cury);
if (o < optium) {
optium = o;
optiumx = curx;
optiumy = cury;
}
}
//right
curx = x + i;
if (curx < dx)
for (cury = ymin; cury <= ymax; cury++) {
typename Maps::TypeH o = maps.get(curx, cury);
if (o < optium) {
optium = o;
optiumx = curx;
optiumy = cury;
}
}
if (maps.IsOptiumGood(optium, optiumx, optiumy))
break;
}
Vect2i p = {optiumx, optiumy};
return p;
}
} // namespace QDEngine

View File

@@ -0,0 +1,74 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "qdengine/qdengine.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/xmath.h"
#include "qdengine/qdcore/qd_camera.h"
#include "qdengine/qdcore/qd_game_object_moving.h"
#include "qdengine/qdcore/util/AIAStar_API.h"
namespace QDEngine {
qdHeuristic::qdHeuristic() : _camera_ptr(NULL), _object_ptr(NULL) {
}
qdHeuristic::~qdHeuristic() {
}
int qdHeuristic::getH(int x, int y) {
x -= _target.x;
y -= _target.y;
if (g_engine->_gameVersion <= 20041201) {
return sqrt(static_cast<float>(x * x + y * y));
} else {
// Достаточно будет эвристики без квадратного корня, который медленный
return static_cast<float>(x * x + y * y);
}
}
int qdHeuristic::getG(int x1, int y1, int x2, int y2) {
if (!_object_ptr->is_walkable(Vect2s(x2, y2)))
return 10000;
// Для диагональных перемещений смотрим еще и перемещения по катетам,
// потому как туда может попасть персонаж из-за погрешностей интерполирования позиции
if ((x1 != x2) && (y1 != y2) &&
(
!_object_ptr->is_walkable(Vect2s(x1, y2)) ||
!_object_ptr->is_walkable(Vect2s(x2, y1))
))
return 10000;
//return abs(x2 - x1) + abs(y2 - y1);
// 14 - приближение корня из 2, умноженного на 10. 10 - единица*10.
if ((x1 != x2) && (y1 != y2))
return 14;
else return 10;
}
void qdHeuristic::init(const Vect3f trg) {
_target_f = trg;
_target = _camera_ptr->get_cell_index(trg.x, trg.y);
}
} // namespace QDEngine

View File

@@ -0,0 +1,66 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_AIASTAR_API_H
#define QDENGINE_QDCORE_UTIL_AIASTAR_API_H
#include "qdengine/qdcore/util/AIAStar.h"
namespace QDEngine {
class qdCamera;
class qdGameObjectMoving;
//! Эвристика для поиска пути.
class qdHeuristic {
public:
qdHeuristic();
~qdHeuristic();
int getH(int x, int y);
int getG(int x1, int y1, int x2, int y2);
bool isEndPoint(int x, int y) {
return (x == _target.x && y == _target.y);
}
void init(const Vect3f trg);
void set_camera(const qdCamera *cam) {
_camera_ptr = cam;
}
void set_object(const qdGameObjectMoving *obj) {
_object_ptr = obj;
}
private:
Vect2i _target;
Vect3f _target_f;
const qdCamera *_camera_ptr;
const qdGameObjectMoving *_object_ptr;
};
typedef AIAStar<qdHeuristic, int> qdAStar;
} // namespace QDEngine
#endif // _AIASTAR_API_H

View File

@@ -0,0 +1,121 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_FILTERS_H
#define QDENGINE_QDCORE_UTIL_FILTERS_H
namespace QDEngine {
namespace scl {
class CGenericFilter {
public:
CGenericFilter(double dWidth) : _dWidth(dWidth) {}
virtual ~CGenericFilter() {}
double getWidth() const {
return _dWidth;
}
void setWidth(double dWidth) {
_dWidth = dWidth;
}
virtual double filter(double dVal) = 0;
protected:
#define FILTER_PI double (3.1415926535897932384626433832795)
#define FILTER_2PI double (2.0 * 3.1415926535897932384626433832795)
#define FILTER_4PI double (4.0 * 3.1415926535897932384626433832795)
double _dWidth;
};
class CBoxFilter : public CGenericFilter {
public:
CBoxFilter(double dWidth = double(0.5)) : CGenericFilter(dWidth) {}
~CBoxFilter() {}
double filter(double dVal) {
return (fabs(dVal) <= _dWidth ? 1.0 : 0.0);
}
};
class CBilinearFilter : public CGenericFilter {
public:
CBilinearFilter(double dWidth = double(1.0)) : CGenericFilter(dWidth) {}
~CBilinearFilter() {}
double filter(double dVal) {
dVal = fabs(dVal);
return (dVal < _dWidth ? _dWidth - dVal : 0.0);
}
};
class CGaussianFilter : public CGenericFilter {
public:
CGaussianFilter(double dWidth = double(3.0)) : CGenericFilter(dWidth) {}
~CGaussianFilter() {}
double filter(double dVal) {
if (fabs(dVal) > _dWidth) {
return 0.0;
}
return exp(-dVal * dVal / 2.0) / sqrt(FILTER_2PI);
}
};
class CHammingFilter : public CGenericFilter {
public:
CHammingFilter(double dWidth = double(0.5)) : CGenericFilter(dWidth) {}
~CHammingFilter() {}
double filter(double dVal) {
if (fabs(dVal) > _dWidth)
return 0.0;
double dWindow = 0.54 + 0.46 * cos(FILTER_2PI * dVal);
double dSinc = (dVal == 0) ? 1.0 : sin(FILTER_PI * dVal) / (FILTER_PI * dVal);
return dWindow * dSinc;
}
};
class CBlackmanFilter : public CGenericFilter {
public:
CBlackmanFilter(double dWidth = double(0.5)) : CGenericFilter(dWidth) {}
~CBlackmanFilter() {}
double filter(double dVal) {
if (fabs(dVal) > _dWidth)
return 0.0;
double dN = 2.0 * _dWidth + 1.0;
return 0.42 + 0.5 * cos(FILTER_2PI * dVal / (dN - 1.0)) + 0.08 * cos(FILTER_4PI * dVal / (dN - 1.0));
}
};
} // namespace scl
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_FILTERS_H

View File

@@ -0,0 +1,178 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_HANDLE_H
#define QDENGINE_QDCORE_UTIL_HANDLE_H
namespace QDEngine {
////////////////////////////////////////////////////////////////////
// Автоматически удаляемый указатель
////////////////////////////////////////////////////////////////////
template<class T>
class PtrHandle {
public:
PtrHandle(T *p = 0) : ptr(p) {}
PtrHandle(PtrHandle &p) : ptr(p.release()) {}
~PtrHandle() {
delete ptr;
}
void set(T *p) {
ptr = p;
}
PtrHandle &operator=(PtrHandle &p) {
if (get() != p.get()) {
delete ptr;
ptr = p.release();
}
return *this;
}
PtrHandle &operator=(T *p) {
if (get() != p)
delete ptr;
set(p);
return *this;
}
T *get() const {
return ptr;
}
T *release() {
T *tmp = ptr;
ptr = 0;
return tmp;
}
T *operator->() const {
return ptr;
}
T &operator*() const {
return *ptr;
}
T *operator()() const {
return ptr;
}
operator T *() const {
return ptr;
}
private:
T *ptr;
};
////////////////////////////////////////////////////////////////////
// Автоматически удаляемый указатель
// с отслеживанием владельцев.
// Обекты должны наследовать ShareHandleBase
////////////////////////////////////////////////////////////////////
template<class T>
class ShareHandle {
public:
ShareHandle(T *p = 0) {
set(p);
}
ShareHandle(const ShareHandle &orig) {
set(orig.ptr);
}
~ShareHandle() {
if (ptr && !ptr->decrRef())
delete ptr;
}
void set(T *p) {
ptr = p;
if (p)
p->addRef();
}
ShareHandle &operator=(const ShareHandle &orig) {
if (ptr && !ptr->decrRef() && ptr != orig.ptr)
delete ptr;
set(orig.ptr);
return *this;
}
ShareHandle &operator=(T *p) {
if (ptr && !ptr->decrRef() && ptr != p)
delete ptr;
set(p);
return *this;
}
T *get() const {
return ptr;
}
T *release() {
T *tmp = ptr;
if (ptr) ptr->decrRef();
ptr = 0;
return tmp;
}
T *operator->() const {
return ptr;
}
T &operator*() const {
return *ptr;
}
T *operator()() const {
return ptr;
}
operator T *() const {
return ptr;
}
private:
T *ptr;
};
class ShareHandleBase {
public:
ShareHandleBase() {
handleCount = 0;
}
ShareHandleBase(const ShareHandleBase &) {
handleCount = 0;
}
~ShareHandleBase() {}
void addRef() {
++handleCount;
}
int decrRef() {
return --handleCount;
}
int numRef() const {
return handleCount;
}
private:
mutable int handleCount;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_HANDLE_H

View File

@@ -0,0 +1,174 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Implementation of pure LZ77 looseless compression.
// Modification of this algorithm was used for NTFS compression.
//
// Implemented by Arkadi Kagan.
//
#include "common/endian.h"
#include "common/util.h"
#include "qdengine/qdcore/util/LZ77.h"
namespace QDEngine {
#define BITS_LEN 4
CLZ77::CLZ77() {
}
CLZ77::~CLZ77() {
}
int32 CLZ77::lzComp(const byte *s1, const byte *s2, int32 maxlen) {
int32 i;
for (i = 0; i < maxlen; i++)
if (s1[i] != s2[i])
return i;
return maxlen;
}
const byte *CLZ77::findLZ(const byte *source, const byte *s, int32 slen, int32 border, int32 mlen, int32 &len) {
int32 maxlen = 0;
int32 limit = slen - (s - source);
const byte *maxp = s - 1;
const byte *p;
len = 0;
for (p = s - 1; p >= source; p--) {
len = lzComp(p, s, limit);
if (len > maxlen) {
maxp = p;
maxlen = len;
}
if (s - p >= border - 1) break;
if (len >= mlen - 1) break;
}
len = MIN(maxlen, mlen - 1);
return maxp;
}
int32 CLZ77::getMaxEncoded(int32 len) {
return len + sizeof(uint32);
}
int32 CLZ77::getMaxDecoded(byte *source) {
return ((uint32 *)source)[0];
}
void CLZ77::encode(byte *target, int32 &tlen, const byte *source, int32 slen) {
int32 len, block;
int32 shift, border;
const byte *s, *p;
byte *t;
byte *flag;
uint16 *ptmp;
((uint32 *)target)[0] = slen; // save source size
target += sizeof(uint32);
tlen = sizeof(uint32);
block = 0; // block - bit in single flag byte
shift = 16; // shift offset to most significant bits
border = 1; // offset can`t be more then border
flag = target; // flag for every 8 entities
tlen++; // byte for first flag
*flag = 0;
s = (const byte *)source;
t = target + 1;
for (s = (const byte *)source; s - source < slen;) {
if (shift > BITS_LEN)
while (s - source >= border) {
if (shift <= BITS_LEN) break;
border = border << 1;
shift--;
}
p = findLZ((const byte *)source, s, slen, border, (1 << shift), len);
if (len <= 2) len = 1;
if (len <= 1) {
*t++ = *s++;
tlen++;
} else {
ptmp = (uint16 *)t;
*ptmp = (uint16)(((s - p - 1) << shift) + len);
*flag |= 1 << block;
t += 2;
tlen += 2;
s += len;
}
if (++block >= 8) {
flag = t++;
*flag = 0;
block = 0;
tlen++;
}
/* if (tlen >= slen)
{
tlen = 0;
return;
}*/
// OnStep();
}
}
int32 CLZ77::decode(byte *target, int32 &tlen, const byte *source, int32 slen) {
uint32 i;
uint32 block, len;
uint32 shift, border;
const byte *s;
byte *t, *p;
const byte *flag;
uint16 tmp;
tlen = READ_LE_UINT32(source);
source += sizeof(uint32); // read/remove target size
slen -= sizeof(uint32);
t = target;
flag = (const byte *)source;
block = 0; // block - bit in single flag byte
shift = 16; // shift offset to most significant bits
border = 1; // offset can`t be more then border
for (s = (const byte *)source + 1; (s < source + slen) && (t - target < tlen);) {
if (shift > BITS_LEN)
while (t - target >= (int)border) {
if (shift <= BITS_LEN) break;
border = border << 1;
shift--;
}
if (flag[0] & (1 << block)) {
tmp = READ_LE_UINT16(s);
len = ((1 << shift) - 1) & tmp;
p = t - (tmp >> shift) - 1;
for (i = 0; i < len; i++)
t[i] = p[i];
t += len;
s += 2;
} else {
*t++ = *s++;
//len = 1;
}
if (++block >= 8) {
flag = s++;
block = 0;
}
// OnStep();
}
return (s - source) + sizeof(uint32);
}
} // namespace QDEngine

View File

@@ -0,0 +1,46 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_LZ77_H
#define QDENGINE_QDCORE_UTIL_LZ77_H
namespace QDEngine {
class CLZ77 {
private:
int32 lzComp(const byte *s1, const byte *s2, int32 maxlen);
const byte *findLZ(const byte *source, const byte *s, int32 slen, int32 border, int32 mlen, int32 &len);
public:
CLZ77();
virtual ~CLZ77();
void encode(byte *target, int32 &tlen, const byte *source, int32 slen);
int32 decode(byte *target, int32 &tlen, const byte *source, int32 slen);
int32 getMaxEncoded(int32 len);
int32 getMaxDecoded(byte *source);
// virtual void OnStep() = 0;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_LZ77_H

View File

@@ -0,0 +1,76 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/util/ResourceDispatcher.h"
namespace QDEngine {
int ResourceUser::IDs;
void ResourceDispatcher::do_start() {
if (_start_log) {
_start_log = false;
_syncro_timer.setTime(1);
for (UserList::iterator i = users.begin(); i != users.end(); ++i)
(*i)->time = _syncro_timer();
}
}
void ResourceDispatcher::reset() {
for (UserList::iterator i = users.begin(); i != users.end(); ++i)
(*i)->time = _syncro_timer();
}
void ResourceDispatcher::quant() {
debugC(9, kDebugQuant, "ResourceDispatcher::quant()");
if (users.empty())
return;
do_start();
_syncro_timer.next_frame();
for (;;) {
time_type t_min = users.front()->time;
ResourceUser *user_min = users.front();
for (UserList::iterator i = users.begin(); i != users.end(); ++i) {
ResourceUser &u = **i;
if (t_min > u.time) {
t_min = u.time;
user_min = &u;
}
}
if (t_min < _syncro_timer.operator()()) {
if (!user_min->quant()) {
debugC(3, kDebugQuant, "ResourceDispatcher::quant() user_min->time = %d", user_min->time);
detach(user_min);
} else
user_min->time += user_min->time_step();
} else
break;
}
}
} // namespace QDEngine

View File

@@ -0,0 +1,152 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_RESOURCE_DISPATCHER_H
#define QDENGINE_QDCORE_UTIL_RESOURCE_DISPATCHER_H
#include "qdengine/qdcore/util/Handle.h"
#include "qdengine/qdcore/util/SynchroTimer.h"
namespace QDEngine {
/////////////////////////////////////////////////////////////////////////////////////////
// General Time Resourcing
/////////////////////////////////////////////////////////////////////////////////////////
class ResourceUser {
int ID;
static int IDs;
public:
ResourceUser(time_type period) {
dtime = period;
time = 0;
ID = ++IDs;
}
virtual ~ResourceUser() {}
virtual int quant() {
return 1;
}
protected:
time_type time;
time_type dtime;
virtual void init_time(time_type time_) {
time = time_ + time_step();
}
virtual time_type time_step() {
return dtime;
}
friend class ResourceDispatcher;
};
class VoidFunctionCallResourceUser : public ResourceUser {
public:
typedef void (*type)();
VoidFunctionCallResourceUser(type func_, time_type dtime_) :
ResourceUser(dtime_), func(func_) {}
virtual ~VoidFunctionCallResourceUser() {}
int quant() {
func();
return 1;
}
protected:
type func;
};
template<class T>
class MemberFunctionCallResourceUser : public ResourceUser {
public:
typedef void (T::*type)();
MemberFunctionCallResourceUser(T &object_, type func_, time_type dtime_) :
ResourceUser(dtime_), object(object_), func(func_) {}
virtual ~MemberFunctionCallResourceUser() {}
int quant() {
(object.*func)();
return 1;
}
protected:
T &object;
type func;
};
/////////////////////////////////////////////////////////////////////////////////////////
// Resource Dispatcher
/////////////////////////////////////////////////////////////////////////////////////////
class ResourceDispatcher {
public:
ResourceDispatcher() : _start_log(false), _max_time_interval(0) { }
void setTimer(int syncro_by_clock, time_type time_per_frame, time_type max_time_interval_) {
_syncro_timer.set(syncro_by_clock, time_per_frame, _max_time_interval = max_time_interval_);
}
void attach(ResourceUser *user) {
PtrHandle<ResourceUser> p(0);
users.push_back(p);
users.back() = user;
user->init_time(_syncro_timer());
}
void attach(void (*func)(), time_type dtime) {
attach(new VoidFunctionCallResourceUser(func, dtime));
}
template<class T>
void attach(T &obj, void (T::*func)(), time_type dtime) {
attach(new MemberFunctionCallResourceUser<T>(obj, func, dtime));
}
void detach(ResourceUser *user) {
PtrHandle<ResourceUser> p(user);
users.remove(p);
p.set(0);
}
void start() {
_start_log = true;
}
void reset();
void skip_time() {
_syncro_timer.skip();
}
void quant();
void set_speed(float speed) {
_syncro_timer.setSpeed(speed);
}
private:
typedef Std::list<PtrHandle<ResourceUser> > UserList;
UserList users;
SyncroTimer _syncro_timer;
time_type _max_time_interval;
bool _start_log;
void do_start();
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_RESOURCE_DISPATCHER_H

View File

@@ -0,0 +1,105 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_SYNCRO_TIMER
#define QDENGINE_QDCORE_UTIL_SYNCRO_TIMER
#include "common/system.h"
typedef uint32 time_type;
namespace QDEngine {
class SyncroTimer {
public:
// Main property
time_type operator()() const {
return round(_time);
}
// Last delta
time_type delta() const {
return _time - _time_prev;
}
SyncroTimer() {
set(1, 15, 100);
_time_prev = _time = 1;
_time_offset = 0;
_time_speed = 1;
}
void set(int syncro_by_clock, time_type time_per_frame, time_type max_time_interval) {
_syncro_by_clock = syncro_by_clock;
_time_per_frame = time_per_frame;
_max_time_interval = max_time_interval;
}
SyncroTimer &adjust() {
_time_prev = _time;
if (_syncro_by_clock) {
float t = float(g_system->getMillis());
float dt = (t - _time - _time_offset) * _time_speed;
if (dt > _max_time_interval)
dt = _max_time_interval;
_time += dt;
_time_offset = t - _time;
}
return *this;
}
void next_frame() {
if (_syncro_by_clock)
adjust();
else {
_time_prev = _time;
_time += _time_per_frame * _time_speed;
// _time += round(_time_per_frame*_time_speed);
}
}
void skip() {
if (_syncro_by_clock)
_time_offset = g_system->getMillis() - _time;
}
void setTime(time_type t) {
_time_prev = _time = t;
_time_offset = _syncro_by_clock ? g_system->getMillis() - _time : 0;
}
void setSpeed(float speed) {
_time_speed = speed;
}
private:
float _time;
float _time_prev;
float _time_offset;
time_type _max_time_interval;
time_type _time_per_frame;
int _syncro_by_clock;
float _time_speed;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_SYNCRO_TIMER

View File

@@ -0,0 +1,177 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "common/file.h"
#include "graphics/managed_surface.h"
#include "video/mpegps_decoder.h"
#include "qdengine/qdengine.h"
#include "qdengine/qdcore/util/WinVideo.h"
#include "qdengine/system/graphics/gr_dispatcher.h"
namespace QDEngine {
bool winVideo::_is_initialized = false;
winVideo::winVideo() {
_decoder = new Video::MPEGPSDecoder();
_x = _y = 0;
_vidWidth = _vidHeight = 0;
_videostream = nullptr;
}
winVideo::~winVideo() {
close_file();
delete _decoder;
}
bool winVideo::init() {
return true;
}
bool winVideo::done() {
if (!_is_initialized)
return false;
_is_initialized = false;
return true;
}
void winVideo::set_window(int x, int y, int xsize, int ysize) {
_x = x;
_y = y;
_vidWidth = xsize;
_vidHeight = ysize;
delete _tempSurf;
_tempSurf = nullptr;
if (_vidWidth != _decoder->getWidth() || _vidHeight != _decoder->getHeight())
_tempSurf = new Graphics::ManagedSurface(xsize, ysize, g_engine->_pixelformat);
}
bool winVideo::open_file(const Common::Path &fname) {
Common::String filename = (char *)transCyrillic(fname.toString());
debugC(3, kDebugLoad, "winVideo::open_file(%s)", filename.c_str());
_videostream = new Common::File();
if (!_videostream->open(filename.c_str())) {
// Try with punyencoded path
if (!_videostream->open(Common::Path(filename).punycodeEncode())) {
warning("WinVideo::open: Failed to open file %s", filename.c_str());
delete _videostream;
_videostream = nullptr;
return false;
}
}
// WORKAROUND: Fix lagging audio in mng and rybalka
// videos by setting specific number of prebuffered packets
// for MPEG-PS demuxer.
Common::String gameId = g_engine->getGameId();
if (gameId == "mng" || gameId == "rybalka") {
_decoder->setPrebufferedPackets(600);
}
if (!_decoder->loadStream(_videostream)) {
warning("WinVideo::open: Failed to Load Stream for file '%s'", filename.c_str());
_videostream = nullptr;
return false;
}
return true;
}
bool winVideo::play() {
if (!_videostream) {
warning("WinVideo::play: No video stream loaded");
return false;
}
_decoder->setVolume(ConfMan.getInt("music_volume"));
_decoder->start();
return true;
}
bool winVideo::quant() {
debugC(9, kDebugGraphics, "WinVideo::play: Video Playback loop");
// Video Playback loop
if (_decoder->needsUpdate()) {
const Graphics::Surface *frame = _decoder->decodeNextFrame();
int frameWidth = _decoder->getWidth();
int frameHeight = _decoder->getHeight();
const Graphics::Surface *surf = frame;
if (frame) {
if (_tempSurf) {
const Common::Rect srcRect(0, 0, frameWidth, frameHeight);
const Common::Rect destRect(0, 0, _vidWidth, _vidHeight);
_tempSurf->blitFrom(*frame, srcRect, destRect);
surf = _tempSurf->surfacePtr();
}
g_system->copyRectToScreen(surf->getPixels(), surf->pitch, _x, _y, _vidWidth, _vidHeight);
}
g_system->delayMillis(10);
g_system->updateScreen();
}
return true;
}
bool winVideo::stop() {
delete _tempSurf;
_tempSurf = NULL;
return true;
}
bool winVideo::is_playback_finished() {
return _decoder->endOfVideo();
}
bool winVideo::get_movie_size(int &sx, int &sy) {
if (!_decoder)
return false;
sx = _decoder->getWidth();
sy = _decoder->getHeight();
return true;
}
void winVideo::close_file() {
if (_videostream)
_videostream->close();
}
} // namespace QDEngine

View File

@@ -0,0 +1,86 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_WINVIDEO_H
#define QDENGINE_QDCORE_UTIL_WINVIDEO_H
//#define __WINVIDEO_LOG__
namespace Video {
class MPEGPSDecoder;
}
namespace Graphics {
class ManagedSurface;
}
namespace Common {
class File;
}
namespace QDEngine {
class winVideo {
public:
enum PlaybackStatus {
VID_RUNNING,
VID_STOPPED,
VID_PAUSED
};
winVideo();
~winVideo();
static bool init(); // initialize DirectShow Lib
static bool done(); // uninitialize DirectShow Lib
bool open_file(const Common::Path &fname);
void close_file();
bool play();
bool stop();
bool quant();
bool is_playback_finished();
void set_window(int x = 0, int y = 0, int xsize = 0, int ysize = 0);
bool get_movie_size(int &sx, int &sy);
bool set_window_size(int sx, int sy);
private:
// Coordinates of the top left corner of the video
int _x;
int _y;
int _vidWidth;
int _vidHeight;
Graphics::ManagedSurface *_tempSurf = nullptr;
// Video decoder
Video::MPEGPSDecoder *_decoder;
Common::File *_videostream;
static bool _is_initialized;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_WINVIDEO_H

View File

@@ -0,0 +1,84 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/system.h"
#include "qdengine/qdcore/util/fps_counter.h"
namespace QDEngine {
fpsCounter::fpsCounter(int period) : _start_time(0.0f),
_prev_time(0.0f),
_period(period),
_frame_count(0),
_value(-1.0f),
_value_min(0.0f),
_value_max(0.0f),
_min_frame_time(1000.0f),
_max_frame_time(0.0f) {
}
bool fpsCounter::quant() {
float time = float(g_system->getMillis());
if (_min_frame_time > time - _prev_time)
_min_frame_time = time - _prev_time;
if (_max_frame_time < time - _prev_time)
_max_frame_time = time - _prev_time;
_frame_count++;
_prev_time = time;
if (_period) {
if (_prev_time - _start_time >= _period) {
_value = float(_frame_count) / (_prev_time - _start_time) * 1000.0f;
_value_min = 1000.0f / _max_frame_time;
_value_max = 1000.0f / _min_frame_time;
_frame_count = 0;
_start_time = _prev_time;
_min_frame_time = 10000.0f;
_max_frame_time = 0.0f;
return true;
}
return false;
} else {
_value = float(_frame_count) / (float(g_system->getMillis()) - _start_time) * 1000.0f;
return true;
}
}
void fpsCounter::reset() {
_prev_time = _start_time = float(g_system->getMillis());
_frame_count = 0;
_value = -1.0f;
_value_min = _value_max = 0.0f;
_min_frame_time = 10000.0f;
_max_frame_time = 0.0f;
}
} // namespace QDEngine

View File

@@ -0,0 +1,73 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_FPS_COUNTER_H
#define QDENGINE_QDCORE_UTIL_FPS_COUNTER_H
namespace QDEngine {
class fpsCounter {
public:
fpsCounter(int period = 3000);
~fpsCounter() { }
bool quant();
float fps_value() const {
return _value;
}
float fps_value_min() const {
return _value_min;
}
float fps_value_max() const {
return _value_max;
}
void reset();
int period() const {
return _period;
}
void set_period(int p) {
_period = p;
}
private:
float _start_time;
float _prev_time;
int _frame_count;
int _period;
float _value;
float _value_min;
float _value_max;
float _min_frame_time;
float _max_frame_time;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_FPS_COUNTER_H

View File

@@ -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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/stream.h"
#include "audio/audiostream.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/mpc.h"
#include "qdengine/qdengine.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/qdcore/qd_file_manager.h"
#include "qdengine/qdcore/util/plaympp_api.h"
namespace QDEngine {
mpegPlayer::mpegPlayer() : _is_enabled(true),
_volume(255),
_cur_track_volume(255),
_paused(false) {
}
mpegPlayer::~mpegPlayer() {
}
bool mpegPlayer::play(const Common::Path &file, bool loop, int vol) {
bool isOGG = file.baseName().hasSuffixIgnoreCase(".ogg");
debugC(1, kDebugSound, "mpegPlayer::play(%s, %d, %d)", file.toString().c_str(), loop, vol);
_file = file;
stop();
Common::SeekableReadStream *stream;
if (!qdFileManager::instance().open_file(&stream, file, false)) {
if (!qdFileManager::instance().open_file(&stream, file.punycodeEncode(), false)) {
warning(" mpegPlayer::play(): Failed to open file %s", file.toString().c_str());
}
}
Audio::SeekableAudioStream *audiostream;
if (isOGG) {
#ifdef USE_VORBIS
audiostream = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
#else
warning("mpegPlayer::play(%s, %d, %d): Vorbis support not compiled", file.toString().c_str(), loop, vol);
return false;
#endif
} else {
#ifdef USE_MPCDEC
audiostream = Audio::makeMPCStream(stream, DisposeAfterUse::YES);
#else
warning("mpegPlayer::play(%s, %d, %d): MPC support not compiled", file.toString().c_str(), loop, vol);
return false;
#endif
}
if (!loop) {
g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audiostream);
} else {
Audio::LoopingAudioStream *looped = new Audio::LoopingAudioStream(audiostream, 0, DisposeAfterUse::YES);
g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, looped);
}
set_volume(vol);
_paused = false;
debugC(1, kDebugSound, "mpegPlayer::play(%s)", _file.toString().c_str());
return true;
}
bool mpegPlayer::stop() {
debugC(1, kDebugSound, "mpegPlayer::stop(%s)", _file.toString().c_str());
g_system->getMixer()->stopHandle(_soundHandle);
return true;
}
bool mpegPlayer::pause() {
if (_paused)
return true;
debugC(1, kDebugSound, "mpegPlayer::pause(%s)", _file.toString().c_str());
g_system->getMixer()->pauseHandle(_soundHandle, true);
_paused = true;
return true;
}
bool mpegPlayer::resume() {
if (!_paused)
return true;
debugC(1, kDebugSound, "mpegPlayer::resume(%s)", _file.toString().c_str());
g_system->getMixer()->pauseHandle(_soundHandle, false);
_paused = false;
g_system->getMixer()->setChannelVolume(_soundHandle, _volume * _cur_track_volume / 256);
return true;
}
mpegPlayer::mpeg_status_t mpegPlayer::status() const {
mpeg_status_t res;
if (!g_system->getMixer()->isReady())
res = MPEG_STOPPED;
else if (_paused)
res = MPEG_PAUSED;
else if (g_system->getMixer()->isSoundHandleActive(_soundHandle))
res = MPEG_PLAYING;
else
res = MPEG_STOPPED;
debugC(7, kDebugSound, "mpegPlayer::status(%s), status: %d", _file.toString().c_str(), res);
return res;
}
void mpegPlayer::set_volume(uint32 vol) {
debugC(1, kDebugSound, "mpegPlayer::set_volume(%s), vol: %d", _file.toString().c_str(), vol);
_volume = vol;
g_system->getMixer()->setChannelVolume(_soundHandle, _volume * _cur_track_volume / 256);
}
bool mpegPlayer::init_library(void *dsound_device) {
return true;
}
void mpegPlayer::deinit_library() {
}
mpegPlayer *g_mpegPlayer = nullptr;
mpegPlayer &mpegPlayer::instance() {
if (!g_mpegPlayer)
g_mpegPlayer = new mpegPlayer;
return *g_mpegPlayer;
}
void mpegPlayer::syncMusicSettings() {
set_volume(ConfMan.getInt("music_volume"));
if (ConfMan.getBool("enable_music"))
enable();
else
disable();
}
} // namespace QDEngine

View File

@@ -0,0 +1,102 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_PLAYMPP_API_H
#define QDENGINE_QDCORE_UTIL_PLAYMPP_API_H
#include "audio/mixer.h"
namespace Common {
class SeekableReadStream;
}
namespace QDEngine {
class MpegSound;
class mpegPlayer {
public:
//! Состояние.
enum mpeg_status_t {
MPEG_STOPPED,
MPEG_PAUSED,
MPEG_PLAYING
};
~mpegPlayer();
bool play(const Common::Path &file, bool loop = false, int vol = 256);
bool stop();
bool pause();
bool resume();
bool is_enabled() const {
return _is_enabled;
}
//! Разрешает проигрывание музыки.
void enable(bool need_resume = true) {
_is_enabled = true;
if (need_resume) resume();
}
//! Запрещает проигрывание музыки.
void disable() {
_is_enabled = false;
pause();
}
mpeg_status_t status() const;
bool is_playing() const {
return (status() == MPEG_PLAYING);
}
uint32 volume() const {
return _volume;
}
void set_volume(uint32 vol);
void syncMusicSettings();
static bool init_library(void *dsound_device);
static void deinit_library();
static mpegPlayer &instance();
private:
mpegPlayer();
//! Music is off when false
bool _is_enabled;
bool _paused;
//! Music volume, [0, 255].
uint32 _volume;
uint32 _cur_track_volume;
Audio::SoundHandle _soundHandle;
Common::Path _file;
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_PLAYMPP_API_H

View File

@@ -0,0 +1,110 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/events.h"
#include "common/fs.h"
#include "common/formats/winexe.h"
#include "common/formats/winexe_pe.h"
#include "common/system.h"
#include "graphics/paletteman.h"
#include "graphics/surface.h"
#include "image/bmp.h"
#include "qdengine/qdcore/util/splash_screen.h"
#include "qdengine/qdengine.h"
namespace QDEngine {
bool SplashScreen::create(int bitmapResID) {
if (!create_window()) return false;
Common::ScopedPtr<Common::PEResources> r(new Common::PEResources());
Common::WinResourceID resid(bitmapResID);
Image::BitmapDecoder decoder;
if (r->loadFromEXE(g_engine->getExeName())) {
Common::SeekableReadStream *stream = r->getResource(Common::kWinBitmap, resid);
if (stream && decoder.loadStream(*stream)) {
_splash = new Graphics::Surface();
_splash->copyFrom(*decoder.getSurface());
_paletteCount = decoder.getPalette().size();
_palette = new byte[_paletteCount * 3];
memcpy(_palette, decoder.getPalette().data(), _paletteCount * 3);
}
} else {
warning("SplashScreen::create(): Cannot load splash screen from file %s", g_engine->getExeName());
}
return true;
}
bool SplashScreen::create(const char *bitmap_file) {
return true;
}
bool SplashScreen::set_mask(int mask_resid) {
return true;
}
bool SplashScreen::set_mask(const char *mask_file) {
return true;
}
bool SplashScreen::destroy() {
delete _splash;
_splash = nullptr;
delete[] _palette;
_palette = nullptr;
return true;
}
void SplashScreen::show() {
g_system->fillScreen(0);
g_system->getPaletteManager()->setPalette(_palette, 0, _paletteCount);
_start_time = g_system->getMillis();
if (!_splash)
return;
int x = (640 - _splash->w) / 2;
int y = (480 - _splash->h) / 2;
g_system->copyRectToScreen(_splash->getPixels(), _splash->pitch, x, y, _splash->w, _splash->h);
g_system->updateScreen();
}
void SplashScreen::wait(uint time) {
if (g_system->getMillis() - _start_time < time)
g_system->delayMillis(time - (g_system->getMillis() - _start_time));
}
void SplashScreen::hide() {
}
bool SplashScreen::create_window() {
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,64 @@
/* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QDENGINE_QDCORE_UTIL_SPLASH_SCREEN_H
#define QDENGINE_QDCORE_UTIL_SPLASH_SCREEN_H
namespace Graphics {
struct Surface;
}
namespace QDEngine {
class SplashScreen {
public:
SplashScreen() : _start_time(0) { }
~SplashScreen() {
destroy();
}
bool create(int bitmap_resid);
bool create(const char *bitmap_file);
bool set_mask(int mask_resid);
bool set_mask(const char *mask_file);
bool destroy();
void show();
void hide();
void wait(uint time);
private:
uint _start_time = 0;
Graphics::Surface *_splash = nullptr;
byte *_palette = nullptr;
int _paletteCount = 0;
bool create_window();
};
} // namespace QDEngine
#endif // QDENGINE_QDCORE_UTIL_SPLASH_SCREEN_H