diff options
-rw-r--r-- | engines/zvision/graphics/effect.h | 83 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/fog.cpp | 174 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/fog.h | 52 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/light.cpp | 110 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/light.h | 53 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/wave.cpp | 146 | ||||
-rw-r--r-- | engines/zvision/graphics/effects/wave.h | 51 | ||||
-rw-r--r-- | engines/zvision/graphics/render_manager.cpp | 218 | ||||
-rw-r--r-- | engines/zvision/graphics/render_manager.h | 14 | ||||
-rw-r--r-- | engines/zvision/module.mk | 4 | ||||
-rw-r--r-- | engines/zvision/scripting/actions.cpp | 80 | ||||
-rw-r--r-- | engines/zvision/scripting/actions.h | 16 | ||||
-rw-r--r-- | engines/zvision/scripting/scr_file_handling.cpp | 2 | ||||
-rw-r--r-- | engines/zvision/scripting/script_manager.h | 4 | ||||
-rw-r--r-- | engines/zvision/scripting/sidefx/region_node.cpp | 56 | ||||
-rw-r--r-- | engines/zvision/scripting/sidefx/region_node.h | 57 |
16 files changed, 1115 insertions, 5 deletions
diff --git a/engines/zvision/graphics/effect.h b/engines/zvision/graphics/effect.h new file mode 100644 index 0000000000..c6653c6037 --- /dev/null +++ b/engines/zvision/graphics/effect.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef EFFECT_H_INCLUDED +#define EFFECT_H_INCLUDED + +#include "common/rect.h" +#include "common/list.h" +#include "graphics/surface.h" + +#include "zvision/zvision.h" + +namespace ZVision { + +class ZVision; + +class Effect { +public: + + Effect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) { + _surface.create(_region.width(), _region.height(), _engine->_pixelFormat); + } + virtual ~Effect() {} + + uint32 getKey() { + return _key; + } + + Common::Rect getRegion() { + return _region; + } + + bool isPort() { + return _ported; + } + + virtual const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) { + return &_surface; + } + + virtual void update() {} + +protected: + ZVision *_engine; + uint32 _key; + Common::Rect _region; + bool _ported; + Graphics::Surface _surface; + +// Static member functions +public: + +}; + +struct EffectMapUnit { + uint32 count; + bool inEffect; +}; + +typedef Common::List<EffectMapUnit> EffectMap; + +} // End of namespace ZVision + +#endif // EFFECT_H_INCLUDED diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp new file mode 100644 index 0000000000..b6c5e7b011 --- /dev/null +++ b/engines/zvision/graphics/effects/fog.cpp @@ -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 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/graphics/effects/fog.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" +#include "zvision/scripting/script_manager.h" + + +namespace ZVision { + +FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds): + Effect(engine, key, region, ported) { + + _map = Map; + + _r = 0; + _g = 0; + _b = 0; + + _pos = 0; + + if (_engine->getSearchManager()->hasFile(clouds)) + _engine->getRenderManager()->readImageToSurface(clouds, _fog); + else + _engine->getRenderManager()->readImageToSurface("cloud.tga", _fog); + + _mp.resize(_fog.h); + for (int16 i = 0; i < _fog.h; i++) { + _mp[i].resize(_fog.w); + for (int16 j = 0; j < _fog.w; j++) + _mp[i][j] = true; + } + + for (uint8 i = 0; i < 32; i++) + _colorMap[i] = 0; +} + +FogFx::~FogFx() { + if (_map) + delete _map; + + for (uint16 i = 0; i < _mp.size(); i++) + _mp[i].clear(); + _mp.clear(); +} + +const Graphics::Surface *FogFx::draw(const Graphics::Surface &srcSubRect) { + _surface.copyFrom(srcSubRect); + EffectMap::iterator it = _map->begin(); + + uint32 cnt = 0; + + for (uint16 j = 0; j < _surface.h; j++) { + uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j); + + for (uint16 i = 0; i < _surface.w; i++) { + if (it->inEffect) { + // Not 100% equivalent, but looks nice and not buggy + uint8 sr, sg, sb; + _engine->_pixelFormat.colorToRGB(lineBuf[i], sr, sg, sb); + uint16 fogColor = *(uint16 *)_fog.getBasePtr((i + _pos) % _fog.w, j); + uint8 dr, dg, db; + _engine->_pixelFormat.colorToRGB(_colorMap[fogColor & 0x1F], dr, dg, db); + uint16 fr = dr + sr; + if (fr > 255) + fr = 255; + uint16 fg = dg + sg; + if (fg > 255) + fg = 255; + uint16 fb = db + sb; + if (fb > 255) + fb = 255; + lineBuf[i] = _engine->_pixelFormat.RGBToColor(fr, fg, fb); + } + cnt++; + if (cnt >= it->count) { + it++; + cnt = 0; + } + if (it == _map->end()) + break; + } + if (it == _map->end()) + break; + } + + return &_surface; +} + +void FogFx::update() { + _pos += _engine->getScriptManager()->getStateValue(StateKey_EF9_Speed); + _pos %= _fog.w; + + uint8 dr = _engine->getScriptManager()->getStateValue(StateKey_EF9_R); + uint8 dg = _engine->getScriptManager()->getStateValue(StateKey_EF9_G); + uint8 db = _engine->getScriptManager()->getStateValue(StateKey_EF9_B); + dr = CLIP((int)dr, 0, 31); + dg = CLIP((int)dg, 0, 31); + db = CLIP((int)db, 0, 31); + + if (dr != _r || dg != _g || db != _b) { + if (_r > dr) + _r--; + else if (_r < dr) + _r++; + + if (_g > dg) + _g--; + else if (_g < dg) + _g++; + + if (_b > db) + _b--; + else if (_b < db) + _b++; + + // Not 100% equivalent, but looks nice and not buggy + + _colorMap[31] = _engine->_pixelFormat.RGBToColor(_r << 3, _g << 3, _b << 3); + + for (uint8 i = 0; i < 31; i++) { + float perc = (float)i / 31.0; + uint8 cr = (float)_r * perc; + uint8 cg = (float)_g * perc; + uint8 cb = (float)_b * perc; + _colorMap[i] = _engine->_pixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3); + } + } + + for (uint16 j = 0; j < _fog.h; j++) { + uint16 *pix = (uint16 *)_fog.getBasePtr(0, j); + + for (uint16 i = 0; i < _fog.w; i++) { + if (_mp[j][i]) { + if ((pix[i] & 0x1F) == 0x1F) { + pix[i]--; + _mp[j][i] = false; + } else + pix[i]++; + } else { + if ((pix[i] & 0x1F) == 0) { + pix[i]++; + _mp[j][i] = true; + } else + pix[i]--; + } + } + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/graphics/effects/fog.h b/engines/zvision/graphics/effects/fog.h new file mode 100644 index 0000000000..62dd1f9473 --- /dev/null +++ b/engines/zvision/graphics/effects/fog.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef FOGFX_H_INCLUDED +#define FOGFX_H_INCLUDED + +#include "zvision/graphics/effect.h" + +namespace ZVision { + +class ZVision; + +class FogFx : public Effect { +public: + + FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds); + ~FogFx(); + + const Graphics::Surface *draw(const Graphics::Surface &srcSubRect); + + void update(); + +private: + EffectMap *_map; + Graphics::Surface _fog; + uint8 _r, _g, _b; + int32 _pos; + Common::Array< Common::Array< bool > > _mp; + uint16 _colorMap[32]; +}; +} // End of namespace ZVision + +#endif // FOGFX_H_INCLUDED diff --git a/engines/zvision/graphics/effects/light.cpp b/engines/zvision/graphics/effects/light.cpp new file mode 100644 index 0000000000..9bff077051 --- /dev/null +++ b/engines/zvision/graphics/effects/light.cpp @@ -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 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/graphics/effects/light.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" + + +namespace ZVision { + +LightFx::LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD, int8 maxD): + Effect(engine, key, region, ported) { + _map = Map; + _delta = delta; + _up = true; + _pos = 0; + + _minD = minD; + if (_minD < -delta) + _minD = -delta; + + _maxD = maxD; + if (_maxD > delta) + _maxD = delta; +} + +LightFx::~LightFx() { + if (_map) + delete _map; +} + +const Graphics::Surface *LightFx::draw(const Graphics::Surface &srcSubRect) { + _surface.copyFrom(srcSubRect); + EffectMap::iterator it = _map->begin(); + uint32 cnt = 0; + + uint32 dcolor = 0; + + if (_pos < 0) { + uint8 cc = ((-_pos) & 0x1F) << 3; + dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc); + } else { + uint8 cc = (_pos & 0x1F) << 3; + dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc); + } + + for (uint16 j = 0; j < _surface.h; j++) { + uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j); + + for (uint16 i = 0; i < _surface.w; i++) { + if (it->inEffect) { + if (_pos < 0) { + lineBuf[i] -= dcolor; + } else { + lineBuf[i] += dcolor; + } + } + cnt++; + if (cnt >= it->count) { + it++; + cnt = 0; + } + if (it == _map->end()) + break; + } + if (it == _map->end()) + break; + } + + return &_surface; +} + +void LightFx::update() { + if (_up) + _pos++; + else + _pos--; + + if (_pos <= _minD) { + _up = !_up; + _pos = _minD; + } else if (_pos >= _maxD) { + _up = !_up; + _pos = _maxD; + } +} + +} // End of namespace ZVision diff --git a/engines/zvision/graphics/effects/light.h b/engines/zvision/graphics/effects/light.h new file mode 100644 index 0000000000..ae87d66cb3 --- /dev/null +++ b/engines/zvision/graphics/effects/light.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LIGHTFX_H_INCLUDED +#define LIGHTFX_H_INCLUDED + +#include "zvision/graphics/effect.h" + +namespace ZVision { + +class ZVision; + +class LightFx : public Effect { +public: + + LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD = -127, int8 maxD = 127); + ~LightFx(); + + const Graphics::Surface *draw(const Graphics::Surface &srcSubRect); + + void update(); + +private: + EffectMap *_map; + int32 _delta; + bool _up; + int32 _pos; + + int8 _minD; + int8 _maxD; +}; +} // End of namespace ZVision + +#endif // LIGHTFX_H_INCLUDED diff --git a/engines/zvision/graphics/effects/wave.cpp b/engines/zvision/graphics/effects/wave.cpp new file mode 100644 index 0000000000..88239f3cad --- /dev/null +++ b/engines/zvision/graphics/effects/wave.cpp @@ -0,0 +1,146 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/graphics/effects/wave.h" + +#include "zvision/zvision.h" +#include "zvision/graphics/render_manager.h" + + +namespace ZVision { + +WaveFx::WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 s_x, int16 s_y, float ampl, float waveln, float spd): + Effect(engine, key, region, ported) { + + _frame = 0; + _frame_cnt = frames; + + _ampls.resize(_frame_cnt); + _hw = _region.width() / 2; + _hh = _region.height() / 2; + + int32 frmsize = _hw * _hh; + + float phase = 0; + + int16 w_4 = _hw / 2; + int16 h_4 = _hh / 2; + + for (int16 i = 0; i < _frame_cnt; i++) { + _ampls[i].resize(frmsize); + + for (int16 y = 0; y < _hh; y++) + for (int16 x = 0; x < _hw; x++) { + int16 dx = (x - w_4); + int16 dy = (y - h_4); + + _ampls[i][x + y * _hw] = ampl * sin(sqrt(dx * dx / (float)s_x + dy * dy / (float)s_y) / (-waveln * 3.1415926) + phase); + } + phase += spd; + } +} + +WaveFx::~WaveFx() { + for (uint16 i = 0; i < _ampls.size(); i++) + _ampls[i].clear(); + _ampls.clear(); +} + +const Graphics::Surface *WaveFx::draw(const Graphics::Surface &srcSubRect) { + for (int16 y = 0; y < _hh; y++) { + uint16 *abc = (uint16 *)_surface.getBasePtr(0, y); + uint16 *abc2 = (uint16 *)_surface.getBasePtr(0, _hh + y); + uint16 *abc3 = (uint16 *)_surface.getBasePtr(_hw, y); + uint16 *abc4 = (uint16 *)_surface.getBasePtr(_hw, _hh + y); + + for (int16 x = 0; x < _hw; x++) { + int8 amnt = _ampls[_frame][x + _hw * y]; + + int16 n_x = x + amnt; + int16 n_y = y + amnt; + + if (n_x < 0) + n_x = 0; + if (n_x >= _region.width()) + n_x = _region.width() - 1; + if (n_y < 0) + n_y = 0; + if (n_y >= _region.height()) + n_y = _region.height() - 1; + *abc = *(const uint16 *)srcSubRect.getBasePtr(n_x, n_y); + + n_x = x + amnt + _hw; + n_y = y + amnt; + + if (n_x < 0) + n_x = 0; + if (n_x >= _region.width()) + n_x = _region.width() - 1; + if (n_y < 0) + n_y = 0; + if (n_y >= _region.height()) + n_y = _region.height() - 1; + *abc3 = *(const uint16 *)srcSubRect.getBasePtr(n_x, n_y); + + n_x = x + amnt; + n_y = y + amnt + _hh; + + if (n_x < 0) + n_x = 0; + if (n_x >= _region.width()) + n_x = _region.width() - 1; + if (n_y < 0) + n_y = 0; + if (n_y >= _region.height()) + n_y = _region.height() - 1; + *abc2 = *(const uint16 *)srcSubRect.getBasePtr(n_x, n_y); + + n_x = x + amnt + _hw; + n_y = y + amnt + _hh; + + if (n_x < 0) + n_x = 0; + if (n_x >= _region.width()) + n_x = _region.width() - 1; + if (n_y < 0) + n_y = 0; + if (n_y >= _region.height()) + n_y = _region.height() - 1; + *abc4 = *(const uint16 *)srcSubRect.getBasePtr(n_x, n_y); + + abc++; + abc2++; + abc3++; + abc4++; + } + } + + return &_surface; +} + +void WaveFx::update() { + _frame = (_frame + 1) % _frame_cnt; +} + +} // End of namespace ZVision diff --git a/engines/zvision/graphics/effects/wave.h b/engines/zvision/graphics/effects/wave.h new file mode 100644 index 0000000000..0046dfceec --- /dev/null +++ b/engines/zvision/graphics/effects/wave.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WAVEFX_H_INCLUDED +#define WAVEFX_H_INCLUDED + +#include "common/array.h" +#include "zvision/graphics/effect.h" + +namespace ZVision { + +class ZVision; + +class WaveFx : public Effect { +public: + + WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 s_x, int16 s_y, float ampl, float waveln, float spd); + ~WaveFx(); + + const Graphics::Surface *draw(const Graphics::Surface &srcSubRect); + + void update(); + +private: + int16 _frame; + int16 _frame_cnt; + int16 _hw, _hh; + Common::Array< Common::Array< int8 > > _ampls; +}; +} // End of namespace ZVision + +#endif // WAVEFX_H_INCLUDED diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp index 5aa0d752d0..0aa062214f 100644 --- a/engines/zvision/graphics/render_manager.cpp +++ b/engines/zvision/graphics/render_manager.cpp @@ -54,6 +54,7 @@ RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowH _renderTable(_wrkWidth, _wrkHeight) { _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); + _effectWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat); _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); @@ -67,21 +68,55 @@ RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowH RenderManager::~RenderManager() { _curBkg.free(); _wrkWnd.free(); + _effectWnd.free(); _outWnd.free(); + _menuWnd.free(); + _subWnd.free(); } void RenderManager::renderBackbufferToScreen() { Graphics::Surface *out = &_outWnd; + Graphics::Surface *in = &_wrkWnd; + + if (!_effects.empty()) { + bool copied = false; + Common::Rect windRect(_wrkWidth, _wrkHeight); + for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + Common::Rect rect = (*it)->getRegion(); + Common::Rect scrPlace = rect; + if ((*it)->isPort()) + scrPlace = bkgRectToScreen(scrPlace); + if (windRect.intersects(scrPlace)) { + if (!copied) { + copied = true; + _effectWnd.copyFrom(_wrkWnd); + in = &_effectWnd; + } + const Graphics::Surface *post; + if ((*it)->isPort()) + post = (*it)->draw(_curBkg.getSubArea(rect)); + else + post = (*it)->draw(_effectWnd.getSubArea(rect)); + blitSurfaceToSurface(*post, _effectWnd, scrPlace.left, scrPlace.top); + scrPlace.clip(windRect); + if (_wrkWndDirtyRect .isEmpty()) { + _wrkWndDirtyRect = scrPlace; + } else { + _wrkWndDirtyRect.extend(scrPlace); + } + } + } + } RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { if (!_wrkWndDirtyRect.isEmpty()) { - _renderTable.mutateImage(&_outWnd, &_wrkWnd); + _renderTable.mutateImage(&_outWnd, in); out = &_outWnd; _outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight); } } else { - out = &_wrkWnd; + out = in; _outWndDirtyRect = _wrkWndDirtyRect; } @@ -832,4 +867,183 @@ Common::Point RenderManager::getBkgSize() { return Common::Point(_bkgWidth, _bkgHeight); } +void RenderManager::addEffect(Effect *_effect) { + _effects.push_back(_effect); +} + +void RenderManager::deleteEffect(uint32 ID) { + for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) { + if ((*it)->getKey() == ID) { + delete *it; + it = _effects.erase(it); + } + } +} + +Common::Rect RenderManager::bkgRectToScreen(const Common::Rect &src) { + Common::Rect tmp = src; + RenderTable::RenderState state = _renderTable.getRenderState(); + + if (state == RenderTable::PANORAMA) { + if (_bkgOff < _screenCenterX) { + Common::Rect rScreen(_screenCenterX + _bkgOff, _wrkHeight); + Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); + lScreen.translate(_bkgWidth - lScreen.width(), 0); + lScreen.clip(src); + rScreen.clip(src); + if (rScreen.width() < lScreen.width()) { + tmp.translate(_screenCenterX - _bkgOff - _bkgWidth, 0); + } else { + tmp.translate(_screenCenterX - _bkgOff, 0); + } + } else if (_bkgWidth - _bkgOff < _screenCenterX) { + Common::Rect rScreen(_screenCenterX - (_bkgWidth - _bkgOff), _wrkHeight); + Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight); + lScreen.translate(_bkgWidth - lScreen.width(), 0); + lScreen.clip(src); + rScreen.clip(src); + if (lScreen.width() < rScreen.width()) { + tmp.translate(_screenCenterX + (_bkgWidth - _bkgOff), 0); + } else { + tmp.translate(_screenCenterX - _bkgOff, 0); + } + } else { + tmp.translate(_screenCenterX - _bkgOff, 0); + } + } else if (state == RenderTable::TILT) { + tmp.translate(0, (_screenCenterY - _bkgOff)); + } + + return tmp; +} + +EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *_minComp, int8 *_maxComp) { + Common::Rect bkgRect(_bkgWidth, _bkgHeight); + if (!bkgRect.contains(xy)) + return NULL; + + if (!bkgRect.intersects(rect)) + return NULL; + + uint16 color = *(uint16 *)_curBkg.getBasePtr(xy.x, xy.y); + uint8 stC1, stC2, stC3; + _curBkg.format.colorToRGB(color, stC1, stC2, stC3); + EffectMap *newMap = new EffectMap; + + EffectMapUnit unit; + unit.count = 0; + unit.inEffect = false; + + int16 w = rect.width(); + int16 h = rect.height(); + + bool first = true; + + uint8 minComp = MIN(MIN(stC1, stC2), stC3); + uint8 maxComp = MAX(MAX(stC1, stC2), stC3); + + uint8 depth8 = depth << 3; + + for (int16 j = 0; j < h; j++) { + uint16 *pix = (uint16 *)_curBkg.getBasePtr(rect.left, rect.top + j); + for (int16 i = 0; i < w; i++) { + uint16 curClr = pix[i]; + uint8 cC1, cC2, cC3; + _curBkg.format.colorToRGB(curClr, cC1, cC2, cC3); + + bool use = false; + + if (curClr == color) + use = true; + else if (curClr > color) { + if ((cC1 - stC1 < depth8) && + (cC2 - stC2 < depth8) && + (cC3 - stC3 < depth8)) + use = true; + } else { /* if (curClr < color) */ + if ((stC1 - cC1 < depth8) && + (stC2 - cC2 < depth8) && + (stC3 - cC3 < depth8)) + use = true; + } + + if (first) { + unit.inEffect = use; + first = false; + } + + if (use) { + uint8 cMinComp = MIN(MIN(cC1, cC2), cC3); + uint8 cMaxComp = MAX(MAX(cC1, cC2), cC3); + if (cMinComp < minComp) + minComp = cMinComp; + if (cMaxComp > maxComp) + maxComp = cMaxComp; + } + + if (unit.inEffect == use) + unit.count++; + else { + newMap->push_back(unit); + unit.count = 1; + unit.inEffect = use; + } + } + } + newMap->push_back(unit); + + if (_minComp) { + if (minComp - depth8 < 0) + *_minComp = -(minComp >> 3); + else + *_minComp = -depth; + } + if (_maxComp) { + if ((int16)maxComp + (int16)depth8 > 255) + *_maxComp = (255 - maxComp) >> 3; + else + *_maxComp = depth; + } + + return newMap; +} + +EffectMap *RenderManager::makeEffectMap(const Graphics::Surface &surf, uint16 transp) { + EffectMapUnit unit; + unit.count = 0; + unit.inEffect = false; + + int16 w = surf.w; + int16 h = surf.h; + + EffectMap *newMap = new EffectMap; + + bool first = true; + + for (int16 j = 0; j < h; j++) { + const uint16 *pix = (const uint16 *)surf.getBasePtr(0, j); + for (int16 i = 0; i < w; i++) { + bool use = false; + if (pix[i] != transp) + use = true; + + if (first) { + unit.inEffect = use; + first = false; + } + + if (unit.inEffect == use) + unit.count++; + else { + newMap->push_back(unit); + unit.count = 1; + unit.inEffect = use; + } + } + } + newMap->push_back(unit); + + return newMap; +} + } // End of namespace ZVision diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h index 24234e28e1..665a27bf64 100644 --- a/engines/zvision/graphics/render_manager.h +++ b/engines/zvision/graphics/render_manager.h @@ -31,6 +31,8 @@ #include "graphics/surface.h" +#include "effect.h" + class OSystem; @@ -68,6 +70,7 @@ private: // }; // typedef Common::HashMap<uint16, oneSub> subMap; + typedef Common::List<Effect *> effectsList; private: ZVision *_engine; @@ -93,6 +96,8 @@ private: Common::Rect _menuWndDirtyRect; + Graphics::Surface _effectWnd; + // A buffer the exact same size as the workingWindow // This buffer stores everything un-warped, then does a warp at the end of the frame @@ -151,6 +156,8 @@ private: /** Holds any 'leftover' milliseconds between frames */ //uint _accumulatedVelocityMilliseconds; + effectsList _effects; + public: void initialize(); @@ -267,6 +274,13 @@ public: */ void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination); void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed); + + void addEffect(Effect *_effect); + void deleteEffect(uint32 ID); + EffectMap *makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *minD, int8 *maxD); + EffectMap *makeEffectMap(const Graphics::Surface &surf, uint16 transp); + + Common::Rect bkgRectToScreen(const Common::Rect &src); }; } // End of namespace ZVision diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk index 6734fde6e2..872b48f775 100644 --- a/engines/zvision/module.mk +++ b/engines/zvision/module.mk @@ -13,6 +13,9 @@ MODULE_OBJS := \ cursors/cursor.o \ detection.o \ fonts/truetype_font.o \ + graphics/effects/fog.o \ + graphics/effects/light.o \ + graphics/effects/wave.o \ graphics/render_manager.o \ graphics/render_table.o \ scripting/actions.o \ @@ -33,6 +36,7 @@ MODULE_OBJS := \ scripting/sidefx.o \ scripting/sidefx/animation_node.o \ scripting/sidefx/music_node.o \ + scripting/sidefx/region_node.o \ scripting/sidefx/syncsound_node.o \ scripting/sidefx/timer_node.o \ scripting/sidefx/ttytext_node.o \ diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp index 399a81d898..839eb1f92c 100644 --- a/engines/zvision/scripting/actions.cpp +++ b/engines/zvision/scripting/actions.cpp @@ -34,7 +34,13 @@ #include "zvision/scripting/sidefx/syncsound_node.h" #include "zvision/scripting/sidefx/animation_node.h" #include "zvision/scripting/sidefx/ttytext_node.h" +#include "zvision/scripting/sidefx/region_node.h" #include "zvision/scripting/controls/titler_control.h" +#include "zvision/graphics/render_table.h" +#include "zvision/graphics/effect.h" +#include "zvision/graphics/effects/fog.h" +#include "zvision/graphics/effects/light.h" +#include "zvision/graphics/effects/wave.h" #include "common/file.h" @@ -476,6 +482,80 @@ bool ActionQuit::execute() { return true; } +////////////////////////////////////////////////////////////////////////////// +// ActionRegion +////////////////////////////////////////////////////////////////////////////// + +ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) : + ResultAction(engine, slotkey) { + + char art[64]; + char custom[64]; + + int32 x1, x2, y1, y2; + + sscanf(line.c_str(), "%s %d %d %d %d %hu %hu %hu %hu %s", art, &x1, &y1, &x2, &y2, &_delay, &_type, &_unk1, &_unk2, custom); + _art = Common::String(art); + _custom = Common::String(custom); + _rect = Common::Rect(x1, y1, x2 + 1, y2 + 1); +} + +ActionRegion::~ActionRegion() { + _engine->getScriptManager()->killSideFx(_slotkey); +} + +bool ActionRegion::execute() { + if (_engine->getScriptManager()->getSideFX(_slotkey)) + return true; + + Effect *effct = NULL; + switch (_type) { + case 0: { + uint16 s_x, s_y, frames; + double amplitude, waveln, speed; + sscanf(_custom.c_str(), "%hu,%hu,%hu,%lf,%lf,%lf,", &s_x, &s_y, &frames, &litude, &waveln, &speed); + effct = new WaveFx(_engine, _slotkey, _rect, _unk1, frames, s_x, s_y, amplitude, waveln, speed); + } + break; + case 1: { + uint16 aX, aY, aD; + if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) + sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aY, &aX, &aD); + else + sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aX, &aY, &aD); + int8 minD; + int8 maxD; + EffectMap *_map = _engine->getRenderManager()->makeEffectMap(Common::Point(aX, aY), aD, _rect, &minD, &maxD); + effct = new LightFx(_engine, _slotkey, _rect, _unk1, _map, atoi(_custom.c_str()), minD, maxD); + } + break; + case 9: { + int16 dum1; + int32 dum2; + char buf[64]; + sscanf(_custom.c_str(), "%hd,%d,%s", &dum1, &dum2, buf); + Graphics::Surface tempMask; + _engine->getRenderManager()->readImageToSurface(_art, tempMask); + if (_rect.width() != tempMask.w) + _rect.setWidth(tempMask.w); + if (_rect.height() != tempMask.h) + _rect.setHeight(tempMask.h); + + EffectMap *_map = _engine->getRenderManager()->makeEffectMap(tempMask, 0); + effct = new FogFx(_engine, _slotkey, _rect, _unk1, _map, Common::String(buf)); + } + break; + default: + break; + } + + if (effct) { + _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotkey, effct, _delay)); + _engine->getRenderManager()->addEffect(effct); + } + + return true; +} ////////////////////////////////////////////////////////////////////////////// // ActionRandom diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h index de303a7b1b..5e34f6eaf0 100644 --- a/engines/zvision/scripting/actions.h +++ b/engines/zvision/scripting/actions.h @@ -317,6 +317,22 @@ public: bool execute(); }; +class ActionRegion : public ResultAction { +public: + ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line); + ~ActionRegion(); + bool execute(); + +private: + Common::String _art; + Common::String _custom; + Common::Rect _rect; + uint16 _delay; + uint16 _type; + uint16 _unk1; + uint16 _unk2; +}; + // TODO: See if this exists in ZGI. It doesn't in ZNem class ActionUnloadAnimation : public ResultAction { public: diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp index 04378f856f..8140d09a6a 100644 --- a/engines/zvision/scripting/scr_file_handling.cpp +++ b/engines/zvision/scripting/scr_file_handling.cpp @@ -266,7 +266,7 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis } else if (act.matchString("random", true)) { actionList.push_back(new ActionRandom(_engine, slot, args)); } else if (act.matchString("region", true)) { - // TODO: Implement ActionRegion + actionList.push_back(new ActionRegion(_engine, slot, args)); } else if (act.matchString("restore_game", true)) { // TODO: Implement ActionRestoreGame } else if (act.matchString("rotate_to", true)) { diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h index 4d82f36aea..219cff9f45 100644 --- a/engines/zvision/scripting/script_manager.h +++ b/engines/zvision/scripting/script_manager.h @@ -87,9 +87,9 @@ enum StateKey { StateKey_DebugCheats = 74, StateKey_JapanFonts = 75, StateKey_Brightness = 77, - StateKey_EF9_B = 91, + StateKey_EF9_R = 91, StateKey_EF9_G = 92, - StateKey_EF9_R = 93, + StateKey_EF9_B = 93, StateKey_EF9_Speed = 94, StateKey_Inv_Cnt_Slot = 100, StateKey_Inv_1_Slot = 101, diff --git a/engines/zvision/scripting/sidefx/region_node.cpp b/engines/zvision/scripting/sidefx/region_node.cpp new file mode 100644 index 0000000000..de613d8af2 --- /dev/null +++ b/engines/zvision/scripting/sidefx/region_node.cpp @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" + +#include "zvision/scripting/sidefx/region_node.h" + +#include "zvision/zvision.h" +#include "zvision/scripting/script_manager.h" +#include "zvision/graphics/render_manager.h" + +namespace ZVision { + +RegionNode::RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay) + : SideFX(engine, key, SIDEFX_REGION) { + _effect = effect; + _delay = delay; + _timeLeft = 0; +} + +RegionNode::~RegionNode() { + _engine->getRenderManager()->deleteEffect(_key); +} + +bool RegionNode::process(uint32 deltaTimeInMillis) { + _timeLeft -= deltaTimeInMillis; + + if (_timeLeft <= 0) { + _timeLeft = _delay; + if (_effect) + _effect->update(); + } + + return false; +} + +} // End of namespace ZVision diff --git a/engines/zvision/scripting/sidefx/region_node.h b/engines/zvision/scripting/sidefx/region_node.h new file mode 100644 index 0000000000..ec716b6e3e --- /dev/null +++ b/engines/zvision/scripting/sidefx/region_node.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. + * + */ + +#ifndef ZVISION_REGION_NODE_H +#define ZVISION_REGION_NODE_H + +#include "graphics/surface.h" + +#include "zvision/scripting/sidefx.h" +#include "zvision/graphics/effect.h" + +namespace ZVision { + +class ZVision; + +class RegionNode : public SideFX { +public: + RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay); + ~RegionNode(); + + /** + * Decrement the timer by the delta time. If the timer is finished, set the status + * in _globalState and let this node be deleted + * + * @param deltaTimeInMillis The number of milliseconds that have passed since last frame + * @return If true, the node can be deleted after process() finishes + */ + bool process(uint32 deltaTimeInMillis); + +private: + int32 _timeLeft; + uint32 _delay; + Effect *_effect; +}; + +} // End of namespace ZVision + +#endif |