git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / client / graph / MainCamera.cpp
blob87d7473f2e9551e23d42ab4c01e32bab8d2e572e
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <client/ClientState.h>
22 #include <client/ScorchedClient.h>
23 #include <client/ClientParams.h>
24 #include <graph/MainCamera.h>
25 #include <graph/Main2DCamera.h>
26 #include <graph/OptionsDisplay.h>
27 #include <landscapemap/LandscapeMaps.h>
28 #include <landscapedef/LandscapeDefn.h>
29 #include <engine/ViewPoints.h>
30 #include <image/ImageFactory.h>
31 #include <image/ImagePng.h>
32 #include <dialogs/MainMenuDialog.h>
33 #include <sound/Sound.h>
34 #include <sound/SoundUtils.h>
35 #include <common/Keyboard.h>
36 #include <common/Defines.h>
37 #include <common/Logger.h>
38 #include <coms/ComsOperationResultMessage.h>
39 #include <coms/ComsMessageSender.h>
40 #include <tank/TankContainer.h>
41 #include <tank/TankCamera.h>
42 #include <lang/LangResource.h>
43 #include <math.h>
44 #include <time.h>
46 MainCamera *MainCamera::instance_ = 0;
48 MainCamera *MainCamera::instance()
50 if (!instance_)
52 instance_ = new MainCamera;
55 return instance_;
58 MainCamera::MainCamera() :
59 GameStateI("MainCamera")
61 Image *map = ImageFactory::loadImage(
62 S3D::getDataFile("data/windows/camera.bmp"),
63 S3D::getDataFile("data/windows/cameraa.bmp"),
64 false);
65 DIALOG_ASSERT(map->getBits());
66 MainMenuDialog::instance()->addMenu(
67 LANG_RESOURCE("CAMERA", "Camera"),
68 "Camera",
69 LANG_RESOURCE("CAMERA_MENU", "Change the current camera view."),
70 32, 0, this, map);
73 MainCamera::~MainCamera()
78 bool MainCamera::getEnabled(const char* menuName)
80 unsigned int state = ScorchedClient::instance()->getGameState().getState();
81 return (state >= ClientState::StateWait);
84 bool MainCamera::getMenuItems(const char* menuName,
85 std::list<GLMenuItem> &result)
87 for (int i=0; i<TargetCamera::getNoCameraNames(); i++)
89 result.push_back(GLMenuItem(
90 LANG_RESOURCE(TargetCamera::getCameraNames()[i], TargetCamera::getCameraNames()[i]),
91 &TargetCamera::getCameraToolTips()[i],
92 (targetCam_.getCameraType() ==
93 (TargetCamera::CamType) i)));
95 return true;
98 void MainCamera::menuSelection(const char* menuName,
99 const int position, GLMenuItem &item)
101 targetCam_.setCameraType((TargetCamera::CamType) position);
104 static int getNumberOfPlayers()
106 int count = 0;
107 std::map<unsigned int, Tank *> &tanks =
108 ScorchedClient::instance()->getTankContainer().getAllTanks();
109 std::map<unsigned int, Tank *>::iterator mainitor;
110 for (mainitor = tanks.begin();
111 mainitor != tanks.end();
112 mainitor++)
114 Tank *current = (*mainitor).second;
115 if (current->getTankAI()) count++;
117 return count;
120 void MainCamera::simulate(const unsigned state, float frameTime)
122 if (state != 0 &&
123 state != ClientState::StateOptions &&
124 OptionsDisplay::instance()->getFullScreen() &&
125 OptionsDisplay::instance()->getSideScroll())
127 int mouseX = ScorchedClient::instance()->getGameState().getMouseX();
128 int mouseY = ScorchedClient::instance()->getGameState().getMouseY();
129 int windowX = Main2DCamera::instance()->getViewPort().getWidth();
130 int windowY = Main2DCamera::instance()->getViewPort().getHeight();
132 float arenaWidth = (float) ScorchedClient::instance()->getLandscapeMaps().
133 getGroundMaps().getArenaWidth();
134 float arenaHeight = (float) ScorchedClient::instance()->getLandscapeMaps().
135 getGroundMaps().getArenaHeight();
136 float arenaX = (float) ScorchedClient::instance()->getLandscapeMaps().
137 getGroundMaps().getArenaX();
138 float arenaY = (float) ScorchedClient::instance()->getLandscapeMaps().
139 getGroundMaps().getArenaY();
142 const int scrollWindow = 5;
143 if (mouseX < scrollWindow)
145 targetCam_.setCameraType(TargetCamera::CamFree);
146 if (Keyboard::instance()->getKeyboardState() & KMOD_LSHIFT)
148 targetCam_.getCamera().movePositionDelta(-0.3f, 0.0f, 0.0f);
150 else
152 targetCam_.getCamera().scroll(GLCamera::eScrollLeft,
153 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
156 else if (mouseX > windowX - scrollWindow)
158 targetCam_.setCameraType(TargetCamera::CamFree);
159 if (Keyboard::instance()->getKeyboardState() & KMOD_LSHIFT)
161 targetCam_.getCamera().movePositionDelta(+0.3f, 0.0f, 0.0f);
163 else
165 targetCam_.getCamera().scroll(GLCamera::eScrollRight,
166 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
170 if (mouseY < scrollWindow)
172 targetCam_.setCameraType(TargetCamera::CamFree);
173 if (Keyboard::instance()->getKeyboardState() & KMOD_LSHIFT)
175 targetCam_.getCamera().movePositionDelta(0.0f, 0.3f, 0.0f);
177 else if (Keyboard::instance()->getKeyboardState() & KMOD_LCTRL)
179 targetCam_.getCamera().movePositionDelta(0.0f, 0.0f, +5.0f);
181 else
183 targetCam_.getCamera().scroll(GLCamera::eScrollDown,
184 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
187 else if (mouseY > windowY - scrollWindow)
189 targetCam_.setCameraType(TargetCamera::CamFree);
190 if (Keyboard::instance()->getKeyboardState() & KMOD_LSHIFT)
192 targetCam_.getCamera().movePositionDelta(0.0f, -0.3f, 0.0f);
194 else if (Keyboard::instance()->getKeyboardState() & KMOD_LCTRL)
196 targetCam_.getCamera().movePositionDelta(0.0f, 0.0f, -5.0f);
198 else
200 targetCam_.getCamera().scroll(GLCamera::eScrollUp,
201 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
207 ScorchedClient::instance()->getContext().getViewPoints().simulate(
208 fixed::fromFloat(frameTime));
209 targetCam_.simulate(frameTime, (state == ClientState::StatePlaying));
211 Sound::instance()->getDefaultListener()->setPosition(
212 targetCam_.getCamera().getCurrentPos());
213 Sound::instance()->getDefaultListener()->setVelocity(
214 targetCam_.getCamera().getVelocity());
215 Vector direction =
216 targetCam_.getCamera().getLookAt() -
217 targetCam_.getCamera().getCurrentPos();
218 Sound::instance()->getDefaultListener()->setOrientation(
219 direction);
221 // Update the current tank's camera attributes
222 if (state == ClientState::StatePlaying ||
223 ClientParams::instance()->getConnectedToServer() ||
224 getNumberOfPlayers() <= 1)
226 Tank *current = ScorchedClient::instance()->getTankContainer().getCurrentTank();
227 if (current)
229 Vector rotation(
230 targetCam_.getCamera().getRotationXY(),
231 targetCam_.getCamera().getRotationYZ(),
232 targetCam_.getCamera().getZoom());
233 current->getCamera().setCameraLookAt(targetCam_.getCamera().getLookAt());
234 current->getCamera().setCameraRotation(rotation);
235 current->getCamera().setCameraType((int) targetCam_.getCameraType());
240 void MainCamera::draw(const unsigned state)
242 targetCam_.draw();
245 void MainCamera::mouseDrag(const unsigned state,
246 GameState::MouseButton button,
247 int mx, int my, int x, int y, bool &skipRest)
249 targetCam_.mouseDrag(button, mx, my, x, y, skipRest);
252 void MainCamera::mouseWheel(const unsigned state, int x, int y, int z, bool &skipRest)
254 targetCam_.mouseWheel(x, y, z, skipRest);
257 void MainCamera::mouseDown(const unsigned state, GameState::MouseButton button,
258 int x, int y, bool &skipRest)
260 targetCam_.mouseDown(button, x, y, skipRest);
263 void MainCamera::mouseUp(const unsigned state, GameState::MouseButton button,
264 int x, int y, bool &skipRest)
266 targetCam_.mouseUp(button, x, y, skipRest);
269 void MainCamera::keyboardCheck(const unsigned state, float frameTime,
270 char *buffer, unsigned int keyState,
271 KeyboardHistory::HistoryElement *history,
272 int hisCount,
273 bool &skipRest)
275 targetCam_.keyboardCheck(frameTime, buffer,
276 keyState, history, hisCount, skipRest);
278 KEYBOARDKEY("SAVE_SCREEN", saveScreenKey);
279 if (saveScreenKey->keyDown(buffer, keyState, false))
281 saveScreen_.saveScreen_ = true;
284 KEYBOARDKEY("CAMERA_SCROLL_UP", scrollUp);
285 KEYBOARDKEY("CAMERA_SCROLL_DOWN", scrollDown);
286 KEYBOARDKEY("CAMERA_SCROLL_LEFT", scrollLeft);
287 KEYBOARDKEY("CAMERA_SCROLL_RIGHT", scrollRight);
289 float arenaWidth = (float) ScorchedClient::instance()->getLandscapeMaps().
290 getGroundMaps().getArenaWidth();
291 float arenaHeight = (float) ScorchedClient::instance()->getLandscapeMaps().
292 getGroundMaps().getArenaHeight();
293 float arenaX = (float) ScorchedClient::instance()->getLandscapeMaps().
294 getGroundMaps().getArenaX();
295 float arenaY = (float) ScorchedClient::instance()->getLandscapeMaps().
296 getGroundMaps().getArenaY();
298 if (scrollUp->keyDown(buffer, keyState))
300 targetCam_.setCameraType(TargetCamera::CamFree);
301 targetCam_.getCamera().scroll(GLCamera::eScrollUp,
302 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
304 else if (scrollDown->keyDown(buffer, keyState))
306 targetCam_.setCameraType(TargetCamera::CamFree);
307 targetCam_.getCamera().scroll(GLCamera::eScrollDown,
308 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
310 else if (scrollLeft->keyDown(buffer, keyState))
312 targetCam_.setCameraType(TargetCamera::CamFree);
313 targetCam_.getCamera().scroll(GLCamera::eScrollLeft,
314 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
316 else if (scrollRight->keyDown(buffer, keyState))
318 targetCam_.setCameraType(TargetCamera::CamFree);
319 targetCam_.getCamera().scroll(GLCamera::eScrollRight,
320 arenaX, arenaY, arenaX + arenaWidth, arenaY + arenaHeight);
323 KEYBOARDKEY("HIDE_ALL_DIALOGS", hideWindows);
324 if (hideWindows->keyDown(buffer, keyState, false))
326 Main2DCamera::instance()->setHide(
327 !Main2DCamera::instance()->getHide());
330 KEYBOARDKEY("CAMERA_SET_QUICK_SLOT_1", setQuick1);
331 KEYBOARDKEY("CAMERA_SET_QUICK_SLOT_2", setQuick2);
332 KEYBOARDKEY("CAMERA_SET_QUICK_SLOT_3", setQuick3);
333 KEYBOARDKEY("CAMERA_SET_QUICK_SLOT_4", setQuick4);
334 KEYBOARDKEY("CAMERA_SET_QUICK_SLOT_5", setQuick5);
335 KEYBOARDKEY("CAMERA_USE_QUICK_SLOT_1", useQuick1);
336 KEYBOARDKEY("CAMERA_USE_QUICK_SLOT_2", useQuick2);
337 KEYBOARDKEY("CAMERA_USE_QUICK_SLOT_3", useQuick3);
338 KEYBOARDKEY("CAMERA_USE_QUICK_SLOT_4", useQuick4);
339 KEYBOARDKEY("CAMERA_USE_QUICK_SLOT_5", useQuick5);
340 if (setQuick1->keyDown(buffer, keyState, false))
341 setQuick(1);
342 else if (setQuick2->keyDown(buffer, keyState, false))
343 setQuick(2);
344 else if (setQuick3->keyDown(buffer, keyState, false))
345 setQuick(3);
346 else if (setQuick4->keyDown(buffer, keyState, false))
347 setQuick(4);
348 else if (setQuick5->keyDown(buffer, keyState, false))
349 setQuick(5);
350 else if (useQuick1->keyDown(buffer, keyState, false))
351 useQuick(1);
352 else if (useQuick2->keyDown(buffer, keyState, false))
353 useQuick(2);
354 else if (useQuick3->keyDown(buffer, keyState, false))
355 useQuick(3);
356 else if (useQuick4->keyDown(buffer, keyState, false))
357 useQuick(4);
358 else if (useQuick5->keyDown(buffer, keyState, false))
359 useQuick(5);
362 void MainCamera::setQuick(int key)
364 std::pair<Vector, Vector> value(
365 targetCam_.getCamera().getLookAt(),
366 Vector(targetCam_.getCamera().getRotationXY(),
367 targetCam_.getCamera().getRotationYZ(),
368 targetCam_.getCamera().getZoom()));
369 quickKeys_[key] = value;
370 Logger::log(S3D::formatStringBuffer("Saved camera preset %i", key));
373 void MainCamera::useQuick(int key)
375 std::map<int, std::pair<Vector, Vector> >::iterator
376 findItor = quickKeys_.find(key);
377 if (findItor != quickKeys_.end())
379 std::pair<Vector, Vector> value = (*findItor).second;
380 targetCam_.setCameraType(TargetCamera::CamFree);
381 targetCam_.getCamera().setLookAt(value.first);
382 targetCam_.getCamera().movePosition(value.second[0],
383 value.second[1], value.second[2]);
384 Logger::log(S3D::formatStringBuffer("Using camera preset %i", key));
388 void MainCamera::SaveScreen::draw(const unsigned state)
390 if (saveScreen_)
392 saveScreen_ = false;
394 bool hide = Main2DCamera::instance()->getHide();
395 Main2DCamera::instance()->setHide(false);
396 Main2DCamera::instance()->draw(0);
397 Main2DCamera::instance()->setHide(hide);
399 static unsigned counter = 0;
400 time_t currentTime = time(0);
401 std::string fileName =
402 S3D::getHomeFile(S3D::formatStringBuffer("ScreenShot-%i-%i.png", currentTime, counter++));
404 ImageHandle screenMap = ImageFactory::grabScreen();
406 ImagePng png(screenMap.getWidth(), screenMap.getHeight());
407 memcpy(png.getBits(), screenMap.getBits(), screenMap.getWidth() * screenMap.getHeight() * 3);
409 NetBuffer buffer;
410 png.writeToBuffer(buffer);
412 FILE *out = fopen(fileName.c_str(), "wb");
413 fwrite(buffer.getBuffer(), 1, buffer.getBufferUsed(), out);
414 fclose(out);
416 // Don't print to banner otherwise this message will be in
417 // the screenshot!
418 Logger::log(S3D::formatStringBuffer("Screen shot saved as file \"%s\"", fileName.c_str()));
420 // snapshot sound
421 CACHE_SOUND(sound, S3D::getDataFile("data/wav/misc/camera.wav"));
422 SoundUtils::playRelativeSound(VirtualSoundPriority::eText, sound);
424 if (saveScreenTest_)
426 saveScreenTest_ = false;
428 ImageHandle screenMap = ImageFactory::grabScreen();
429 ComsOperationResultMessage resultMessage;
430 resultMessage.getResultBuffer().addDataToBuffer(
431 screenMap.getBits(),
432 screenMap.getWidth() * screenMap.getHeight() * 3);
433 resultMessage.getWidth() = screenMap.getWidth();
434 resultMessage.getHeight() = screenMap.getHeight();
435 ComsMessageSender::sendToServer(resultMessage);
439 void MainCamera::Precipitation::draw(const unsigned state)
441 MainCamera::instance()->getTarget().drawPrecipitation();