Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / progress.cpp
blob377e06ec74c48023bb92811e3ce5cf2b1e36c7db
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stdpch.h"
23 #include "progress.h"
24 #include "time_client.h"
25 #include "global.h"
26 #include "nel/misc/events.h"
27 #include "nel/3d/u_texture.h"
28 #include "nel/misc/i18n.h"
29 #include "continent.h"
30 #include "weather.h"
31 #include "weather_manager_client.h"
32 #include "interface_v3/input_handler_manager.h"
33 #include "interface_v3/interface_manager.h"
34 #include "release.h"
35 #include "net_manager.h"
36 #include "client_cfg.h"
37 #include "user_agent.h"
38 #include "bg_downloader_access.h"
39 #include "nel/misc/system_utils.h"
40 #include "nel/3d/stereo_hmd.h"
42 using namespace std;
43 using namespace NLMISC;
44 using namespace NL3D;
47 extern void selectTipsOfTheDay (uint tips);
48 extern NL3D::UMaterial LoadingMaterial;
49 extern NL3D::UMaterial LoadingMaterialFull;
51 extern std::vector<UTextureFile*> LogoBitmaps;
52 extern uint TipsOfTheDayIndex;
53 extern string TipsOfTheDay;
54 extern string NewsAtProgress;
55 extern bool UseEscapeDuringLoading;
57 CProgress::CProgress ()
59 _LastUpdate = ryzomGetLocalTime ();
60 _FontFactor = 1.0f;
61 pushCropedValues (0, 1);
62 ApplyTextCommands = false;
63 _TPCancelFlag = false;
66 CProgress::~CProgress ()
70 void CProgress::setFontFactor(float temp)
72 _FontFactor = temp;
75 void CProgress::newMessage (const string& message)
77 popCropedValues ();
78 _CurrentRootStep++;
79 pushCropedValues ((float)_CurrentRootStep/(float)_RootStepCount, (float)(_CurrentRootStep+1)/(float)_RootStepCount);
81 // New message
82 _ProgressMessage = message;
84 // Force call to progress
85 internalProgress (0);
88 void CProgress::reset (uint rootNodeCount)
90 _CurrentRootStep = 0;
91 _RootStepCount = rootNodeCount;
92 popCropedValues ();
93 pushCropedValues (0, 1/(float)_RootStepCount);
94 ApplyTextCommands = false;
96 finish();
99 void CProgress::progress (float value)
101 // Timer
102 sint64 newTime = ryzomGetLocalTime ();
103 if (newTime - _LastUpdate > PROGRESS_BAR_UPDATE)
105 internalProgress (value);
107 _LastUpdate = newTime;
111 float nextLine (uint fontHeight, uint windowHeight, float previousY)
113 if (windowHeight > 0)
115 return previousY-(float)fontHeight/(float)windowHeight;
117 return previousY;
120 void drawLoadingBitmap (float progress)
122 if (!LoadingMaterial.empty() && !LoadingMaterialFull.empty())
124 Driver->setMatrixMode2D11();
125 LoadingMaterialFull.setAlphaTestThreshold (1.f-progress);
127 CQuadUV quad;
128 uint wh = Driver->getWindowHeight();
129 uint ww = Driver->getWindowWidth();
130 float x1 = 0;
131 float y1 = 0;
132 float x2 = 1;
133 float y2 = 1;
135 if ((ww > 1024) || (wh > 768))
137 if ((ww - 1024) > (wh - 768))
138 x1 = ((ww - (wh * 1024.f) / 768.f) / 2.f) / ww;
139 else
140 y1 = ((wh - (ww * 768.f) / 1024.f) / 2.f) / wh;
143 if (x1 != 0)
144 x2 = 1 - x1;
145 if (y1 != 0)
146 y2 = 1 - y1;
148 quad.V0.set (x1,y1,0);
149 quad.V1.set (x2,y1,0);
150 quad.V2.set (x2,y2,0);
151 quad.V3.set (x1,y2,0);
153 quad.Uv0.U= 0;
154 quad.Uv0.V= 0.75f;
155 quad.Uv1.U= 1;
156 quad.Uv1.V= 0.75f;
157 quad.Uv2.U= 1;
158 quad.Uv2.V= 0;
159 quad.Uv3.U= 0;
160 quad.Uv3.V= 0;
162 Driver->drawQuad(0, 0, 1, 1, CRGBA(0, 0, 0, 255));
163 Driver->drawQuad(quad, LoadingMaterial);
164 Driver->drawQuad(quad, LoadingMaterialFull);
168 void CProgress::internalProgress (float value)
170 // Get croped value
171 value = getCropedValue (value);
173 // can't do anything if no driver
174 if (Driver == NULL)
175 return;
177 if (Driver->AsyncListener.isKeyPushed (KeyDOWN))
178 selectTipsOfTheDay (TipsOfTheDayIndex-1);
179 if (Driver->AsyncListener.isKeyPushed (KeyUP))
180 selectTipsOfTheDay (TipsOfTheDayIndex+1);
182 // Create camera for stereo mode
183 bool stereoHMD = StereoHMD && !MainCam.empty() && (MainCam.getTransformMode() == UCamera::RotQuat);
184 CVector oldPos;
185 CQuat oldQuat;
186 if (stereoHMD)
188 MainCam.getPos(oldPos);
189 MainCam.getRotQuat(oldQuat);
190 StereoHMD->setInterfaceMatrix(CMatrix()); // identity
191 NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
192 NLMISC::CMatrix camMatrix;
193 camMatrix.identity();
194 NLMISC::CMatrix hmdMatrix;
195 hmdMatrix.setRot(hmdOrient);
196 NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
197 posMatrix.translate(StereoHMD->getEyePosition());
198 NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix);
199 MainCam.setPos(mat.getPos());
200 MainCam.setRotQuat(mat.getRot());
201 StereoDisplay->updateCamera(0, &MainCam);
203 uint i = 0;
204 while ((!stereoHMD && i == 0) || (stereoHMD && StereoDisplay->nextPass()))
206 ++i;
207 if (stereoHMD)
209 // modify cameras for stereo display
210 const CViewport &vp = StereoDisplay->getCurrentViewport();
211 Driver->setViewport(vp);
212 StereoDisplay->getCurrentMatrix(0, &MainCam);
213 StereoDisplay->getCurrentFrustum(0, &MainCam);
215 // begin current pass
216 StereoDisplay->beginRenderTarget();
218 nldebug("Cam pos: %f, %f, %f", MainCam.getPos().x, MainCam.getPos().y, MainCam.getPos().z);
221 if (!stereoHMD || StereoDisplay->wantClear())
223 Driver->clearBuffers(CRGBA(0, 0, 0, 0));
226 if (stereoHMD && StereoDisplay->wantScene())
228 Driver->setMatrixMode3D(MainCam);
231 if (!stereoHMD || StereoDisplay->wantInterface2D())
233 // nldebug("Draw progress 2D");
235 // Font factor
236 float fontFactor = 1;
237 if (Driver->getWindowHeight() > 0)
238 fontFactor = (float)Driver->getWindowHeight() / 600.f;
239 fontFactor *= _FontFactor;
241 // Set 2d view.
242 Driver->setMatrixMode2D11();
244 // Display the loading background.
245 drawLoadingBitmap(value);
247 // temporary values for conversions
248 float x, y, width, height;
250 for(uint i = 0; i < ClientCfg.Logos.size(); i++)
252 std::vector<string> res;
253 explode(ClientCfg.Logos[i], string(":"), res);
254 if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL)
256 fromString(res[1], x);
257 fromString(res[2], y);
258 fromString(res[3], width);
259 fromString(res[4], height);
260 Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]);
264 if (TextContext != NULL)
266 // Init the Pen.
267 TextContext->setKeep800x600Ratio(false);
268 TextContext->setColor(CRGBA(255,255,255));
269 TextContext->setFontSize((uint)(12.f * fontFactor));
270 TextContext->setHotSpot(UTextContext::TopRight);
272 #if !FINAL_VERSION
273 // Display the Text.
274 TextContext->printAt(1, 0.98f, _ProgressMessage);
275 #else
276 if( ClientCfg.LoadingStringCount > 0 )
278 TextContext->printAt(1, 0.98f, _ProgressMessage);
280 #endif // FINAL_VERSION
282 // Display the build version.
283 TextContext->setFontSize((uint)(12.f * fontFactor));
284 TextContext->setHotSpot(UTextContext::TopRight);
285 string str = getDisplayVersion();
286 TextContext->printfAt(1.0f,1.0f, str.c_str());
288 // Display the tips of the day.
289 TextContext->setFontSize((uint)(16.f * fontFactor));
290 TextContext->setHotSpot(UTextContext::MiddleTop);
291 string::size_type index = 0;
292 string::size_type end = TipsOfTheDay.find('\n');
293 if (end == string::npos)
294 end = TipsOfTheDay.size();
295 float fY = ClientCfg.TipsY;
296 if (!TipsOfTheDay.empty())
298 while (index < end)
300 // Get the line
301 string line = TipsOfTheDay.substr (index, end-index);
303 // Draw the line
304 TextContext->printAt(0.5f, fY, line);
305 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
307 index=end+1;
308 end = TipsOfTheDay.find('\n', index);
309 if (end == string::npos)
310 end = TipsOfTheDay.size();
313 // More help
314 TextContext->setFontSize((uint)(12.f * fontFactor));
315 /* todo tips of the day uncomment
316 string ucstr = CI18N::get ("uiTipsEnd");
317 TextContext->printAt(0.5f, fY, ucstr); */
318 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
319 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
324 if (!_TPReason.empty())
326 TextContext->setHotSpot(UTextContext::MiddleMiddle);
327 TextContext->setFontSize((uint)(14.f * fontFactor));
328 TextContext->printAt(0.5f, 0.5f, _TPReason);
329 TextContext->setHotSpot(UTextContext::BottomLeft);
330 TextContext->setColor(NLMISC::CRGBA::White);
335 if (!_TPCancelText.empty())
337 if (ClientCfg.Width != 0 && ClientCfg.Height != 0)
339 TextContext->setFontSize((uint)(15.f * fontFactor));
340 TextContext->setHotSpot(UTextContext::BottomLeft);
342 string uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel");
343 UTextContext::CStringInfo info = TextContext->getStringInfo(uc);
344 float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2);
345 TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc);
350 // Teleport help
351 //fY = ClientCfg.TeleportInfoY;
352 if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor)
354 TextContext->setFontSize((uint)(13.f * fontFactor));
356 // Print some more info
357 uint32 day = RT.getRyzomDay();
358 str = toString (CI18N::get ("uiTipsTeleport").c_str(),
359 CI18N::get (LoadingContinent->LocalizedName).c_str(),
360 day,
361 (uint)RT.getRyzomTime(),
362 CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).c_str(),
363 CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).c_str());
364 TextContext->setHotSpot(UTextContext::MiddleBottom);
365 TextContext->setColor(CRGBA(186, 179, 163, 255));
366 TextContext->printAt(0.5f, 25/768.f, str);
369 // apply text commands
370 if( ApplyTextCommands )
372 std::vector<CClientConfig::SPrintfCommand> loadingTexts = ClientCfg.loadingTexts;
374 if( !loadingTexts.empty() )
376 TextContext->setHotSpot(UTextContext::MiddleBottom);
378 vector<CClientConfig::SPrintfCommand>::iterator itpc;
379 for( itpc = loadingTexts.begin(); itpc != loadingTexts.end(); ++itpc )
381 float x = 0.5f;//((*itpc).X / 1024.f);
382 float y = ((*itpc).Y / 768.f);
383 TextContext->setColor( (*itpc).Color );
384 TextContext->setFontSize( (uint)((*itpc).FontSize * fontFactor));
386 // build the ucstr(s)
387 string text = (*itpc).Text;
388 string ucstr;
389 if (text == "NEWS")
390 ucstr = NewsAtProgress;
391 else
392 ucstr = CI18N::get(text);
393 vector<string> vucstr;
394 string sep("\n");
395 splitString(ucstr,sep,vucstr);
397 // Letter size
398 UTextContext::CStringInfo si = TextContext->getStringInfo("|");
399 uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap
401 uint i;
402 float newy = y;
403 for( i=0; i<vucstr.size(); ++i )
405 TextContext->printAt(x,newy, vucstr[i]);
406 newy = nextLine(fontHeight, Driver->getWindowHeight(), newy);
414 if (stereoHMD)
416 StereoDisplay->endRenderTarget();
418 } /* stereo loop */
420 if (stereoHMD)
422 MainCam.setPos(oldPos);
423 MainCam.setRotQuat(oldQuat);
426 // Clamp
427 clamp (value, 0.f, 1.f);
429 // Set matrix
430 Driver->setMatrixMode2D11 ();
432 // want to receive the 'mouse down' event to deal with the 'cancel tp button'
433 Driver->EventServer.addListener(EventMouseDownId, this);
435 // Update messages
436 CInputHandlerManager::getInstance()->pumpEventsNoIM();
438 Driver->EventServer.removeListener(EventMouseDownId, this);
440 // Exit ?
441 bool activeDriver = Driver->isActive();
442 if ((UseEscapeDuringLoading && Driver->AsyncListener.isKeyPushed (KeyESCAPE)) || !activeDriver)
444 // Release the application
445 releaseMainLoop(true);
446 release();
447 // Leave the application
448 extern void quitCrashReport ();
449 quitCrashReport ();
450 exit(EXIT_SUCCESS);
453 if(!_TPCancelText.empty() && Driver->AsyncListener.isKeyPushed(KeySHIFT) && Driver->AsyncListener.isKeyPushed(KeyESCAPE))
455 _TPCancelFlag = true;
458 #ifdef RYZOM_BG_DOWNLOADER
459 CBGDownloaderAccess::getInstance().update();
460 #endif
461 // Display to screen.
462 Driver->swapBuffers();
464 // \todo GUIGUI : Remove this when possible.
465 NetMngr.update();
466 IngameDbMngr.flushObserverCalls();
467 NLGUI::CDBManager::getInstance()->flushObserverCalls();
469 // update system dependent progress bar
470 static uint previousValue = 0;
471 uint currentValue = (uint)(value*100.0f);
473 if (currentValue != previousValue)
475 CSystemUtils::updateProgressBar(currentValue, 100);
476 previousValue = currentValue;
481 void CProgress::setTPMessages(const string &tpReason,const string &tpCancelText, const string &/* iconName */)
483 _TPReason = tpReason;
484 _TPCancelText = tpCancelText;
488 void CProgress::operator ()(const CEvent& /* event */)
492 bool CProgress::getTPCancelFlag(bool clearFlag /*=true*/)
494 bool flag = _TPCancelFlag;
495 if (clearFlag)
497 _TPCancelFlag = false;
499 return flag;
502 void CProgress::release()
504 setTPMessages(string(), string(), string());
505 _TPCancelFlag = false;
508 void CProgress::finish()
510 // stop system dependent progress bar
511 CSystemUtils::updateProgressBar(1, 0);