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,304 @@
/* 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/file.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "video/video_decoder.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/fist_control.h"
#include "zvision/video/rlf_decoder.h"
namespace ZVision {
FistControl::FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_FIST) {
_cursor = CursorIndex_Idle;
_animation = NULL;
_soundKey = 0;
_fiststatus = 0;
_order = 0;
_fistnum = 0;
_animationId = 0;
clearFistArray(_fistsUp);
clearFistArray(_fistsDwn);
_numEntries = 0;
_entries.clear();
_anmRect = Common::Rect();
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("sound_key", true)) {
_soundKey = atoi(values.c_str());
} else if (param.matchString("cursor", true)) {
_cursor = _engine->getCursorManager()->getCursorId(values);
} else if (param.matchString("descfile", true)) {
readDescFile(Common::Path(values));
} else if (param.matchString("animation_id", true)) {
_animationId = atoi(values.c_str());
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
}
FistControl::~FistControl() {
if (_animation)
delete _animation;
clearFistArray(_fistsUp);
clearFistArray(_fistsDwn);
_entries.clear();
}
bool FistControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_animation && _animation->isPlaying()) {
if (_animation->endOfVideo()) {
_animation->stop();
_engine->getScriptManager()->setStateValue(_animationId, 2);
return false;
}
if (_animation->needsUpdate()) {
const Graphics::Surface *frameData = _animation->decodeNextFrame();
if (frameData)
// WORKAROUND: Ignore the target frame dimensions for the finger animations.
// The target dimensions specify an area smaller than expected, thus if we
// scale the finger videos to fit these dimensions, they are not aligned
// correctly. Not scaling these videos yields a result identical to the
// original. Fixes bug #6784.
_engine->getRenderManager()->blitSurfaceToBkg(*frameData, _anmRect.left, _anmRect.top);
}
}
return false;
}
bool FistControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (mouseIn(screenSpacePos, backgroundImageSpacePos) >= 0) {
_engine->getCursorManager()->changeCursor(_cursor);
return true;
}
return false;
}
bool FistControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
int fistNumber = mouseIn(screenSpacePos, backgroundImageSpacePos);
if (fistNumber >= 0) {
setVenus();
uint32 oldStatus = _fiststatus;
_fiststatus ^= (1 << fistNumber);
for (int i = 0; i < _numEntries; i++)
if (_entries[i]._bitsStrt == oldStatus && _entries[i]._bitsEnd == _fiststatus) {
if (_animation) {
_animation->stop();
_animation->seekToFrame(_entries[i]._anmStrt);
_animation->setEndFrame(_entries[i]._anmEnd);
_animation->start();
}
_engine->getScriptManager()->setStateValue(_animationId, 1);
_engine->getScriptManager()->setStateValue(_soundKey, _entries[i]._sound);
break;
}
_engine->getScriptManager()->setStateValue(_key, _fiststatus);
}
return false;
}
void FistControl::readDescFile(const Common::Path &fileName) {
Common::File file;
if (!file.open(fileName)) {
warning("Desc file %s could could be opened", fileName.toString().c_str());
return;
}
Common::String line;
Common::String param;
Common::String values;
while (!file.eos()) {
line = file.readLine();
getFistParams(line, param, values);
if (param.matchString("animation_id", true)) {
// Not used
} else if (param.matchString("animation", true)) {
_animation = _engine->loadAnimation(Common::Path(values));
} else if (param.matchString("anim_rect", true)) {
int left, top, right, bottom;
if (sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom) == 4)
_anmRect = Common::Rect(left, top, right, bottom);
} else if (param.matchString("num_fingers", true)) {
if (sscanf(values.c_str(), "%d", &_fistnum) == 1) {
_fistsUp.resize(_fistnum);
_fistsDwn.resize(_fistnum);
}
} else if (param.matchString("entries", true)) {
if (sscanf(values.c_str(), "%d", &_numEntries) == 1)
_entries.resize(_numEntries);
} else if (param.matchString("eval_order_ascending", true)) {
sscanf(values.c_str(), "%d", &_order);
} else if (param.matchString("up_hs_num_*", true)) {
int fist, num;
num = atoi(values.c_str());
if (sscanf(param.c_str(), "up_hs_num_%d", &fist) == 1)
_fistsUp[fist].resize(num);
} else if (param.matchString("up_hs_*", true)) {
int16 fist, box, x1, y1, x2, y2;
if (sscanf(param.c_str(), "up_hs_%hd_%hd", &fist, &box) == 2) {
if (sscanf(values.c_str(), "%hd %hd %hd %hd", &x1, &y1, &x2, &y2) == 4)
(_fistsUp[fist])[box] = Common::Rect(x1, y1, x2, y2);
}
} else if (param.matchString("down_hs_num_*", true)) {
int fist, num;
num = atoi(values.c_str());
if (sscanf(param.c_str(), "down_hs_num_%d", &fist) == 1)
_fistsDwn[fist].resize(num);
} else if (param.matchString("down_hs_*", true)) {
int16 fist, box, x1, y1, x2, y2;
if (sscanf(param.c_str(), "down_hs_%hd_%hd", &fist, &box) == 2) {
if (sscanf(values.c_str(), "%hd %hd %hd %hd", &x1, &y1, &x2, &y2) == 4)
(_fistsDwn[fist])[box] = Common::Rect(x1, y1, x2, y2);
}
} else {
int entry, start, end, sound;
char bitsStart[33];
char bitsEnd[33];
entry = atoi(param.c_str());
if (sscanf(values.c_str(), "%s %s %d %d (%d)", bitsStart, bitsEnd, &start, &end, &sound) == 5) {
_entries[entry]._bitsStrt = readBits(bitsStart);
_entries[entry]._bitsEnd = readBits(bitsEnd);
_entries[entry]._anmStrt = start;
_entries[entry]._anmEnd = end;
_entries[entry]._sound = sound;
}
}
}
file.close();
}
void FistControl::clearFistArray(Common::Array< Common::Array<Common::Rect> > &arr) {
for (uint i = 0; i < arr.size(); i++)
arr[i].clear();
arr.clear();
}
uint32 FistControl::readBits(const char *str) {
uint32 bfield = 0;
int len = strlen(str);
for (int i = 0; i < len; i++)
if (str[i] != '0')
bfield |= (1 << i);
return bfield;
}
int FistControl::mouseIn(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_order) {
for (int i = 0; i < _fistnum; i++) {
if (((_fiststatus >> i) & 1) == 1) {
for (uint j = 0; j < _fistsDwn[i].size(); j++)
if ((_fistsDwn[i])[j].contains(backgroundImageSpacePos))
return i;
} else {
for (uint j = 0; j < _fistsUp[i].size(); j++)
if ((_fistsUp[i])[j].contains(backgroundImageSpacePos))
return i;
}
}
} else {
for (int i = _fistnum - 1; i >= 0; i--) {
if (((_fiststatus >> i) & 1) == 1) {
for (uint j = 0; j < _fistsDwn[i].size(); j++)
if ((_fistsDwn[i])[j].contains(backgroundImageSpacePos))
return i;
} else {
for (uint j = 0; j < _fistsUp[i].size(); j++)
if ((_fistsUp[i])[j].contains(backgroundImageSpacePos))
return i;
}
}
}
return -1;
}
void FistControl::getFistParams(const Common::String &inputStr, Common::String &parameter, Common::String &values) {
const char *chrs = inputStr.c_str();
uint lbr;
for (lbr = 0; lbr < inputStr.size(); lbr++)
if (chrs[lbr] == ':')
break;
if (lbr >= inputStr.size())
return;
uint rbr;
for (rbr = lbr + 1; rbr < inputStr.size(); rbr++)
if (chrs[rbr] == '~')
break;
if (rbr >= inputStr.size())
return;
parameter = Common::String(chrs, chrs + lbr);
values = Common::String(chrs + lbr + 1, chrs + rbr);
}
} // End of namespace ZVision

View File

@@ -0,0 +1,82 @@
/* 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 ZVISION_FIST_CONTROL_H
#define ZVISION_FIST_CONTROL_H
#include "common/array.h"
#include "common/rect.h"
#include "zvision/scripting/control.h"
namespace Video {
class VideoDecoder;
}
namespace ZVision {
// Only used in Zork Nemesis, handles the door lock puzzle with the skeletal fingers (td9e)
class FistControl : public Control {
public:
FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~FistControl() override;
private:
uint32 _fiststatus;
int _fistnum;
int16 _cursor;
int _order;
Common::Array< Common::Array<Common::Rect> > _fistsUp;
Common::Array< Common::Array<Common::Rect> > _fistsDwn;
int32 _numEntries;
struct entries {
uint32 _bitsStrt;
uint32 _bitsEnd;
int32 _anmStrt;
int32 _anmEnd;
int32 _sound;
};
Common::Array<entries> _entries;
Video::VideoDecoder *_animation;
Common::Rect _anmRect;
int32 _soundKey;
int32 _animationId;
public:
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override;
private:
void readDescFile(const Common::Path &fileName);
void clearFistArray(Common::Array< Common::Array<Common::Rect> > &arr);
uint32 readBits(const char *str);
int mouseIn(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
void getFistParams(const Common::String &inputStr, Common::String &parameter, Common::String &values);
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,184 @@
/* 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/file.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "video/video_decoder.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/hotmov_control.h"
namespace ZVision {
HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_HOTMOV) {
_animation = NULL;
_cycle = 0;
_frames.clear();
_cyclesCount = 0;
_framesCount = 0;
_engine->getScriptManager()->setStateValue(_key, 0);
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("hs_frame_list", true)) {
readHsFile(Common::Path(values));
} else if (param.matchString("rectangle", true)) {
int x;
int y;
int width;
int height;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height) == 4)
_rectangle = Common::Rect(x, y, width, height);
} else if (param.matchString("num_frames", true)) {
_framesCount = atoi(values.c_str());
} else if (param.matchString("num_cycles", true)) {
_cyclesCount = atoi(values.c_str());
} else if (param.matchString("animation", true)) {
char filename[64];
if (sscanf(values.c_str(), "%s", filename) == 1) {
values = Common::String(filename);
_animation = _engine->loadAnimation(Common::Path(values));
_animation->start();
}
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
}
HotMovControl::~HotMovControl() {
if (_animation)
delete _animation;
_frames.clear();
}
bool HotMovControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_cycle < _cyclesCount) {
if (_animation && _animation->endOfVideo()) {
_cycle++;
if (_cycle == _cyclesCount) {
_engine->getScriptManager()->setStateValue(_key, 2);
return false;
}
_animation->rewind();
}
if (_animation && _animation->needsUpdate()) {
const Graphics::Surface *frameData = _animation->decodeNextFrame();
if (frameData)
_engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _rectangle);
}
}
return false;
}
bool HotMovControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (!_animation)
return false;
if (_cycle < _cyclesCount) {
if (_frames[_animation->getCurFrame()].contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(CursorIndex_Active);
return true;
}
}
return false;
}
bool HotMovControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (!_animation)
return false;
if (_cycle < _cyclesCount) {
if (_frames[_animation->getCurFrame()].contains(backgroundImageSpacePos)) {
setVenus();
_engine->getScriptManager()->setStateValue(_key, 1);
return true;
}
}
return false;
}
void HotMovControl::readHsFile(const Common::Path &fileName) {
if (_framesCount == 0)
return;
Common::File file;
if (!file.open(fileName)) {
warning("HS file %s could could be opened", fileName.toString().c_str());
return;
}
Common::String line;
_frames.resize(_framesCount);
while (!file.eos()) {
line = file.readLine();
int frame;
int x;
int y;
int width;
int height;
if (sscanf(line.c_str(), "%d:%d %d %d %d~", &frame, &x, &y, &width, &height) == 5) {
if (frame >= 0 && frame < _framesCount)
_frames[frame] = Common::Rect(x, y, width, height);
}
}
file.close();
}
} // End of namespace ZVision

View File

@@ -0,0 +1,60 @@
/* 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 ZVISION_HOTMOV_CONTROL_H
#define ZVISION_HOTMOV_CONTROL_H
#include "common/array.h"
#include "common/path.h"
#include "common/rect.h"
#include "zvision/scripting/control.h"
namespace Video {
class VideoDecoder;
}
namespace ZVision {
// Only used in Zork Nemesis, handles movies where the player needs to click on something (mj7g, vw3g)
class HotMovControl : public Control {
public:
HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~HotMovControl() override;
private:
int32 _framesCount;
int32 _cycle;
int32 _cyclesCount;
Video::VideoDecoder *_animation;
Common::Rect _rectangle;
Common::Array<Common::Rect> _frames;
public:
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override;
private:
void readHsFile(const Common::Path &fileName);
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,271 @@
/* 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 "backends/keymapper/keymap.h"
#include "common/rect.h"
#include "common/scummsys.h"
#include "common/str.h"
#include "common/stream.h"
#include "common/system.h"
#include "video/video_decoder.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/input_control.h"
#include "zvision/text/string_manager.h"
namespace ZVision {
InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_INPUT),
_background(0),
_nextTabstop(0),
_focused(false),
_textChanged(false),
_enterPressed(false),
_readOnly(false),
_txtWidth(0),
_animation(NULL) {
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("rectangle", true)) {
int x1, y1, x2, y2;
if (sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2) == 4)
_textRectangle = Common::Rect(x1, y1, x2, y2);
} else if (param.matchString("aux_hotspot", true)) {
int x1, y1, x2, y2;
if (sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2) == 4)
_headerRectangle = Common::Rect(x1, y1, x2, y2);
} else if (param.matchString("string_init", true)) {
uint fontFormatNumber;
if (sscanf(values.c_str(), "%u", &fontFormatNumber) == 1)
_stringInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber));
} else if (param.matchString("chooser_init_string", true)) {
uint fontFormatNumber;
if (sscanf(values.c_str(), "%u", &fontFormatNumber) == 1)
_stringChooserInit.readAllStyles(_engine->getStringManager()->getTextLine(fontFormatNumber));
} else if (param.matchString("next_tabstop", true)) {
sscanf(values.c_str(), "%u", &_nextTabstop);
} else if (param.matchString("cursor_dimensions", true)) {
// Ignore, use the dimensions in the animation file
} else if (param.matchString("cursor_animation_frames", true)) {
// Ignore, use the frame count in the animation file
} else if (param.matchString("cursor_animation", true)) {
char fileName[25];
if (sscanf(values.c_str(), "%24s %*u", fileName) == 1) {
_animation = _engine->loadAnimation(fileName);
_animation->start();
}
} else if (param.matchString("focus", true)) {
_focused = true;
_engine->getScriptManager()->setFocusControlKey(_key);
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
_maxTxtWidth = _textRectangle.width();
if (_animation)
_maxTxtWidth -= _animation->getWidth();
}
InputControl::~InputControl() {
_background->free();
delete _background;
unfocus();
}
void InputControl::focus() {
if (!_readOnly) {
_engine->getGameKeymap()->setEnabled(false);
}
_focused = true;
_textChanged = true;
}
void InputControl::unfocus() {
if (!_readOnly) {
_engine->getGameKeymap()->setEnabled(true);
}
_focused = false;
_textChanged = true;
}
bool InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_textRectangle.contains(backgroundImageSpacePos)) {
if (!_readOnly) {
// Save
_engine->getScriptManager()->focusControl(_key);
setVenus();
} else {
// Restore
if (_currentInputText.size()) {
setVenus();
_enterPressed = true;
}
}
}
return false;
}
bool InputControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_textRectangle.contains(backgroundImageSpacePos)) {
if (!_readOnly) {
// Save
_engine->getCursorManager()->changeCursor(CursorIndex_Active);
return true;
} else {
// Restore
if (_currentInputText.size()) {
_engine->getCursorManager()->changeCursor(CursorIndex_Active);
_engine->getScriptManager()->focusControl(_key);
return true;
}
}
}
return false;
}
bool InputControl::onKeyDown(Common::KeyState keyState) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (!_focused) {
return false;
}
if (keyState.keycode == Common::KEYCODE_BACKSPACE) {
if (!_readOnly) {
_currentInputText.deleteLastChar();
_textChanged = true;
}
} else if (keyState.keycode == Common::KEYCODE_RETURN) {
_enterPressed = true;
} else if (keyState.keycode == Common::KEYCODE_TAB) {
unfocus();
// Focus the next input control
_engine->getScriptManager()->focusControl(_nextTabstop);
// Don't process this event for other controls
return true;
} else {
if (!_readOnly) {
// Otherwise, append the new character to the end of the current text
uint16 asciiValue = keyState.ascii;
// We only care about text values
if (asciiValue >= 32 && asciiValue <= 126) {
_currentInputText += (char)asciiValue;
_textChanged = true;
}
}
}
return false;
}
bool InputControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (!_background) {
_background = _engine->getRenderManager()->getBkgRect(_textRectangle);
}
// First see if we need to render the text
if (_textChanged) {
// Blit the text using the RenderManager
Graphics::Surface txt;
txt.copyFrom(*_background);
int32 oldTxtWidth = _txtWidth;
if (!_readOnly || !_focused)
_txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringInit, txt);
else
_txtWidth = _engine->getTextRenderer()->drawText(_currentInputText, _stringChooserInit, txt);
if (_readOnly || _txtWidth <= _maxTxtWidth)
_engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top);
else {
// Assume the last character caused the overflow.
_currentInputText.deleteLastChar();
_txtWidth = oldTxtWidth;
}
txt.free();
}
if (_animation && !_readOnly && _focused) {
if (_animation->endOfVideo())
_animation->rewind();
if (_animation->needsUpdate()) {
const Graphics::Surface *srf = _animation->decodeNextFrame();
int16 xx = _textRectangle.left + _txtWidth;
if (xx >= _textRectangle.left + (_textRectangle.width() - (int16)_animation->getWidth()))
xx = _textRectangle.left + _textRectangle.width() - (int16)_animation->getWidth();
_engine->getRenderManager()->blitSurfaceToBkg(*srf, xx, _textRectangle.top);
}
}
_textChanged = false;
return false;
}
bool InputControl::enterPress() {
if (_enterPressed) {
_enterPressed = false;
return true;
}
return false;
}
void InputControl::setText(const Common::String &_str) {
_currentInputText = _str;
_textChanged = true;
}
const Common::String InputControl::getText() {
return _currentInputText;
}
void InputControl::setReadOnly(bool readonly) {
_readOnly = readonly;
}
} // End of namespace ZVision

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/>.
*
*/
#ifndef ZVISION_INPUT_CONTROL_H
#define ZVISION_INPUT_CONTROL_H
#include "common/rect.h"
#include "zvision/scripting/control.h"
#include "zvision/text/string_manager.h"
#include "zvision/text/text.h"
namespace Video {
class VideoDecoder;
}
namespace ZVision {
class InputControl : public Control {
public:
InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~InputControl() override;
private:
Graphics::Surface *_background;
Common::Rect _textRectangle;
Common::Rect _headerRectangle;
TextStyleState _stringInit;
TextStyleState _stringChooserInit;
uint32 _nextTabstop;
bool _focused;
Common::String _currentInputText;
bool _textChanged;
bool _enterPressed;
bool _readOnly;
int16 _txtWidth;
int16 _maxTxtWidth;
Video::VideoDecoder *_animation;
public:
void focus() override;
void unfocus() override;
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onKeyDown(Common::KeyState keyState) override;
bool process(uint32 deltaTimeInMillis) override;
void setText(const Common::String &_str);
const Common::String getText();
bool enterPress();
void setReadOnly(bool);
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,352 @@
/* 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 "common/file.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/system.h"
#include "common/tokenizer.h"
#include "graphics/surface.h"
#include "video/video_decoder.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/lever_control.h"
namespace ZVision {
LeverControl::LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_LEVER),
_frameInfo(0),
_frameCount(0),
_startFrame(0),
_currentFrame(0),
_lastRenderedFrame(0),
_mouseIsCaptured(false),
_isReturning(false),
_accumulatedTime(0),
_returnRoutesCurrentFrame(0),
_animation(NULL),
_cursor(CursorIndex_Active),
_mirrored(false) {
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("descfile", true)) {
char levFileName[25];
if (sscanf(values.c_str(), "%24s", levFileName) == 1)
parseLevFile(levFileName);
} else if (param.matchString("cursor", true)) {
char cursorName[25];
if (sscanf(values.c_str(), "%24s", cursorName) == 1)
_cursor = _engine->getCursorManager()->getCursorId(Common::String(cursorName));
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
renderFrame(_currentFrame);
}
LeverControl::~LeverControl() {
if (_animation)
delete _animation;
delete[] _frameInfo;
}
void LeverControl::parseLevFile(const Common::Path &fileName) {
debugC(2, kDebugControl, "LeverControl::parseLevFile(%s)", fileName.toString().c_str());
Common::File file;
if (!file.open(fileName)) {
warning("LEV file %s could could be opened", fileName.toString().c_str());
return;
}
Common::String line;
Common::String param;
Common::String values;
int id = 0;
while (!file.eos()) {
line = file.readLine();
getLevParams(line, param, values);
if (param.matchString("animation_id", true)) {
sscanf(values.c_str(), "%d", &id);
debugC(2, kDebugControl, "Lever animation ID: %d", id);
} else if (param.matchString("filename", true)) {
_animation = _engine->loadAnimation(Common::Path(values));
} else if (param.matchString("skipcolor", true)) {
// Not used
} else if (param.matchString("anim_coords", true)) {
int left, top, right, bottom;
if (sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom) == 4) {
_animationCoords.left = left;
_animationCoords.top = top;
_animationCoords.right = right;
_animationCoords.bottom = bottom;
}
} else if (param.matchString("mirrored", true)) {
uint mirrored;
if (sscanf(values.c_str(), "%u", &mirrored) == 1)
_mirrored = mirrored == 0 ? false : true;
} else if (param.matchString("frames", true)) {
if (sscanf(values.c_str(), "%u", &_frameCount) == 1)
_frameInfo = new FrameInfo[_frameCount];
} else if (param.matchString("elsewhere", true)) {
// Not used
} else if (param.matchString("out_of_control", true)) {
// Not used
} else if (param.matchString("start_pos", true)) {
if (sscanf(values.c_str(), "%u", &_startFrame) == 1)
_currentFrame = _startFrame;
} else if (param.matchString("hotspot_deltas", true)) {
uint x;
uint y;
if (sscanf(values.c_str(), "%u %u", &x, &y) == 2) {
_hotspotDelta.x = x;
_hotspotDelta.y = y;
}
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
} else {
uint frameNumber;
uint x, y;
line.toLowercase();
if (sscanf(line.c_str(), "%u:%u %u", &frameNumber, &x, &y) == 3) {
_frameInfo[frameNumber].hotspot.left = x;
_frameInfo[frameNumber].hotspot.top = y;
_frameInfo[frameNumber].hotspot.right = x + _hotspotDelta.x;
_frameInfo[frameNumber].hotspot.bottom = y + _hotspotDelta.y;
}
Common::StringTokenizer tokenizer(line, " ^=()~");
tokenizer.nextToken();
tokenizer.nextToken();
Common::String token = tokenizer.nextToken();
while (!tokenizer.empty()) {
if (token == "d") {
token = tokenizer.nextToken();
uint angle;
uint toFrame;
if (sscanf(token.c_str(), "%u,%u", &toFrame, &angle) == 2)
_frameInfo[frameNumber].paths.push_back(PathSegment(angle, toFrame));
} else if (token.hasPrefix("p")) {
// Format: P(<from> to <to>)
tokenizer.nextToken();
tokenizer.nextToken();
token = tokenizer.nextToken();
uint to = atoi(token.c_str());
_frameInfo[frameNumber].returnRoute.push_back(to);
}
token = tokenizer.nextToken();
}
}
// Don't read lines in this place because last will not be parsed.
}
// WORKAROUND for a script bug in Zork: Nemesis, room tz2e (orrery)
// Animation coordinates for left hand lever do not properly align with background image
switch (id) {
case 2926:
_animationCoords.bottom -= 4;
_animationCoords.right += 1;
_animationCoords.left -= 1;
_animationCoords.top += 1;
break;
default:
break;
}
// Cycle through all unit direction vectors in path segments & determine step distance
debugC(3, kDebugControl, "Setting step distances");
for (uint frame=0; frame < _frameCount; frame++) {
debugC(3, kDebugControl, "Frame %d", frame);
for (auto &iter : _frameInfo[frame].paths) {
uint destFrame = iter.toFrame;
Common::Point deltaPos = _frameInfo[destFrame].hotspot.origin() - _frameInfo[frame].hotspot.origin();
Math::Vector2d deltaPosVector((float)deltaPos.x, (float)deltaPos.y);
iter.distance *= deltaPosVector.getMagnitude();
debugC(3, kDebugControl, "\tdeltaPos = %d,%d, Distance %f", deltaPos.x, deltaPos.y, iter.distance);
}
}
debugC(2, kDebugControl, "LeverControl::~parseLevFile()");
}
bool LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
setVenus();
_mouseIsCaptured = true;
_gripOffset = backgroundImageSpacePos - _frameInfo[_currentFrame].hotspot.origin();
}
return false;
}
bool LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_mouseIsCaptured) {
_mouseIsCaptured = false;
_engine->getScriptManager()->setStateValue(_key, _currentFrame);
_isReturning = true;
_returnRoutesCurrentProgress = _frameInfo[_currentFrame].returnRoute.begin();
_returnRoutesCurrentFrame = _currentFrame;
}
_gripOffset = Common::Point(0,0);
return false;
}
bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
bool cursorWasChanged = false;
if (_mouseIsCaptured) {
uint nextFrame = _currentFrame;
do {
Common::Point gripOrigin = _frameInfo[_currentFrame].hotspot.origin() + _gripOffset;
debugC(1, kDebugControl, "LeverControl::onMouseMove() screenPos = %d,%d, imagePos = %d,%d, gripOrigin = %d,%d", screenSpacePos.x, screenSpacePos.y, backgroundImageSpacePos.x, backgroundImageSpacePos.y, gripOrigin.x, gripOrigin.y);
Common::Point deltaPos = backgroundImageSpacePos - gripOrigin;
nextFrame = getNextFrame(deltaPos);
if (nextFrame != _currentFrame) {
_currentFrame = nextFrame;
_engine->getScriptManager()->setStateValue(_key, _currentFrame);
}
} while (nextFrame != _currentFrame);
if (_lastRenderedFrame != _currentFrame)
renderFrame(_currentFrame);
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
} else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
}
return cursorWasChanged;
}
uint LeverControl::getNextFrame(Common::Point &deltaPos) {
Math::Vector2d movement((float)deltaPos.x, (float)deltaPos.y);
for (auto &iter : _frameInfo[_currentFrame].paths) {
debugC(1, kDebugControl, "\tPossible step = %f,%f, angle = %d, distance %f", iter.direction.getX(), iter.direction.getY(), (uint)Math::rad2deg(iter.angle), iter.distance);
if (movement.dotProduct(iter.direction) >= iter.distance/2) {
return iter.toFrame;
}
}
return _currentFrame;
}
bool LeverControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_isReturning) {
_accumulatedTime += deltaTimeInMillis;
while (_accumulatedTime >= _returnFramePeriod) {
_accumulatedTime -= _returnFramePeriod;
if (_returnRoutesCurrentFrame == *_returnRoutesCurrentProgress) {
_returnRoutesCurrentProgress++;
}
if (_returnRoutesCurrentProgress == _frameInfo[_currentFrame].returnRoute.end()) {
_isReturning = false;
_currentFrame = _returnRoutesCurrentFrame;
return false;
}
uint toFrame = *_returnRoutesCurrentProgress;
if (_returnRoutesCurrentFrame < toFrame) {
_returnRoutesCurrentFrame++;
} else if (_returnRoutesCurrentFrame > toFrame) {
_returnRoutesCurrentFrame--;
}
_engine->getScriptManager()->setStateValue(_key, _returnRoutesCurrentFrame);
renderFrame(_returnRoutesCurrentFrame);
}
}
return false;
}
void LeverControl::renderFrame(uint frameNumber) {
_lastRenderedFrame = frameNumber;
if (frameNumber != 0 && frameNumber < _lastRenderedFrame && _mirrored)
frameNumber = (_frameCount * 2) - frameNumber - 1;
const Graphics::Surface *frameData;
_animation->seekToFrame(frameNumber);
frameData = _animation->decodeNextFrame();
if (frameData)
_engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _animationCoords);
}
void LeverControl::getLevParams(const Common::String &inputStr, Common::String &parameter, Common::String &values) {
const char *chrs = inputStr.c_str();
uint lbr;
for (lbr = 0; lbr < inputStr.size(); lbr++)
if (chrs[lbr] == ':')
break;
if (lbr >= inputStr.size())
return;
uint rbr;
for (rbr = lbr + 1; rbr < inputStr.size(); rbr++)
if (chrs[rbr] == '~')
break;
if (rbr >= inputStr.size())
return;
parameter = Common::String(chrs, chrs + lbr);
values = Common::String(chrs + lbr + 1, chrs + rbr);
}
} // End of namespace ZVision

View File

@@ -0,0 +1,96 @@
/* 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 ZVISION_LEVER_CONTROL_H
#define ZVISION_LEVER_CONTROL_H
#include "common/list.h"
#include "common/path.h"
#include "common/rect.h"
#include "math/vector2d.h"
#include "zvision/scripting/control.h"
namespace Video {
class VideoDecoder;
}
namespace ZVision {
// Only used in Zork Nemesis, handles draggable levers (te2e, tm7e, tp2e, tt2e, tz2e)
class LeverControl : public Control {
public:
LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~LeverControl() override;
private:
struct PathSegment {
PathSegment(uint a, uint t) : angle(Math::deg2rad<float>(a)), toFrame(t), direction(cos(angle), -sin(angle)) {}
float angle; // Radians
uint toFrame;
Math::Vector2d direction; // NB unit vector upon initialisation
float distance = 1.0f;
};
struct FrameInfo {
Common::Rect hotspot;
Common::List<PathSegment> paths;
Common::List<uint> returnRoute;
};
private:
Video::VideoDecoder *_animation;
int _cursor;
Common::Rect _animationCoords;
bool _mirrored;
uint _frameCount;
uint _startFrame;
Common::Point _hotspotDelta;
FrameInfo *_frameInfo;
uint _currentFrame;
uint _lastRenderedFrame;
bool _mouseIsCaptured;
bool _isReturning;
Common::Point _gripOffset;
Common::List<uint>::iterator _returnRoutesCurrentProgress;
uint _returnRoutesCurrentFrame;
const uint8 _returnFramePeriod = 60; // milliseconds
uint32 _accumulatedTime;
public:
bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override;
private:
void parseLevFile(const Common::Path &fileName);
void renderFrame(uint frameNumber);
void getLevParams(const Common::String &inputStr, Common::String &parameter, Common::String &values);
uint getNextFrame(Common::Point &deltaPos);
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,216 @@
/* 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/scummsys.h"
#include "common/stream.h"
#include "zvision/zvision.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/paint_control.h"
namespace ZVision {
PaintControl::PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_PAINT) {
_cursor = CursorIndex_Active;
_paint = NULL;
_bkg = NULL;
_brush = NULL;
_colorKey = 0;
_mouseDown = false;
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("rectangle", true)) {
int x;
int y;
int width;
int height;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height) == 4)
_rectangle = Common::Rect(x, y, width + x, height + y);
} else if (param.matchString("cursor", true)) {
_cursor = _engine->getCursorManager()->getCursorId(values);
} else if (param.matchString("brush_file", true)) {
_brush = _engine->getRenderManager()->loadImage(Common::Path(values), false);
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
} else if (param.matchString("paint_file", true)) {
_paint = _engine->getRenderManager()->loadImage(Common::Path(values), false);
} else if (param.matchString("eligible_objects", true)) {
char buf[256];
memset(buf, 0, 256);
strncpy(buf, values.c_str(), 255);
char *curpos = buf;
char *strend = buf + strlen(buf);
while (true) {
char *st = curpos;
if (st >= strend)
break;
while (*curpos != ' ' && curpos < strend)
curpos++;
*curpos = 0;
curpos++;
int obj = atoi(st);
_eligibleObjects.push_back(obj);
}
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
if (_paint) {
_colorKey = _paint->format.RGBToColor(255, 0, 255);
_bkg = new Graphics::Surface;
_bkg->create(_rectangle.width(), _rectangle.height(), _paint->format);
_bkg->fillRect(Common::Rect(_rectangle.width(), _rectangle.height()), _colorKey);
Graphics::Surface *tmp = new Graphics::Surface;
tmp->create(_rectangle.width(), _rectangle.height(), _paint->format);
_engine->getRenderManager()->blitSurfaceToSurface(*_paint, _rectangle, *tmp, 0, 0);
_paint->free();
delete _paint;
_paint = tmp;
}
}
PaintControl::~PaintControl() {
// Clear the state value back to 0
//_engine->getScriptManager()->setStateValue(_key, 0);
if (_paint) {
_paint->free();
delete _paint;
}
if (_brush) {
_brush->free();
delete _brush;
}
if (_bkg) {
_bkg->free();
delete _bkg;
}
}
bool PaintControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
_mouseDown = false;
return false;
}
bool PaintControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_rectangle.contains(backgroundImageSpacePos)) {
int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
if (eligeblity(mouseItem)) {
setVenus();
_mouseDown = true;
}
}
return false;
}
bool PaintControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_rectangle.contains(backgroundImageSpacePos)) {
int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
if (eligeblity(mouseItem)) {
_engine->getCursorManager()->changeCursor(_cursor);
if (_mouseDown) {
Common::Rect bkgRect = paint(backgroundImageSpacePos);
if (!bkgRect.isEmpty()) {
Common::Rect imgRect = bkgRect;
imgRect.translate(-_rectangle.left, -_rectangle.top);
Graphics::Surface imgUpdate = _bkg->getSubArea(imgRect);
_engine->getRenderManager()->blitSurfaceToBkg(imgUpdate, bkgRect.left, bkgRect.top, _colorKey);
}
}
return true;
}
}
return false;
}
bool PaintControl::eligeblity(int itemId) {
for (Common::List<int>::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++)
if (*it == itemId)
return true;
return false;
}
Common::Rect PaintControl::paint(const Common::Point &point) {
Common::Rect paintRect = Common::Rect(_brush->w, _brush->h);
paintRect.moveTo(point);
paintRect.clip(_rectangle);
if (!paintRect.isEmpty()) {
Common::Rect brushRect = paintRect;
brushRect.translate(-point.x, -point.y);
Common::Rect bkgRect = paintRect;
bkgRect.translate(-_rectangle.left, -_rectangle.top);
for (int yy = 0; yy < brushRect.height(); yy++) {
uint16 *mask = (uint16 *)_brush->getBasePtr(brushRect.left, brushRect.top + yy);
uint16 *from = (uint16 *)_paint->getBasePtr(bkgRect.left, bkgRect.top + yy);
uint16 *to = (uint16 *)_bkg->getBasePtr(bkgRect.left, bkgRect.top + yy);
for (int xx = 0; xx < brushRect.width(); xx++) {
if (*mask != 0)
*(to + xx) = *(from + xx);
mask++;
}
}
}
return paintRect;
}
} // End of namespace ZVision

View File

@@ -0,0 +1,89 @@
/* 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 ZVISION_PAINT_CONTROL_H
#define ZVISION_PAINT_CONTROL_H
#include "common/list.h"
#include "common/rect.h"
#include "graphics/surface.h"
#include "zvision/scripting/control.h"
namespace ZVision {
// Only used in Zork Nemesis, handles the painting puzzle screen in Lucien's room in Irondune (ch4g)
class PaintControl : public Control {
public:
PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~PaintControl() override;
/**
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
/**
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
/**
* Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
*
* @param engine The base engine
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
* @return Was the cursor changed?
*/
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override {
return false;
};
private:
/**
* The area that will trigger the event
* This is in image space coordinates, NOT screen space
*/
uint32 _colorKey;
Graphics::Surface *_paint;
Graphics::Surface *_bkg;
Graphics::Surface *_brush;
Common::List<int> _eligibleObjects;
int _cursor;
Common::Rect _rectangle;
bool _mouseDown;
bool eligeblity(int itemId);
Common::Rect paint(const Common::Point &point);
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,142 @@
/* 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/scummsys.h"
#include "common/stream.h"
#include "zvision/zvision.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/push_toggle_control.h"
namespace ZVision {
PushToggleControl::PushToggleControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_PUSHTGL),
_countTo(2),
_cursor(CursorIndex_Active),
_event(Common::EVENT_LBUTTONUP) {
_hotspots.clear();
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("*_hotspot", true)) {
uint x;
uint y;
uint width;
uint height;
if (sscanf(values.c_str(), "%u,%u,%u,%u", &x, &y, &width, &height) == 4)
_hotspots.push_back(Common::Rect(x, y, x + width + 1, y + height + 1));
} else if (param.matchString("cursor", true)) {
_cursor = _engine->getCursorManager()->getCursorId(values);
} else if (param.matchString("animation", true)) {
// Not used
} else if (param.matchString("sound", true)) {
// Not used
} else if (param.matchString("count_to", true)) {
sscanf(values.c_str(), "%u", &_countTo);
} else if (param.matchString("mouse_event", true)) {
if (values.equalsIgnoreCase("up")) {
_event = Common::EVENT_LBUTTONUP;
} else if (values.equalsIgnoreCase("down")) {
_event = Common::EVENT_LBUTTONDOWN;
} else if (values.equalsIgnoreCase("double")) {
// Not used
}
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
if (_hotspots.size() == 0) {
warning("Push_toggle %u was parsed incorrectly", key);
}
}
PushToggleControl::~PushToggleControl() {
_hotspots.clear();
}
bool PushToggleControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_event != Common::EVENT_LBUTTONUP)
return false;
if (contain(backgroundImageSpacePos)) {
setVenus();
int32 val = _engine->getScriptManager()->getStateValue(_key);
val = (val + 1) % _countTo;
_engine->getScriptManager()->setStateValue(_key, val);
return true;
}
return false;
}
bool PushToggleControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_event != Common::EVENT_LBUTTONDOWN)
return false;
if (contain(backgroundImageSpacePos)) {
setVenus();
int32 val = _engine->getScriptManager()->getStateValue(_key);
val = (val + 1) % _countTo;
_engine->getScriptManager()->setStateValue(_key, val);
return true;
}
return false;
}
bool PushToggleControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (contain(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_cursor);
return true;
}
return false;
}
bool PushToggleControl::contain(const Common::Point &point) {
for (uint i = 0; i < _hotspots.size(); i++)
if (_hotspots[i].contains(point))
return true;
return false;
}
} // End of namespace ZVision

View File

@@ -0,0 +1,79 @@
/* 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 ZVISION_PUSH_TOGGLE_CONTROL_H
#define ZVISION_PUSH_TOGGLE_CONTROL_H
#include "common/array.h"
#include "common/events.h"
#include "common/rect.h"
#include "zvision/scripting/control.h"
namespace ZVision {
class PushToggleControl : public Control {
public:
PushToggleControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~PushToggleControl() override;
/**
* Called when LeftMouse is pushed. Default is NOP.
*
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
/**
* Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
*
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
/**
* Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
*
* @param engine The base engine
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
* @return Was the cursor changed?
*/
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
private:
/**
* The area that will trigger the event
* This is in image space coordinates, NOT screen space
*/
Common::Array<Common::Rect> _hotspots;
/** The cursor to use when hovering over _hotspot */
int _cursor;
/** Button maximal values count */
uint _countTo;
Common::EventType _event;
bool contain(const Common::Point &point);
};
} // End of namespace ZVision
#endif

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/file.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "common/system.h"
#include "common/tokenizer.h"
#include "graphics/surface.h"
#include "video/video_decoder.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/safe_control.h"
namespace ZVision {
SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_SAFE) {
_statesCount = 0;
_curState = 0;
_animation = NULL;
_innerRaduis = 0;
_innerRadiusSqr = 0;
_outerRadius = 0;
_outerRadiusSqr = 0;
_zeroPointer = 0;
_startPointer = 0;
_targetFrame = 0;
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("animation", true)) {
_animation = _engine->loadAnimation(Common::Path(values));
_animation->start();
} else if (param.matchString("rectangle", true)) {
int x;
int y;
int width;
int height;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height) == 4)
_rectangle = Common::Rect(x, y, width, height);
} else if (param.matchString("num_states", true)) {
_statesCount = atoi(values.c_str());
} else if (param.matchString("center", true)) {
int x;
int y;
if (sscanf(values.c_str(), "%d %d", &x, &y) == 2)
_center = Common::Point(x, y);
} else if (param.matchString("dial_inner_radius", true)) {
_innerRaduis = atoi(values.c_str());
_innerRadiusSqr = _innerRaduis * _innerRaduis;
} else if (param.matchString("radius", true)) {
_outerRadius = atoi(values.c_str());
_outerRadiusSqr = _outerRadius * _outerRadius;
} else if (param.matchString("zero_radians_offset", true)) {
_zeroPointer = atoi(values.c_str());
} else if (param.matchString("pointer_offset", true)) {
_startPointer = atoi(values.c_str());
_curState = _startPointer;
} else if (param.matchString("cursor", true)) {
// Not used
} else if (param.matchString("mirrored", true)) {
// Not used
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
if (_animation)
_animation->seekToFrame(_curState);
}
SafeControl::~SafeControl() {
if (_animation)
delete _animation;
}
bool SafeControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_animation && _animation->getCurFrame() != _targetFrame && _animation->needsUpdate()) {
// If we're past the target frame, move back one
if (_animation->getCurFrame() > _targetFrame)
_animation->seekToFrame(_animation->getCurFrame() - 1);
const Graphics::Surface *frameData = _animation->decodeNextFrame();
if (_animation->getCurFrame() == _targetFrame)
_engine->getScriptManager()->setStateValue(_key, _curState);
if (frameData)
_engine->getRenderManager()->blitSurfaceToBkg(*frameData, _rectangle.left, _rectangle.top);
}
return false;
}
bool SafeControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_rectangle.contains(backgroundImageSpacePos)) {
int32 mR = backgroundImageSpacePos.sqrDist(_center);
if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
_engine->getCursorManager()->changeCursor(CursorIndex_Active);
return true;
}
}
return false;
}
bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_rectangle.contains(backgroundImageSpacePos)) {
int32 mR = backgroundImageSpacePos.sqrDist(_center);
if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
setVenus();
Common::Point tmp = backgroundImageSpacePos - _center;
// Coverity complains about the order of arguments here,
// but changing that breaks the Zork Nemesis safe puzzle.
float dd = atan2((float)tmp.x, (float)tmp.y) * 57.29578;
int16 dp_state = 360 / _statesCount;
int16 m_state = (_statesCount - ((((int16)dd + 540) % 360) / dp_state)) % _statesCount;
int16 tmp2 = (m_state + _curState - _zeroPointer + _statesCount - 1) % _statesCount;
if (_animation)
_animation->seekToFrame((_curState + _statesCount - _startPointer) % _statesCount);
_curState = (_statesCount * 2 + tmp2) % _statesCount;
_targetFrame = (_curState + _statesCount - _startPointer) % _statesCount;
return true;
}
}
return false;
}
} // End of namespace ZVision

View File

@@ -0,0 +1,63 @@
/* 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 ZVISION_SAFE_CONTROL_H
#define ZVISION_SAFE_CONTROL_H
#include "common/list.h"
#include "common/rect.h"
#include "zvision/scripting/control.h"
namespace Video {
class VideoDecoder;
}
namespace ZVision {
// Only used in Zork Nemesis, handles the safe in the Asylum (ac4g)
class SafeControl : public Control {
public:
SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~SafeControl() override;
private:
int16 _statesCount;
int16 _curState;
Video::VideoDecoder *_animation;
Common::Point _center;
Common::Rect _rectangle;
int16 _innerRaduis;
int32 _innerRadiusSqr;
int16 _outerRadius;
int32 _outerRadiusSqr;
int16 _zeroPointer;
int16 _startPointer;
int16 _targetFrame;
public:
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override;
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,118 @@
/* 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/scummsys.h"
#include "common/str.h"
#include "common/stream.h"
#include "zvision/zvision.h"
#include "zvision/file/save_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/input_control.h"
#include "zvision/scripting/controls/save_control.h"
#include "zvision/text/string_manager.h"
#include "zvision/text/subtitle_manager.h"
namespace ZVision {
SaveControl::SaveControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_SAVE),
_saveControl(false) {
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("savebox", true)) {
int saveId;
int inputId;
if (sscanf(values.c_str(), "%d %d", &saveId, &inputId) == 2) {
saveElement elmnt;
elmnt.inputKey = inputId;
elmnt.saveId = saveId;
elmnt.exist = false;
_inputs.push_back(elmnt);
}
} else if (param.matchString("control_type", true)) {
if (values.contains("save"))
_saveControl = true;
else
_saveControl = false;
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
for (saveElmntList::iterator iter = _inputs.begin(); iter != _inputs.end(); ++iter) {
Control *ctrl = _engine->getScriptManager()->getControl(iter->inputKey);
if (ctrl && ctrl->getType() == Control::CONTROL_INPUT) {
InputControl *inp = (InputControl *)ctrl;
inp->setReadOnly(!_saveControl);
Common::SeekableReadStream *save = _engine->getSaveManager()->getSlotFile(iter->saveId);
if (save) {
SaveGameHeader header;
if (_engine->getSaveManager()->readSaveGameHeader(save, header)) {
inp->setText(header.saveName);
iter->exist = true;
}
delete save;
}
}
}
}
bool SaveControl::process(uint32 deltaTimeInMillis) {
for (saveElmntList::iterator iter = _inputs.begin(); iter != _inputs.end(); ++iter) {
Control *ctrl = _engine->getScriptManager()->getControl(iter->inputKey);
if (ctrl && ctrl->getType() == Control::CONTROL_INPUT) {
InputControl *inp = (InputControl *)ctrl;
if (inp->enterPress()) {
if (_saveControl) {
if (inp->getText().size() > 0) {
bool toSave = true;
if (iter->exist)
if (!_engine->getSubtitleManager()->askQuestion(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEXIST)))
toSave = false;
if (toSave) {
_engine->getSaveManager()->saveGame(iter->saveId, inp->getText(), true);
_engine->getSubtitleManager()->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000);
_engine->getScriptManager()->changeLocation(_engine->getScriptManager()->getLastMenuLocation());
}
} else {
_engine->getSubtitleManager()->timedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEMPTY), 2000);
}
} else {
_engine->getSaveManager()->loadGame(iter->saveId);
return true;
}
break;
}
}
}
return false;
}
} // End of namespace ZVision

View File

@@ -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 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 ZVISION_SAVE_CONTROL_H
#define ZVISION_SAVE_CONTROL_H
#include "common/list.h"
#include "zvision/scripting/control.h"
namespace ZVision {
class SaveControl : public Control {
public:
SaveControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
private:
struct saveElement {
int saveId;
int inputKey;
bool exist;
};
typedef Common::List<saveElement> saveElmntList;
saveElmntList _inputs;
bool _saveControl;
public:
bool process(uint32 deltaTimeInMillis) override;
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,213 @@
/* 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/scummsys.h"
#include "common/stream.h"
#include "zvision/zvision.h"
#include "zvision/graphics/cursors/cursor_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/slot_control.h"
namespace ZVision {
SlotControl::SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_SLOT),
_cursor(CursorIndex_Active),
_distanceId('0') {
_renderedItem = 0;
_bkg = NULL;
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("hotspot", true)) {
int x;
int y;
int width;
int height;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height) == 4)
_hotspot = Common::Rect(x, y, width, height);
} else if (param.matchString("rectangle", true)) {
int x;
int y;
int width;
int height;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height) == 4)
_rectangle = Common::Rect(x, y, width, height);
} else if (param.matchString("cursor", true)) {
_cursor = _engine->getCursorManager()->getCursorId(values);
} else if (param.matchString("distance_id", true)) {
sscanf(values.c_str(), "%c", &_distanceId);
} else if (param.matchString("venus_id", true)) {
_venusId = atoi(values.c_str());
} else if (param.matchString("eligible_objects", true)) {
char buf[256];
memset(buf, 0, 256);
strncpy(buf, values.c_str(), 255);
char *curpos = buf;
char *strend = buf + strlen(buf);
while (true) {
char *st = curpos;
if (st >= strend)
break;
while (*curpos != ' ' && curpos < strend)
curpos++;
*curpos = 0;
curpos++;
int obj = atoi(st);
_eligibleObjects.push_back(obj);
}
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
if (_hotspot.isEmpty() || _rectangle.isEmpty()) {
warning("Slot %u was parsed incorrectly", key);
}
}
SlotControl::~SlotControl() {
// Clear the state value back to 0
//_engine->getScriptManager()->setStateValue(_key, 0);
if (_bkg)
delete _bkg;
}
bool SlotControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_hotspot.contains(backgroundImageSpacePos)) {
setVenus();
int item = _engine->getScriptManager()->getStateValue(_key);
int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
if (item != 0) {
if (mouseItem != 0) {
if (eligeblity(mouseItem)) {
_engine->getScriptManager()->inventoryDrop(mouseItem);
_engine->getScriptManager()->inventoryAdd(item);
_engine->getScriptManager()->setStateValue(_key, mouseItem);
}
} else {
_engine->getScriptManager()->inventoryAdd(item);
_engine->getScriptManager()->setStateValue(_key, 0);
}
} else if (mouseItem == 0) {
if (eligeblity(0)) {
_engine->getScriptManager()->inventoryDrop(0);
_engine->getScriptManager()->setStateValue(_key, 0);
}
} else if (eligeblity(mouseItem)) {
_engine->getScriptManager()->setStateValue(_key, mouseItem);
_engine->getScriptManager()->inventoryDrop(mouseItem);
}
}
return false;
}
bool SlotControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_hotspot.contains(backgroundImageSpacePos)) {
_engine->getCursorManager()->changeCursor(_cursor);
return true;
}
return false;
}
bool SlotControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_engine->canRender()) {
int curItem = _engine->getScriptManager()->getStateValue(_key);
if (curItem != _renderedItem) {
if (_renderedItem != 0 && curItem == 0) {
_engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
_renderedItem = curItem;
} else {
if (_renderedItem == 0) {
if (_bkg)
delete _bkg;
_bkg = _engine->getRenderManager()->getBkgRect(_rectangle);
} else {
_engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
}
char buf[16];
if (_engine->getGameId() == GID_NEMESIS)
Common::sprintf_s(buf, "%d%cobj.tga", curItem, _distanceId);
else
Common::sprintf_s(buf, "g0z%cu%2.2x1.tga", _distanceId, curItem);
Graphics::Surface *srf = _engine->getRenderManager()->loadImage(buf);
int16 drawx = _rectangle.left;
int16 drawy = _rectangle.top;
if (_rectangle.width() > srf->w)
drawx = _rectangle.left + (_rectangle.width() - srf->w) / 2;
if (_rectangle.height() > srf->h)
drawy = _rectangle.top + (_rectangle.height() - srf->h) / 2;
_engine->getRenderManager()->blitSurfaceToBkg(*srf, drawx, drawy, 0);
delete srf;
_renderedItem = curItem;
}
}
}
return false;
}
bool SlotControl::eligeblity(int itemId) {
for (Common::List<int>::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++)
if (*it == itemId)
return true;
return false;
}
} // End of namespace ZVision

View File

@@ -0,0 +1,81 @@
/* 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 ZVISION_SLOT_CONTROL_H
#define ZVISION_SLOT_CONTROL_H
#include "common/list.h"
#include "common/rect.h"
#include "graphics/surface.h"
#include "zvision/scripting/control.h"
namespace ZVision {
class SlotControl : public Control {
public:
SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~SlotControl() override;
/**
* Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
*
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
/**
* Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
*
* @param engine The base engine
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
* @return Was the cursor changed?
*/
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) override;
bool process(uint32 deltaTimeInMillis) override;
private:
/**
* The area that will trigger the event
* This is in image space coordinates, NOT screen space
*/
Common::Rect _rectangle;
Common::Rect _hotspot;
int _cursor;
char _distanceId;
int _renderedItem;
Common::List<int> _eligibleObjects;
bool eligeblity(int itemId);
Graphics::Surface *_bkg;
/** The cursor to use when hovering over _hotspot */
Common::String _hoverCursor;
};
} // End of namespace ZVision
#endif

View File

@@ -0,0 +1,103 @@
/* 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/scummsys.h"
#include "common/stream.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/scripting/controls/titler_control.h"
#include "zvision/text/text.h"
namespace ZVision {
TitlerControl::TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
: Control(engine, key, CONTROL_TITLER) {
_surface = NULL;
_curString = -1;
// Loop until we find the closing brace
Common::String line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
Common::String param;
Common::String values;
getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
if (param.matchString("string_resource_file", true)) {
readStringsFile(Common::Path(values));
} else if (param.matchString("rectangle", true)) {
int x;
int y;
int x2;
int y2;
if (sscanf(values.c_str(), "%d %d %d %d", &x, &y, &x2, &y2) == 4)
_rectangle = Common::Rect(x, y, x2, y2);
}
line = stream.readLine();
_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
getParams(line, param, values);
}
if (!_rectangle.isEmpty()) {
_surface = new Graphics::Surface;
_surface->create(_rectangle.width(), _rectangle.height(), _engine->_resourcePixelFormat);
_surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
}
}
TitlerControl::~TitlerControl() {
if (_surface) {
_surface->free();
delete _surface;
}
}
void TitlerControl::setString(int strLine) {
if (strLine != _curString && strLine >= 0 && strLine < (int)_strings.size()) {
_surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
_engine->getTextRenderer()->drawTextWithWordWrapping(_strings[strLine], *_surface);
_engine->getRenderManager()->blitSurfaceToBkg(*_surface, _rectangle.left, _rectangle.top);
_curString = strLine;
}
}
void TitlerControl::readStringsFile(const Common::Path &fileName) {
Common::File file;
if (!file.open(fileName)) {
warning("String_resource_file %s could could be opened", fileName.toString().c_str());
return;
}
_strings.clear();
while (!file.eos()) {
Common::String line = readWideLine(file).encode();
_strings.push_back(line);
}
file.close();
}
} // End of namespace ZVision

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 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 ZVISION_TITLER_CONTROL_H
#define ZVISION_TITLER_CONTROL_H
#include "common/array.h"
#include "common/file.h"
#include "common/path.h"
#include "common/rect.h"
#include "common/stream.h"
#include "graphics/surface.h"
#include "zvision/scripting/control.h"
namespace ZVision {
// Only used in Zork Nemesis, handles the death screen with the Restore/Exit buttons
class TitlerControl : public Control {
public:
TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
~TitlerControl() override;
void setString(int strLine);
private:
Common::Array< Common::String > _strings;
Common::Rect _rectangle;
int16 _curString;
Graphics::Surface *_surface;
void readStringsFile(const Common::Path &fileName);
};
} // End of namespace ZVision
#endif