1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/scummsys.h"
24 
25 #include "zvision/scripting/controls/safe_control.h"
26 
27 #include "zvision/zvision.h"
28 #include "zvision/scripting/script_manager.h"
29 #include "zvision/graphics/render_manager.h"
30 #include "zvision/graphics/cursors/cursor_manager.h"
31 
32 #include "common/stream.h"
33 #include "common/file.h"
34 #include "common/tokenizer.h"
35 #include "common/system.h"
36 #include "graphics/surface.h"
37 #include "video/video_decoder.h"
38 
39 namespace ZVision {
40 
SafeControl(ZVision * engine,uint32 key,Common::SeekableReadStream & stream)41 SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
42 	: Control(engine, key, CONTROL_SAFE) {
43 	_statesCount = 0;
44 	_curState = 0;
45 	_animation = NULL;
46 	_innerRaduis = 0;
47 	_innerRadiusSqr = 0;
48 	_outerRadius = 0;
49 	_outerRadiusSqr = 0;
50 	_zeroPointer = 0;
51 	_startPointer = 0;
52 	_targetFrame = 0;
53 
54 	// Loop until we find the closing brace
55 	Common::String line = stream.readLine();
56 	_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
57 	Common::String param;
58 	Common::String values;
59 	getParams(line, param, values);
60 
61 	while (!stream.eos() && !line.contains('}')) {
62 		if (param.matchString("animation", true)) {
63 			_animation = _engine->loadAnimation(values);
64 			_animation->start();
65 		} else if (param.matchString("rectangle", true)) {
66 			int x;
67 			int y;
68 			int width;
69 			int height;
70 
71 			sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
72 
73 			_rectangle = Common::Rect(x, y, width, height);
74 		} else if (param.matchString("num_states", true)) {
75 			_statesCount = atoi(values.c_str());
76 		} else if (param.matchString("center", true)) {
77 			int x;
78 			int y;
79 
80 			sscanf(values.c_str(), "%d %d", &x, &y);
81 			_center = Common::Point(x, y);
82 		} else if (param.matchString("dial_inner_radius", true)) {
83 			_innerRaduis = atoi(values.c_str());
84 			_innerRadiusSqr = _innerRaduis * _innerRaduis;
85 		} else if (param.matchString("radius", true)) {
86 			_outerRadius = atoi(values.c_str());
87 			_outerRadiusSqr = _outerRadius * _outerRadius;
88 		} else if (param.matchString("zero_radians_offset", true)) {
89 			_zeroPointer = atoi(values.c_str());
90 		} else if (param.matchString("pointer_offset", true)) {
91 			_startPointer = atoi(values.c_str());
92 			_curState = _startPointer;
93 		} else if (param.matchString("cursor", true)) {
94 			// Not used
95 		} else if (param.matchString("mirrored", true)) {
96 			// Not used
97 		} else if (param.matchString("venus_id", true)) {
98 			_venusId = atoi(values.c_str());
99 		}
100 
101 		line = stream.readLine();
102 		_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
103 		getParams(line, param, values);
104 	}
105 
106 	if (_animation)
107 		_animation->seekToFrame(_curState);
108 }
109 
~SafeControl()110 SafeControl::~SafeControl() {
111 	if (_animation)
112 		delete _animation;
113 
114 }
115 
process(uint32 deltaTimeInMillis)116 bool SafeControl::process(uint32 deltaTimeInMillis) {
117 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
118 		return false;
119 
120 	if (_animation && _animation->getCurFrame() != _targetFrame && _animation->needsUpdate()) {
121 		// If we're past the target frame, move back one
122 		if (_animation->getCurFrame() > _targetFrame)
123 			_animation->seekToFrame(_animation->getCurFrame() - 1);
124 
125 		const Graphics::Surface *frameData = _animation->decodeNextFrame();
126 		if (_animation->getCurFrame() == _targetFrame)
127 			_engine->getScriptManager()->setStateValue(_key, _curState);
128 		if (frameData)
129 			_engine->getRenderManager()->blitSurfaceToBkg(*frameData, _rectangle.left, _rectangle.top);
130 	}
131 
132 	return false;
133 }
134 
onMouseMove(const Common::Point & screenSpacePos,const Common::Point & backgroundImageSpacePos)135 bool SafeControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
136 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
137 		return false;
138 
139 	if (_rectangle.contains(backgroundImageSpacePos)) {
140 		int32 mR = backgroundImageSpacePos.sqrDist(_center);
141 		if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
142 			_engine->getCursorManager()->changeCursor(CursorIndex_Active);
143 			return true;
144 		}
145 	}
146 	return false;
147 }
148 
onMouseUp(const Common::Point & screenSpacePos,const Common::Point & backgroundImageSpacePos)149 bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
150 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
151 		return false;
152 
153 	if (_rectangle.contains(backgroundImageSpacePos)) {
154 		int32 mR = backgroundImageSpacePos.sqrDist(_center);
155 		if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
156 			setVenus();
157 
158 			Common::Point tmp = backgroundImageSpacePos - _center;
159 
160 			float dd = atan2((float)tmp.y, (float)tmp.x) * 57.29578;
161 
162 			int16 dp_state = 360 / _statesCount;
163 
164 			int16 m_state = (_statesCount - ((((int16)dd + 540) % 360) / dp_state)) % _statesCount;
165 
166 			int16 tmp2 = (m_state + _curState - _zeroPointer + _statesCount - 1) % _statesCount;
167 
168 			if (_animation)
169 				_animation->seekToFrame((_curState + _statesCount - _startPointer) % _statesCount);
170 
171 			_curState = (_statesCount * 2 + tmp2) % _statesCount;
172 
173 			_targetFrame = (_curState + _statesCount - _startPointer) % _statesCount;
174 			return true;
175 		}
176 	}
177 	return false;
178 }
179 
180 } // End of namespace ZVision
181