1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
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>
46 MainCamera
*MainCamera::instance_
= 0;
48 MainCamera
*MainCamera::instance()
52 instance_
= new MainCamera
;
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"),
65 DIALOG_ASSERT(map
->getBits());
66 MainMenuDialog::instance()->addMenu(
67 LANG_RESOURCE("CAMERA", "Camera"),
69 LANG_RESOURCE("CAMERA_MENU", "Change the current camera view."),
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
)));
98 void MainCamera::menuSelection(const char* menuName
,
99 const int position
, GLMenuItem
&item
)
101 targetCam_
.setCameraType((TargetCamera::CamType
) position
);
104 static int getNumberOfPlayers()
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();
114 Tank
*current
= (*mainitor
).second
;
115 if (current
->getTankAI()) count
++;
120 void MainCamera::simulate(const unsigned state
, float frameTime
)
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
);
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
);
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
);
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
);
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());
216 targetCam_
.getCamera().getLookAt() -
217 targetCam_
.getCamera().getCurrentPos();
218 Sound::instance()->getDefaultListener()->setOrientation(
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();
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
)
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
,
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))
342 else if (setQuick2
->keyDown(buffer
, keyState
, false))
344 else if (setQuick3
->keyDown(buffer
, keyState
, false))
346 else if (setQuick4
->keyDown(buffer
, keyState
, false))
348 else if (setQuick5
->keyDown(buffer
, keyState
, false))
350 else if (useQuick1
->keyDown(buffer
, keyState
, false))
352 else if (useQuick2
->keyDown(buffer
, keyState
, false))
354 else if (useQuick3
->keyDown(buffer
, keyState
, false))
356 else if (useQuick4
->keyDown(buffer
, keyState
, false))
358 else if (useQuick5
->keyDown(buffer
, keyState
, false))
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
)
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);
410 png
.writeToBuffer(buffer
);
412 FILE *out
= fopen(fileName
.c_str(), "wb");
413 fwrite(buffer
.getBuffer(), 1, buffer
.getBufferUsed(), out
);
416 // Don't print to banner otherwise this message will be in
418 Logger::log(S3D::formatStringBuffer("Screen shot saved as file \"%s\"", fileName
.c_str()));
421 CACHE_SOUND(sound
, S3D::getDataFile("data/wav/misc/camera.wav"));
422 SoundUtils::playRelativeSound(VirtualSoundPriority::eText
, sound
);
426 saveScreenTest_
= false;
428 ImageHandle screenMap
= ImageFactory::grabScreen();
429 ComsOperationResultMessage resultMessage
;
430 resultMessage
.getResultBuffer().addDataToBuffer(
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();