Fix css style order when using external css files
[ryzomcore.git] / ryzom / client / src / progress.cpp
blob620b5486d4194dc899d44185f92ea7255059849b
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 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 bool UseEscapeDuringLoading;
56 CProgress::CProgress ()
58 _LastUpdate = ryzomGetLocalTime ();
59 _FontFactor = 1.0f;
60 pushCropedValues (0, 1);
61 ApplyTextCommands = false;
62 _TPCancelFlag = false;
65 CProgress::~CProgress ()
69 void CProgress::setFontFactor(float temp)
71 _FontFactor = temp;
74 void CProgress::newMessage (const string& message)
76 popCropedValues ();
77 _CurrentRootStep++;
78 pushCropedValues ((float)_CurrentRootStep/(float)_RootStepCount, (float)(_CurrentRootStep+1)/(float)_RootStepCount);
80 // New message
81 _ProgressMessage = message;
83 // Force call to progress
84 internalProgress (0);
87 void CProgress::reset (uint rootNodeCount)
89 _CurrentRootStep = 0;
90 _RootStepCount = rootNodeCount;
91 popCropedValues ();
92 pushCropedValues (0, 1/(float)_RootStepCount);
93 ApplyTextCommands = false;
95 finish();
98 void CProgress::progress (float value)
100 // Timer
101 sint64 newTime = ryzomGetLocalTime ();
102 if (newTime - _LastUpdate > PROGRESS_BAR_UPDATE)
104 internalProgress (value);
106 _LastUpdate = newTime;
110 float nextLine (uint fontHeight, uint windowHeight, float previousY)
112 if (windowHeight > 0)
114 return previousY-(float)fontHeight/(float)windowHeight;
116 return previousY;
119 void drawLoadingBitmap (float progress)
121 if (!LoadingMaterial.empty() && !LoadingMaterialFull.empty())
123 Driver->setMatrixMode2D11();
124 LoadingMaterialFull.setAlphaTestThreshold (1.f-progress);
126 CQuadUV quad;
127 uint wh = Driver->getWindowHeight();
128 uint ww = Driver->getWindowWidth();
129 float x1 = 0;
130 float y1 = 0;
131 float x2 = 1;
132 float y2 = 1;
134 if ((ww > 1024) || (wh > 768))
136 if ((ww - 1024) > (wh - 768))
137 x1 = ((ww - (wh * 1024.f) / 768.f) / 2.f) / ww;
138 else
139 y1 = ((wh - (ww * 768.f) / 1024.f) / 2.f) / wh;
142 if (x1 != 0)
143 x2 = 1 - x1;
144 if (y1 != 0)
145 y2 = 1 - y1;
147 quad.V0.set (x1,y1,0);
148 quad.V1.set (x2,y1,0);
149 quad.V2.set (x2,y2,0);
150 quad.V3.set (x1,y2,0);
152 quad.Uv0.U= 0;
153 quad.Uv0.V= 0.75f;
154 quad.Uv1.U= 1;
155 quad.Uv1.V= 0.75f;
156 quad.Uv2.U= 1;
157 quad.Uv2.V= 0;
158 quad.Uv3.U= 0;
159 quad.Uv3.V= 0;
161 Driver->drawQuad(0, 0, 1, 1, CRGBA(0, 0, 0, 255));
162 Driver->drawQuad(quad, LoadingMaterial);
163 Driver->drawQuad(quad, LoadingMaterialFull);
167 void CProgress::internalProgress (float value)
169 // Get croped value
170 value = getCropedValue (value);
172 // can't do anything if no driver
173 if (Driver == NULL)
174 return;
176 if (Driver->AsyncListener.isKeyPushed (KeyDOWN))
177 selectTipsOfTheDay (TipsOfTheDayIndex-1);
178 if (Driver->AsyncListener.isKeyPushed (KeyUP))
179 selectTipsOfTheDay (TipsOfTheDayIndex+1);
181 // Create camera for stereo mode
182 bool stereoHMD = StereoHMD && !MainCam.empty() && (MainCam.getTransformMode() == UCamera::RotQuat);
183 CVector oldPos;
184 CQuat oldQuat;
185 if (stereoHMD)
187 MainCam.getPos(oldPos);
188 MainCam.getRotQuat(oldQuat);
189 StereoHMD->setInterfaceMatrix(CMatrix()); // identity
190 NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
191 NLMISC::CMatrix camMatrix;
192 camMatrix.identity();
193 NLMISC::CMatrix hmdMatrix;
194 hmdMatrix.setRot(hmdOrient);
195 NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
196 posMatrix.translate(StereoHMD->getEyePosition());
197 NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix);
198 MainCam.setPos(mat.getPos());
199 MainCam.setRotQuat(mat.getRot());
200 StereoDisplay->updateCamera(0, &MainCam);
202 uint i = 0;
203 while ((!stereoHMD && i == 0) || (stereoHMD && StereoDisplay->nextPass()))
205 ++i;
206 if (stereoHMD)
208 // modify cameras for stereo display
209 const CViewport &vp = StereoDisplay->getCurrentViewport();
210 Driver->setViewport(vp);
211 StereoDisplay->getCurrentMatrix(0, &MainCam);
212 StereoDisplay->getCurrentFrustum(0, &MainCam);
214 // begin current pass
215 StereoDisplay->beginRenderTarget();
217 nldebug("Cam pos: %f, %f, %f", MainCam.getPos().x, MainCam.getPos().y, MainCam.getPos().z);
220 if (!stereoHMD || StereoDisplay->wantClear())
222 Driver->clearBuffers(CRGBA(0, 0, 0, 0));
225 if (stereoHMD && StereoDisplay->wantScene())
227 Driver->setMatrixMode3D(MainCam);
230 if (!stereoHMD || StereoDisplay->wantInterface2D())
232 // nldebug("Draw progress 2D");
234 // Font factor
235 float fontFactor = 1;
236 if (Driver->getWindowHeight() > 0)
237 fontFactor = (float)Driver->getWindowHeight() / 600.f;
238 fontFactor *= _FontFactor;
240 // Set 2d view.
241 Driver->setMatrixMode2D11();
243 // Display the loading background.
244 drawLoadingBitmap(value);
246 // temporary values for conversions
247 float x, y, width, height;
249 for(uint i = 0; i < ClientCfg.Logos.size(); i++)
251 std::vector<string> res;
252 explode(ClientCfg.Logos[i], string(":"), res);
253 if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL)
255 fromString(res[1], x);
256 fromString(res[2], y);
257 fromString(res[3], width);
258 fromString(res[4], height);
259 Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]);
263 if (TextContext != NULL)
265 // Init the Pen.
266 TextContext->setKeep800x600Ratio(false);
267 TextContext->setColor(CRGBA(255,255,255));
268 TextContext->setFontSize((uint)(12.f * fontFactor));
269 TextContext->setHotSpot(UTextContext::TopRight);
271 #if !FINAL_VERSION
272 // Display the Text.
273 TextContext->printAt(1, 0.98f, _ProgressMessage);
274 #else
275 if( ClientCfg.LoadingStringCount > 0 )
277 TextContext->printAt(1, 0.98f, _ProgressMessage);
279 #endif // FINAL_VERSION
281 // Display the build version.
282 TextContext->setFontSize((uint)(12.f * fontFactor));
283 TextContext->setHotSpot(UTextContext::TopRight);
284 string str = getDisplayVersion();
285 TextContext->printfAt(1.0f,1.0f, str.c_str());
287 // Display the tips of the day.
288 TextContext->setFontSize((uint)(16.f * fontFactor));
289 TextContext->setHotSpot(UTextContext::MiddleTop);
290 string::size_type index = 0;
291 string::size_type end = TipsOfTheDay.find('\n');
292 if (end == string::npos)
293 end = TipsOfTheDay.size();
294 float fY = ClientCfg.TipsY;
295 if (!TipsOfTheDay.empty())
297 while (index < end)
299 // Get the line
300 string line = TipsOfTheDay.substr (index, end-index);
302 // Draw the line
303 TextContext->printAt(0.5f, fY, line);
304 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
306 index=end+1;
307 end = TipsOfTheDay.find('\n', index);
308 if (end == string::npos)
309 end = TipsOfTheDay.size();
312 // More help
313 TextContext->setFontSize((uint)(12.f * fontFactor));
314 /* todo tips of the day uncomment
315 string ucstr = CI18N::get ("uiTipsEnd");
316 TextContext->printAt(0.5f, fY, ucstr); */
317 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
318 fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY);
323 if (!_TPReason.empty())
325 TextContext->setHotSpot(UTextContext::MiddleMiddle);
326 TextContext->setFontSize((uint)(14.f * fontFactor));
327 TextContext->printAt(0.5f, 0.5f, _TPReason);
328 TextContext->setHotSpot(UTextContext::BottomLeft);
329 TextContext->setColor(NLMISC::CRGBA::White);
334 if (!_TPCancelText.empty())
336 if (ClientCfg.Width != 0 && ClientCfg.Height != 0)
338 TextContext->setFontSize((uint)(15.f * fontFactor));
339 TextContext->setHotSpot(UTextContext::BottomLeft);
341 string uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel");
342 UTextContext::CStringInfo info = TextContext->getStringInfo(uc);
343 float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2);
344 TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc);
349 // Teleport help
350 //fY = ClientCfg.TeleportInfoY;
351 if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor)
353 TextContext->setFontSize((uint)(13.f * fontFactor));
355 // Print some more info
356 uint32 day = RT.getRyzomDay();
357 str = toString (CI18N::get ("uiTipsTeleport").c_str(),
358 CI18N::get (LoadingContinent->LocalizedName).c_str(),
359 day,
360 (uint)RT.getRyzomTime(),
361 CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).c_str(),
362 CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).c_str());
363 TextContext->setHotSpot(UTextContext::MiddleBottom);
364 TextContext->setColor(CRGBA(186, 179, 163, 255));
365 TextContext->printAt(0.5f, 25/768.f, str);
368 // apply text commands
369 if( ApplyTextCommands )
371 std::vector<CClientConfig::SPrintfCommand> printfCommands = ClientCfg.PrintfCommands;
372 if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial;
374 if( !printfCommands.empty() )
376 TextContext->setHotSpot(UTextContext::MiddleBottom);
378 vector<CClientConfig::SPrintfCommand>::iterator itpc;
379 for( itpc = printfCommands.begin(); itpc != printfCommands.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)(16.f * fontFactor));
386 // build the ucstr(s)
387 string ucstr = CI18N::get((*itpc).Text);
388 vector<string> vucstr;
389 string sep("\n");
390 splitString(ucstr,sep,vucstr);
392 // Letter size
393 UTextContext::CStringInfo si = TextContext->getStringInfo("|");
394 uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap
396 uint i;
397 float newy = y;
398 for( i=0; i<vucstr.size(); ++i )
400 TextContext->printAt(x,newy, vucstr[i]);
401 newy = nextLine(fontHeight, Driver->getWindowHeight(), newy);
409 if (stereoHMD)
411 StereoDisplay->endRenderTarget();
413 } /* stereo loop */
415 if (stereoHMD)
417 MainCam.setPos(oldPos);
418 MainCam.setRotQuat(oldQuat);
421 // Clamp
422 clamp (value, 0.f, 1.f);
424 // Set matrix
425 Driver->setMatrixMode2D11 ();
427 // want to receive the 'mouse down' event to deal with the 'cancel tp button'
428 Driver->EventServer.addListener(EventMouseDownId, this);
430 // Update messages
431 CInputHandlerManager::getInstance()->pumpEventsNoIM();
433 Driver->EventServer.removeListener(EventMouseDownId, this);
435 // Exit ?
436 bool activeDriver = Driver->isActive();
437 if ((UseEscapeDuringLoading && Driver->AsyncListener.isKeyPushed (KeyESCAPE)) || !activeDriver)
439 // Release the application
440 releaseMainLoop(true);
441 release();
442 // Leave the application
443 extern void quitCrashReport ();
444 quitCrashReport ();
445 exit(EXIT_SUCCESS);
448 if(!_TPCancelText.empty() && Driver->AsyncListener.isKeyPushed(KeySHIFT) && Driver->AsyncListener.isKeyPushed(KeyESCAPE))
450 _TPCancelFlag = true;
453 #ifdef RYZOM_BG_DOWNLOADER
454 CBGDownloaderAccess::getInstance().update();
455 #endif
456 // Display to screen.
457 Driver->swapBuffers();
459 // \todo GUIGUI : Remove this when possible.
460 NetMngr.update();
461 IngameDbMngr.flushObserverCalls();
462 NLGUI::CDBManager::getInstance()->flushObserverCalls();
464 // update system dependent progress bar
465 static uint previousValue = 0;
466 uint currentValue = (uint)(value*100.0f);
468 if (currentValue != previousValue)
470 CSystemUtils::updateProgressBar(currentValue, 100);
471 previousValue = currentValue;
476 void CProgress::setTPMessages(const string &tpReason,const string &tpCancelText, const string &/* iconName */)
478 _TPReason = tpReason;
479 _TPCancelText = tpCancelText;
483 void CProgress::operator ()(const CEvent& /* event */)
487 bool CProgress::getTPCancelFlag(bool clearFlag /*=true*/)
489 bool flag = _TPCancelFlag;
490 if (clearFlag)
492 _TPCancelFlag = false;
494 return flag;
497 void CProgress::release()
499 setTPMessages(string(), string(), string());
500 _TPCancelFlag = false;
503 void CProgress::finish()
505 // stop system dependent progress bar
506 CSystemUtils::updateProgressBar(1, 0);