Merge branch '164-crash-on-patching-and-possibly-right-after-login' into main/gingo...
[ryzomcore.git] / ryzom / client / src / main_loop.cpp
blob56452ba4ac766955cbebfccecaf91d8f298679d3
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) 2013-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 /////////////
23 // INCLUDE //
24 /////////////
27 #include "stdpch.h"
29 // Misc.
30 #include "nel/misc/path.h"
31 #include "nel/misc/i18n.h"
32 #include "nel/misc/hierarchical_timer.h"
33 #include "nel/misc/displayer.h"
34 #include "nel/misc/value_smoother.h"
35 #include "nel/misc/geom_ext.h"
36 // Net
37 #include "nel/net/module_manager.h"
38 // 3D Interface.
39 #include "nel/3d/bloom_effect.h"
40 #include "nel/3d/u_driver.h"
41 #include "nel/3d/u_scene.h"
42 #include "nel/3d/u_landscape.h"
43 #include "nel/3d/u_camera.h"
44 #include "nel/3d/u_text_context.h"
45 #include "nel/3d/u_instance.h"
46 #include "nel/3d/u_material.h"
47 #include "nel/3d/u_instance_material.h"
48 #include "nel/3d/u_cloud_scape.h"
49 #include "nel/3d/stereo_hmd.h"
50 #include "nel/3d/render_target_manager.h"
51 #include "nel/3d/driver_user.h"
52 #include "nel/3d/fxaa.h"
53 // game share
54 #include "game_share/brick_types.h"
55 #include "game_share/light_cycle.h"
56 #include "game_share/time_weather_season/time_and_season.h"
57 #include "game_share/bot_chat_types.h"
58 // PACS
59 #include "nel/pacs/u_global_position.h"
60 // client sheets
61 #include "client_sheets/weather_function_params_sheet.h"
62 // std
63 #include <string>
64 // Client
65 #include "game_share/constants.h"
66 #include "main_loop.h"
67 #include "input.h"
68 #include "client_cfg.h"
69 #include "actions_client.h"
70 #include "motion/user_controls.h"
71 #include "entity_animation_manager.h"
72 #include "pacs_client.h"
73 #include "view.h"
74 #include "time_client.h"
75 #include "cursor_functions.h"
76 #include "pacs_client.h"
77 #include "entity_fx.h"
78 #include "light_cycle_manager.h"
79 #include "weather_manager_client.h"
80 #include "weather.h"
81 #include "game_share/time_weather_season/weather_predict.h"
82 #include "entities.h"
83 #include "net_manager.h"
84 #include "world_database_manager.h"
85 #include "continent_manager.h"
86 #include "ig_callback.h"
87 #include "release.h"
88 //#include "fog_map.h"
89 #include "movie_shooter.h"
90 #include "sound_manager.h"
91 #include "graph.h"
92 #include "interface_v3/interface_manager.h"
93 #include "demo.h"
94 #include "color_slot_manager.h"
95 #include "interface_v3/input_handler_manager.h"
96 #include "ingame_database_manager.h"
97 #include "sky_render.h"
98 #include "prim_file.h"
99 #include "misc.h"
100 #include "interface_v3/people_interraction.h"
101 #include "debug_client.h"
102 #include "nel/gui/action_handler.h"
103 #include "interface_v3/action_handler_misc.h"
104 #include "interface_v3/action_handler_item.h"
105 #include "fx_manager.h"
106 #include "ground_fx_manager.h"
107 #include "string_manager_client.h"
108 #include "interface_v3/group_in_scene_bubble.h"
109 #include "game_context_menu.h"
110 #include "init_main_loop.h"
111 #include "micro_life_manager.h"
112 #include "timed_fx_manager.h"
113 #include "interface_v3/sphrase_manager.h"
114 #include "outpost_manager.h"
115 #include "sky.h" // new-style sky
116 #include "sky_render.h" // new-style sky
117 #include "interface_v3/music_player.h"
118 #include "permanent_ban.h"
119 #include "camera_recorder.h"
120 #include "connection.h"
121 #include "landscape_poly_drawer.h"
122 #include "nel/gui/lua_ihm.h"
123 #include "interface_v3/lua_ihm_ryzom.h"
124 #include "far_tp.h"
125 #include "session_browser_impl.h"
126 #include "bg_downloader_access.h"
127 #include "login_progress_post_thread.h"
128 #include "npc_icon.h"
129 #include "item_group_manager.h"
130 // R2ED
131 #include "r2/editor.h"
133 #include "nel/misc/check_fpu.h"
137 #ifdef USE_WATER_ENV_MAP
138 #include "water_env_map_rdr.h"
139 #endif
141 // temp
142 #include "precipitation.h"
143 #include "interface_v3/bot_chat_manager.h"
144 #include "string_manager_client.h"
146 #include "nel/gui/lua_manager.h"
147 #include "nel/gui/group_table.h"
149 // pulled from main_loop.cpp
150 #include "ping.h"
151 #include "profiling.h"
152 #include "camera.h"
153 #include "main_loop_debug.h"
154 #include "main_loop_temp.h"
155 #include "main_loop_utilities.h"
158 ///////////
159 // USING //
160 ///////////
161 using namespace NLMISC;
162 using namespace NL3D;
163 using namespace NLPACS;
164 using namespace NLNET;
165 using namespace std;
167 #ifdef DEBUG_NEW
168 #define new DEBUG_NEW
169 #endif
174 ////////////
175 // EXTERN //
176 ////////////
177 extern UDriver *Driver;
178 extern UScene *Scene;
179 extern UScene *SceneRoot;
180 extern ULandscape *Landscape;
181 extern UCloudScape *CloudScape;
182 extern bool InitCloudScape;
183 extern CLandscapeIGManager LandscapeIGManager;
184 extern UTextContext *TextContext;
185 extern CEntityAnimationManager *EAM;
186 extern TTime UniversalTime;
187 extern UMaterial GenericMat;
188 extern UCamera MainCam;
189 extern CEventsListener EventsListener;
190 extern CMatrix MainSceneViewMatrix;
191 extern CMatrix InvMainSceneViewMatrix;
192 extern std::vector<UTextureFile*> LogoBitmaps;
193 extern bool IsInRingSession;
194 extern std::string UsedFSAddr;
196 // temp
197 extern NLMISC::CValueSmoother smoothFPS;
198 extern NLMISC::CValueSmoother moreSmoothFPS;
200 void loadBackgroundBitmap (TBackground background);
201 void destroyLoadingBitmap ();
202 void drawLoadingBitmap (float progress);
203 void updateStatReport ();
205 CFogState MainFogState;
206 CFogState RootFogState;
209 #define RYZOM_FIRST_FRAME_TO_SKIP 30
212 const float CANOPY_DEPTH_RANGE_START = 0.95f;
213 const float SKY_DEPTH_RANGE_START = 0.99f;
215 CRGBA ThunderColor;
217 float SimulatedServerDate = 0.f;
218 uint64 SimulatedServerTick = 0;
223 /////////////
224 // GLOBALS //
225 /////////////
226 bool game_exit = false;
227 bool ryzom_exit = false;
228 bool game_exit_request = false;
229 bool ryzom_exit_request = false;
230 bool paying_account_request = false;
231 bool paying_account_already_request = false;
232 bool game_exit_after_paying_account_request = false;
233 bool Render = true;
235 float MouseX; // Mouse pos X for the frame.
236 float MouseY; // Mouse pos Y for the frame.
237 float OldMouseX; // Mouse pos X of the last frame.
238 float OldMouseY; // Mouse pos Y of the last frame.
240 uint32 Width; // Width of the window.
241 uint32 Height; // Height of the window.
242 uint32 OldWidth; // Last Width of the window.
243 uint32 OldHeight; // Last Height of the window.
245 bool ShowInterface = true; // Do the Chat OSD have to be displayed.
246 bool DebugUIView = false;
247 bool DebugUICtrl = false;
248 bool DebugUIGroup = false;
249 std::string DebugUIFilter;
250 bool ShowHelp = false; // Do the Help have to be displayed.
251 uint8 ShowInfos = 0; // 0=no info 1=text info 2=graph info
253 bool bZeroCpu = false; // For no Cpu use if application is minimize TODO: intercept minimize message, called by CTRL + Z at this
255 bool MovieShooterSaving= false; // Are we in Shooting mode?
258 bool DisplayWeatherFunction = false;
260 // temp
261 float DelayBeforeCloudUpdate = 0.f; // delay in s before cloud state must be recomputed
262 const float CloudUpdatePeriod = 45.f; // period used for clouds update
264 TScreenshotRequest ScreenshotRequest = ScreenshotRequestNone;
267 // First frames to skip
268 bool FirstFrame = false;
269 uint SkipFrame = 0;
271 // temp : for timed fxs test
272 bool ShowTimedFX = false;
273 CTimedFXManager::TDebugDisplayMode ShowTimedFXMode = CTimedFXManager::NoText;
275 //CGraph FpsGraph ("frame rate (fps)", 10.0f, 110.0f, 100.0f, 100.0f, CRGBA(128,0,0,128), 1000, 60.0f);
276 //CGraph SpfGraph ("mspf", 10.0f, 10.0f, 100.0f, 100.0f, CRGBA(0,128,0,128), 0, 800.0f);
277 // TestYoyo
278 //CGraph CameraThirPersonGraph ("Camera Thir Person", 300.0f, 460.0f, 200.0f, 200.0f, CRGBA(0,64,128,128), 0, 5.0f, 1);
280 // DEBUG
281 bool PACSBorders = false;
282 bool ARKPACSBorders = false;
283 bool DebugClusters = false;
284 CVector LastDebugClusterCameraThirdPersonStart= CVector::Null;
285 CVector LastDebugClusterCameraThirdPersonEnd= CVector::Null;
286 CVector LastDebugClusterCameraThirdPersonTestStart= CVector::Null;
287 CVector LastDebugClusterCameraThirdPersonPelvisPos= CVector::Null;
288 CVector LastDebugClusterCameraThirdPersonResult= CVector::Null;
289 bool LastDebugClusterCameraThirdPersonForceFPV= false;
290 bool SoundBox = false;
291 CPing Ping;
292 sint CompassMode = 0; // 0: compass with regard to the user front, 1: to the camera direction.
294 float BanMsgCountdown = 0.f;
295 const float BanMsgRepeatTime = 5.f;
297 CGameContextMenu GameContextMenu;
303 static CRefPtr<CCDBNodeLeaf> s_FpsLeaf;
304 static CRefPtr<CCDBNodeLeaf> s_UiDirectionLeaf;
307 // Profile
309 0 : AllMeshNoVP
310 1 : AllMeshVP
311 2 : FX
312 3 : Landscape
313 4 : Vegetable
314 5 : Skeleton
315 6 : Water
316 7 : Cloud
317 8 : CoarseMesh*/
318 bool Filter3D[RYZOM_MAX_FILTER_3D] = {true, true, true, true, true, true, true, true, true, true};
319 bool Scene_Profile= false;
323 // Hierarchical timer
324 H_AUTO_DECL ( RZ_Client_Check_Actions )
325 H_AUTO_DECL ( RZ_Client_Main_Loop )
326 H_AUTO_DECL ( RZ_Client_Main_Loop_Zero_Cpu )
327 H_AUTO_DECL ( RZ_Client_Main_Loop_Cursor )
328 H_AUTO_DECL ( RZ_Client_Main_Loop_Time_Update )
329 H_AUTO_DECL ( RZ_Client_Main_Loop_Selection_FX )
330 H_AUTO_DECL ( RZ_Client_Main_Loop_Sky_And_Weather )
331 H_AUTO_DECL ( RZ_Client_Main_Loop_Render_Root )
332 H_AUTO_DECL ( RZ_Client_Main_Loop_Render_Main )
333 H_AUTO_DECL ( RZ_Client_Main_Loop_Anim_Cloud_Scape )
334 H_AUTO_DECL ( RZ_Client_Main_Loop_Update_Cloud_Scape )
335 H_AUTO_DECL ( RZ_Client_Main_Loop_Render_Cloud_Scape )
336 H_AUTO_DECL ( RZ_Client_Main_Loop_Debug )
337 H_AUTO_DECL ( RZ_Client_Main_Loop_Guild_Symbol )
338 H_AUTO_DECL ( RZ_Client_Main_Loop_Render_Thunder )
339 H_AUTO_DECL ( RZ_Client_Main_Loop_Interface )
340 H_AUTO_DECL ( RZ_Client_Main_Loop_Sound )
341 H_AUTO_DECL ( RZ_Client_Main_Loop_Net )
343 ///////////////
344 // FUNCTIONS //
345 ///////////////
347 //update the sound manager (listener pos, user walk/run sound...)
348 void updateSound();
350 void displaySpecialTextProgress(const char *text);
352 void endMovieShooting();
353 void updateMovieShooting();
355 void updateLightDesc();
356 void updateClouds();
358 void displayPACSBorders();
359 void displayPACSPrimitive();
360 void displaySoundBox();
361 void displayDebugClusters();
363 void displaySceneProfiles();
365 // validate current dialogs (end them if the player is too far from its interlocutor)
366 void validateDialogs(const CGameContextMenu &gcm);
369 // ***************************************************************************
371 enum TSkyMode { NoSky, OldSky, NewSky };
372 static TSkyMode s_SkyMode = NoSky;
374 void preRenderNewSky ()
376 CSky &sky = ContinentMngr.cur()->CurrentSky;
377 // setup fog, lighting & sky object. We use the same light direction than with the main scene
378 CClientDate cd = SmoothedClientDate;
379 if (ClientCfg.R2EDEnabled && R2::getEditor().getFixedLighting())
381 cd.Hour = 12.f;
383 sky.setup(cd, SmoothedClientDate, WeatherManager.getWeatherValue(), MainFogState.FogColor, Scene->getSunDirection(), false);
386 void commitCamera()
388 // Set the sky camera
389 if (s_SkyMode == NewSky)
391 CSky &sky = ContinentMngr.cur()->CurrentSky;
392 // setup camera
393 CFrustum frust = MainCam.getFrustum();
394 UCamera camSky = sky.getScene()->getCam();
395 sky.getScene()->setViewport(Scene->getViewport());
396 camSky.setTransformMode(UTransform::DirectMatrix);
397 // must have our own Far!!!
398 frust.Far= SkyCameraZFar;
399 camSky.setFrustum(frust);
400 CMatrix skyCameraMatrix;
401 skyCameraMatrix.identity();
402 skyCameraMatrix= MainCam.getMatrix();
403 skyCameraMatrix.setPos(CVector::Null);
404 camSky.setMatrix(skyCameraMatrix);
407 // Set The Root Camera
408 UCamera camRoot = SceneRoot->getCam();
409 if(!camRoot.empty())
411 // Update Camera Position/Rotation.
412 //camRoot.setPos(View.currentViewPos());
413 //camRoot.setRotQuat(View.currentViewQuat());
414 camRoot.setPos(MainCam.getPos());
415 camRoot.setRotQuat(MainCam.getRotQuat());
419 // ***************************************************************************
421 void beginRenderCanopyPart()
423 SceneRoot->beginPartRender();
425 void endRenderCanopyPart()
427 SceneRoot->endPartRender(false);
430 void beginRenderMainScenePart()
432 Scene->beginPartRender();
434 void endRenderMainScenePart(bool keepTraversals)
436 Scene->endPartRender(!keepTraversals, true, keepTraversals);
439 void beginRenderSkyPart()
441 if (s_SkyMode == NewSky)
443 CSky &sky = ContinentMngr.cur()->CurrentSky;
444 sky.getScene()->beginPartRender();
447 void endRenderSkyPart()
449 if (s_SkyMode == NewSky)
451 CSky &sky = ContinentMngr.cur()->CurrentSky;
452 sky.getScene()->endPartRender(false);
457 // ***************************************************************************************************************************
458 // Render a part of the canopy
459 static void renderCanopyPart(UScene::TRenderPart renderPart)
461 H_AUTO_USE ( RZ_Client_Main_Loop_Render_Root )
462 Driver->setDepthRange(CANOPY_DEPTH_RANGE_START, SKY_DEPTH_RANGE_START);
464 ContinentMngr.getFogState(CanopyFog, LightCycleManager.getLightLevel(), LightCycleManager.getLightDesc().DuskRatio, LightCycleManager.getState(), View.viewPos(), RootFogState);
465 RootFogState.setupInDriver(*Driver);
467 // Render the root scene
468 SceneRoot->renderPart(renderPart);
471 // ***************************************************************************************************************************
472 // Render a part of the main scene
473 static void renderMainScenePart(UScene::TRenderPart renderPart, bool wantTraversals, bool keepTraversals)
475 H_AUTO_USE ( RZ_Client_Main_Loop_Render_Main )
476 Driver->setDepthRange(0.f, CANOPY_DEPTH_RANGE_START);
477 if(ClientCfg.Fog == false )
479 Driver->enableFog (false);
481 else
483 MainFogState.setupInDriver (*Driver);
485 Scene->renderPart(renderPart, true, wantTraversals, keepTraversals);
489 // ***************************************************************************************************************************
490 // Render a part of the sky
491 static void renderSkyPart(UScene::TRenderPart renderPart)
493 nlassert(s_SkyMode != NoSky);
494 Driver->setDepthRange(SKY_DEPTH_RANGE_START, 1.f);
495 Driver->enableFog(false);
496 if (s_SkyMode == NewSky)
498 CSky &sky = ContinentMngr.cur()->CurrentSky;
499 sky.getScene()->renderPart(renderPart);
501 else
503 // old style sky
504 renderSky(LightCycleManager, MainFogState.FogColor);
506 #ifdef RENDER_CLOUDS
507 if (CloudScape != NULL && Filter3D[FilterCloud])
509 H_AUTO_USE( RZ_Client_Main_Loop_Render_Cloud_Scape )
510 CloudScape->render ();
512 #endif
515 // ***************************************************************************************************************************
516 // Utility to force full detail
517 struct CForceFullDetail
519 public:
520 void backup()
522 maxFullDetailChar = Scene->getMaxSkeletonsInNotCLodForm();
523 oldBalancingMode = Scene->getPolygonBalancingMode();
524 oldSkyBalancingMode = UScene::PolygonBalancingOff;
525 UScene *skyScene = getSkyScene();
526 if (skyScene) oldSkyBalancingMode = skyScene->getPolygonBalancingMode();
528 void set()
530 Scene->setMaxSkeletonsInNotCLodForm(1000000);
531 Scene->setPolygonBalancingMode(UScene::PolygonBalancingOff);
532 UScene *skyScene = getSkyScene();
533 if (skyScene) skyScene->setPolygonBalancingMode(UScene::PolygonBalancingOff);
535 void restore()
537 Scene->setMaxSkeletonsInNotCLodForm(maxFullDetailChar);
538 Scene->setPolygonBalancingMode(oldBalancingMode);
539 UScene *skyScene = getSkyScene();
540 if (skyScene) skyScene->setPolygonBalancingMode(oldSkyBalancingMode);
542 private:
543 uint maxFullDetailChar;
544 UScene::TPolygonBalancingMode oldBalancingMode;
545 UScene::TPolygonBalancingMode oldSkyBalancingMode;
547 static CForceFullDetail s_ForceFullDetail;
549 void clearBuffers()
551 if (Render)
553 if (Driver->getPolygonMode() == UDriver::Filled)
555 Driver->clearZBuffer();
558 // Sky is used to clear the frame buffer now, but if in line or point polygon mode, we should draw it
559 if (Driver->getPolygonMode() != UDriver::Filled || !Filter3D[FilterSky])
561 if (!Driver->isLost())
563 Driver->clearBuffers (ClientCfg.BGColor);
567 else
569 Driver->clearBuffers(ClientCfg.BGColor);
573 void renderScene(bool forceFullDetail, bool bloom)
575 CTextureUser *effectRenderTarget = NULL;
576 if (bloom)
578 // set bloom parameters before applying bloom effect
579 CBloomEffect::getInstance().setSquareBloom(ClientCfg.SquareBloom);
580 CBloomEffect::getInstance().setDensityBloom((uint8)ClientCfg.DensityBloom);
582 // init effect render target
583 Driver->beginDefaultRenderTarget();
585 if (forceFullDetail)
587 s_ForceFullDetail.backup();
588 s_ForceFullDetail.set();
590 clearBuffers();
591 doRenderScene(true, false);
592 if (forceFullDetail)
594 s_ForceFullDetail.restore();
596 if (bloom)
598 // apply bloom effect
599 CBloomEffect::getInstance().applyBloom();
601 // draw final result to backbuffer
602 Driver->endDefaultRenderTarget(Scene);
606 // ***************************************************************************************************************************
608 void updateWaterEnvMap()
610 #ifdef USE_WATER_ENV_MAP
611 if (WaterEnvMapRefCount > 0) // water env map needed
613 if (!WaterEnvMap)
615 CSky &sky = ContinentMngr.cur()->CurrentSky;
616 if (sky.getScene())
618 nlassert(WaterEnvMapSkyCam.empty());
619 WaterEnvMapSkyCam = sky.getScene()->createCamera(); // deleted in unselect
620 nlassert(WaterEnvMapCanopyCam.empty());
621 WaterEnvMapCanopyCam = SceneRoot->createCamera(); // deleted in unselect
622 // Create water env map if not already created
623 WaterEnvMap = Driver->createWaterEnvMap();
624 if(WaterEnvMap)
626 WaterEnvMap->init(128, 256, ClientCfg.WaterEnvMapUpdateTime);
627 WaterEnvMap->setWaterEnvMapRenderCallback(&WaterEnvMapRdr);
628 Scene->setWaterEnvMap(WaterEnvMap);
632 WaterEnvMapRdr.CurrDate = SmoothedClientDate;
633 WaterEnvMapRdr.AnimationDate = SmoothedClientDate;
634 if (ClientCfg.R2EDEnabled && R2::getEditor().getFixedLighting())
636 WaterEnvMapRdr.CurrDate.Hour = 12.f;
638 WaterEnvMapRdr.CurrFogColor = MainFogState.FogColor;
639 WaterEnvMapRdr.CurrTime = TimeInSec - FirstTimeInSec;
640 WaterEnvMapRdr.CurrWeather = WeatherManager.getWeatherValue();
641 CSky &sky = ContinentMngr.cur()->CurrentSky;
642 WaterEnvMap->setAlpha(sky.getWaterEnvMapAlpha());
643 Scene->updateWaterEnvMaps(TimeInSec - FirstTimeInSec);
645 #endif
648 // ***************************************************************************************************************************
650 void updateWeather()
652 H_AUTO_USE ( RZ_Client_Main_Loop_Sky_And_Weather )
654 //HeightGrid.update(Scene->getCam().getPos());
656 // update description of light cycle
657 updateLightDesc();
659 // server driven weather mgt
660 updateDBDrivenWeatherValue();
662 // Update the weather manager
663 updateWeatherManager(MainCam.getMatrix(), ContinentMngr.cur());
665 // compute thunder color
666 ThunderColor.modulateFromui(WeatherManager.getCurrWeatherState().ThunderColor, (uint) (256.f * WeatherManager.getThunderLevel()));
668 // Update the lighting
669 LightCycleManager.setHour(DayNightCycleHour, WeatherManager, ThunderColor);
671 #ifdef RENDER_CLOUDS
672 if (Filter3D[FilterCloud])
674 H_AUTO_USE ( RZ_Client_Main_Loop_Update_Cloud_Scape );
675 updateClouds();
677 #endif
679 ContinentMngr.getFogState(MainFog, LightCycleManager.getLightLevel(), LightCycleManager.getLightDesc().DuskRatio, LightCycleManager.getState(), View.viewPos(), MainFogState);
681 // TODO: ZBuffer clear was originally before this, but should not be necessary normally.
682 // The anim function renders new clouds. Ensure this does not break.
683 // These are old-style nel clouds.
685 #ifdef RENDER_CLOUDS
686 if (CloudScape != NULL && Filter3D[FilterCloud])
688 H_AUTO_USE ( RZ_Client_Main_Loop_Anim_Cloud_Scape );
690 Driver->enableFog (false);
692 // Force polygon mode to filled
693 NL3D::UDriver::TPolygonMode oldMode = Driver->getPolygonMode();
694 Driver->setPolygonMode(NL3D::UDriver::Filled);
696 CloudScape->anim (DT); // WARNING this function work with screen
698 Driver->enableFog (true);
700 // Reset backuped polygon mode
701 Driver->setPolygonMode(oldMode);
703 #endif
705 // Update new sky
706 s_SkyMode = NoSky;
707 if (ContinentMngr.cur() && !ContinentMngr.cur()->Indoor)
709 if(Driver->getPolygonMode() == UDriver::Filled)
711 if (Filter3D[FilterSky])
713 CSky &sky = ContinentMngr.cur()->CurrentSky;
714 if (sky.getScene())
716 s_SkyMode = NewSky;
717 sky.getScene()->animate(TimeInSec-FirstTimeInSec);
718 // Setup the sky camera
719 preRenderNewSky();
721 else
723 s_SkyMode = OldSky;
730 void beginRenderScene()
732 // Update Filter Flags
733 Scene->enableElementRender(UScene::FilterAllMeshNoVP, Filter3D[FilterMeshNoVP]);
734 Scene->enableElementRender(UScene::FilterAllMeshVP, Filter3D[FilterMeshVP]);
735 Scene->enableElementRender(UScene::FilterFX, Filter3D[FilterFXs]);
736 Scene->enableElementRender(UScene::FilterLandscape, Filter3D[FilterLandscape]);
737 Scene->enableElementRender(UScene::FilterSkeleton, Filter3D[FilterSkeleton]);
738 Scene->enableElementRender(UScene::FilterWater, Filter3D[FilterWater]);
739 Scene->enableElementRender(UScene::FilterCoarseMesh, Filter3D[FilterCoarseMesh]);
741 // profile this frame?
742 if(Scene_Profile)
743 Scene->profileNextRender();
745 // initialisation of polygons renderer
746 CLandscapePolyDrawer::getInstance().beginRenderLandscapePolyPart();
748 // Start Part Rendering
749 beginRenderCanopyPart();
750 beginRenderMainScenePart();
751 beginRenderSkyPart();
754 void drawRenderScene(bool wantTraversals, bool keepTraversals)
756 // Render part
757 // WARNING: always must begin rendering with at least UScene::RenderOpaque,
758 // else dynamic shadows won't work
759 renderCanopyPart(UScene::RenderOpaque);
760 renderMainScenePart(UScene::RenderOpaque, wantTraversals, keepTraversals);
762 // render of polygons on landscape
763 CLandscapePolyDrawer::getInstance().renderLandscapePolyPart();
765 if (s_SkyMode != NoSky) renderSkyPart((UScene::TRenderPart) (UScene::RenderOpaque | UScene::RenderTransparent));
766 renderCanopyPart((UScene::TRenderPart) (UScene::RenderTransparent | UScene::RenderFlare));
767 renderMainScenePart((UScene::TRenderPart) (UScene::RenderTransparent | UScene::RenderFlare), wantTraversals, keepTraversals);
768 if (s_SkyMode == NewSky) renderSkyPart(UScene::RenderFlare);
771 void endRenderScene(bool keepTraversals)
773 // End Part Rendering
774 endRenderSkyPart();
775 endRenderMainScenePart(keepTraversals);
776 endRenderCanopyPart();
778 // reset depth range
779 Driver->setDepthRange(0.f, CANOPY_DEPTH_RANGE_START);
782 // ***************************************************************************************************************************
783 // Render all scenes
784 void doRenderScene(bool wantTraversals, bool keepTraversals)
786 beginRenderScene();
787 drawRenderScene(wantTraversals, keepTraversals);
788 endRenderScene(keepTraversals);
792 // ***************************************************************************
793 class CMusicFader
795 public:
796 uint NFrameSkip;
797 float TotalTime;
798 bool Done;
800 public:
801 CMusicFader(uint nframeToSkip, float fadeTime)
803 NFrameSkip= nframeToSkip;
804 // avoid div by zero
805 fadeTime= max(fadeTime, 0.01f);
806 TotalTime= fadeTime;
807 Done= false;
810 void fade();
812 void CMusicFader::fade()
814 // ended?
815 if(NFrameSkip==0 && Done)
816 return;
818 // else fade
819 if(NFrameSkip==0)
821 // stop music (slow fade out of 3 secondes)
822 if(SoundMngr)
823 SoundMngr->stopMusic(uint(TotalTime*1000));
824 Done= true;
826 else
827 NFrameSkip--;
830 // ***************************************************************************
831 void updateGameQuitting()
833 static sint64 firstTimeLostConnection= 0;
835 // Yoyo: prefer now leave the user press "Quit Now" if don't want to wait server
837 // if want quiting, and if server stalled, quit now
838 if(game_exit_request)
840 // abort until 10 seconds if connection lost
841 if(!NetMngr.getConnectionQuality())
843 if(!firstTimeLostConnection)
844 firstTimeLostConnection= T1;
846 else
848 firstTimeLostConnection= 0;
851 // if connection lost until 10 seconds
852 if(firstTimeLostConnection && T1-firstTimeLostConnection > 10000)
854 game_exit= true;
855 ryzom_exit= ryzom_exit_request;
858 else
860 // reset
861 firstTimeLostConnection= 0;
864 // update the window
865 CInterfaceManager *pIM= CInterfaceManager::getInstance();
867 CInterfaceGroup *group= dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:free_trial_game_quitting"));
868 if(group)
870 // if Free trial
871 if(paying_account_request)
873 // if no current modal window, or if not the quit window
874 if(group != CWidgetManager::getInstance()->getModalWindow())
876 // disable
877 CWidgetManager::getInstance()->disableModalWindow();
878 CWidgetManager::getInstance()->enableModalWindow(NULL, group);
882 else
884 // if the current modal window is the quit window, disable
885 if(group == CWidgetManager::getInstance()->getModalWindow())
887 // disable
888 CWidgetManager::getInstance()->disableModalWindow();
893 group= dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:game_quitting"));
894 if(group)
896 // if exit request
897 if(game_exit_request && !paying_account_request)
899 // if no current modal window, or if not the quit window
900 if(group != CWidgetManager::getInstance()->getModalWindow())
902 // disable
903 CWidgetManager::getInstance()->disableModalWindow();
904 CWidgetManager::getInstance()->enableModalWindow(NULL, group);
906 bool farTPing = FarTP.isFarTPInProgress();
907 // Far TP: skipping not allowed (because we can't duplicate the avatar...), anyway the quit button would quit the game (no far tp)
908 CInterfaceElement *quitNowButton = group->getElement(group->getId() + ":indent_middle:ryzom");
909 if (quitNowButton)
910 quitNowButton->setActive(!farTPing);
911 // From ring session or from mainland's ring access point: cancelling not allowed (would lead to inconsistencies with the SU & DSS)
912 CInterfaceElement *backToGame = group->getElement(group->getId() + ":indent_middle:cancel");
913 if (backToGame)
914 backToGame->setActive(!(farTPing && (IsInRingSession || FarTP.isFastDisconnectGranted())));
915 CInterfaceElement *quittingRules = group->getElement(group->getId() + ":text_mean");
916 if (quittingRules)
917 quittingRules->setActive(!farTPing);
918 CInterfaceElement *quittingText = group->getElement(group->getId() + ":text");
919 if (quittingText)
920 quittingText->setActive(!farTPing);
923 // else
924 else
926 // if the current modal window is the quit window, disable
927 if(group == CWidgetManager::getInstance()->getModalWindow())
929 // disable
930 CWidgetManager::getInstance()->disableModalWindow();
937 void setDefaultChatWindow(CChatWindow *defaultChatWindow)
939 if (defaultChatWindow)
941 CInterfaceManager *im = CInterfaceManager::getInstance();
942 if (defaultChatWindow->getContainer())
944 CInterfaceGroup *ig = defaultChatWindow->getContainer()->getGroup("eb");
945 if (ig) CWidgetManager::getInstance()->setDefaultCaptureKeyboard(ig);
950 void updateDayNightCycleHour()
952 if (ClientCfg.R2EDEnabled && R2::getEditor().getFixedLighting())
954 DayNightCycleHour = 12.f;
956 else
958 // if there's a forced time, apply it
959 if( ForcedDayNightCycleHour < 0 )
960 DayNightCycleHour = (float)RT.getRyzomTime();
961 else
962 DayNightCycleHour = ForcedDayNightCycleHour;
967 // ***************************************************************************
968 //---------------------------------------------------
969 // mainLoop :
970 // Main loop of the application (displayer, input, ...).
971 // Return true to exit the game, false to return to character selection
972 //---------------------------------------------------
973 bool mainLoop()
975 resetIngameTime ();
977 NLMISC::TTime initStart = ryzomGetLocalTime();
978 NLMISC::TTime initLast = initStart;
979 NLMISC::TTime initCurrent = initLast;
981 game_exit = false;
982 game_exit_request = false;
983 paying_account_request = false;
984 paying_account_already_request = false;
985 game_exit_after_paying_account_request = false;
986 FarTP.setMainLoopEntered();
988 nlinfo ("Starting main loop...", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
990 // Get the Width and Height of the window and set the Old values..
991 Driver->getWindowSize(Width, Height);
992 OldWidth = Width; OldHeight = Height;
994 CGraph::init( Driver );
995 CGraph::Display = false;
997 T1 = ryzomGetLocalTime (); //(sint64)CGDTime::getTime (); // \todo GUIGUI : VOIR COMMENT MANAGER LE TEMPS
998 TSend = ((T1+DTSend)/DTSend)*DTSend;
1000 // initialize the structure for the ping.
1001 Ping.init();
1003 // Call a function for a demo to init.
1005 if (ClientCfg.Local)
1007 if (!ClientCfg.Light)
1008 initDemo();
1011 // Get the Connection State.
1012 CNetworkConnection::TConnectionState lastConnectionState = CNetworkConnection::Connected;
1013 CNetworkConnection::TConnectionState connectionState = NetMngr.getConnectionState();
1015 updateLightDesc();
1017 SetMouseFreeLook ();
1018 SetMouseCursor ();
1019 // Set the cursor.
1020 ContextCur.context("STAND BY");
1021 UserControls.reset();
1023 // set the default box for keyboard
1024 setDefaultChatWindow(PeopleInterraction.ChatGroup.Window);
1027 // Init GameContextMenu.
1028 GameContextMenu.init("");
1030 // Active inputs
1031 Actions.enable(true);
1032 EditActions.enable(true);
1034 // For stoping the outgame music, start after 30 frames, and duration of 3 seconds
1035 CMusicFader outgameFader(60, 3);
1038 // check for banned player
1039 if (testPermanentBanMarkers())
1041 setPermanentBanMarkers(true); // re-set any marker that could have been removed by the trouble maker
1042 applyPermanentBanPunishment();
1043 PermanentlyBanned = true;
1047 CNiceInputAuto niceInputs;
1048 // R2 editor and modules
1049 R2::getEditor().autoConfigInit(IsInRingSession);
1051 if (ClientCfg.BeepWhenLaunched)
1053 beep( 680, 400 );
1054 beep( 440, 400 );
1055 Driver->showWindow();
1058 FPU_CHECKER_ONCE
1060 CurrSeason = computeCurrSeason();
1062 initLast = initCurrent;
1063 initCurrent = ryzomGetLocalTime();
1064 nlinfo ("PROFILE: %d seconds (%d total) for Starting main loop", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000);
1066 if (ClientCfg.R2EDEnabled && !ClientCfg.Local)
1068 R2::getEditor().waitScenario();
1071 CSessionBrowserImpl::getInstance().init(CLuaManager::getInstance().getLuaState());
1074 CLuaManager::getInstance().executeLuaScript("game:onMainLoopBegin()");
1077 if (StartInitTime != 0)
1079 CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_InGameEntry, "login_step_game_entry&load_time=" + toString((NLMISC::CTime::getLocalTime() - StartInitTime) / 1000)));
1080 StartInitTime = 0;
1083 ProgressBar.finish();
1085 bool musicTriggerAutoPlay = true;
1087 // Main loop. If the window is no more Active -> Exit.
1088 while( !UserEntity->permanentDeath()
1089 && !game_exit )
1091 // If an action handler execute. NB: MUST BE DONE BEFORE ANY THING ELSE PROFILE CRASH!!!!!!!!!!!!!!!!!
1092 testLaunchProfile();
1094 // Test and may run a VBLock profile (only once)
1095 testLaunchProfileVBLock();
1097 // Start Bench
1098 H_AUTO_USE ( RZ_Client_Main_Loop )
1100 #ifdef RYZOM_BG_DOWNLOADER
1101 if (isBGDownloadEnabled())
1103 CBGDownloaderAccess &bgDownloader = CBGDownloaderAccess::getInstance();
1104 // if the ui is frozen, wait for a few frame to allow client to do first frame load,
1105 // without having to compete with the downloader frame
1106 if (!FirstFrame && bgDownloader.isDownloaderUIFrozen() && SkipFrame == 0)
1108 unpauseBGDownloader();
1111 #endif
1113 FPU_CHECKER_ONCE
1115 EGSPD::CSeason::TSeason newLocalSeason = computeCurrSeason();
1116 if (newLocalSeason != CurrSeason)
1118 LoadingBackground= TeleportKaravanBackground;
1119 beginLoading (LoadingBackground);
1120 extern void selectTipsOfTheDay (uint tips);
1121 selectTipsOfTheDay (rand());
1122 UseEscapeDuringLoading = false;
1124 #define BAR_STEP_TP 2
1125 ProgressBar.reset (BAR_STEP_TP);
1126 string nmsg("Loading...");
1127 ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
1128 ProgressBar.progress(0);
1129 ContinentMngr.select(UserEntity->pos(), ProgressBar);
1130 ProgressBar.finish();
1131 CurrSeason = newLocalSeason;
1134 if (ClientCfg.R2EDEnabled)
1136 if (R2::ResetWanted)
1138 R2::getEditor().reset();
1139 R2::ResetWanted = false;
1142 if (R2::ResetScenarioWanted)
1144 R2::getEditor().resetScenario();
1145 R2::ResetScenarioWanted = false;
1147 if (R2::ReloadScenarioWanted)
1149 R2::getEditor().reloadScenario();
1150 R2::ReloadScenarioWanted = false;
1156 if (PermanentlyBanned)
1158 if (UserEntity)
1160 UserEntity->runVelocity(0);
1161 UserEntity->walkVelocity(0);
1163 BanMsgCountdown -= DT;
1164 if (BanMsgCountdown < 0.f)
1166 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1167 string msg = CI18N::get("msgPermanentlyBanned");
1168 string cat = getStringCategory(msg, msg);
1169 pIM->displaySystemInfo(msg, cat);
1170 BanMsgCountdown = BanMsgRepeatTime;
1176 // Stop the Outgame music, with fade effect
1177 outgameFader.fade();
1179 // update quit feature
1180 updateGameQuitting();
1182 // update module manager
1183 NLNET::IModuleManager::getInstance().updateModules();
1185 if (ClientCfg.R2EDEnabled)
1187 R2::getEditor().getDMC().flushActions();
1189 if (UserEntity) { UserEntity->updateNpcContolSpeed(); }
1193 // update outpost stuff
1194 OutpostManager.update();
1197 // flush observers
1198 IngameDbMngr.flushObserverCalls();
1199 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1203 EventsListener.setUIHandledButtonMask(NLMISC::noButton);
1205 // Fast mode.
1206 if(bZeroCpu)
1208 H_AUTO_USE ( RZ_Client_Main_Loop_Zero_Cpu )
1210 // Grab Inputs.
1211 CInputHandlerManager::getInstance()->pumpEventsNoIM();
1214 // NetWork Update.
1215 NetMngr.update();
1216 IngameDbMngr.flushObserverCalls();
1217 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1218 // lets some CPU.
1219 NetMngr.send();
1220 nlSleep(100);
1221 // End of the frame.
1226 continue;
1229 CSessionBrowserImpl::getInstance().update();
1231 //////////////////////////
1232 // INITIALIZE THE FRAME //
1233 //////////////////////////
1234 CInterfaceManager *pIMinstance;
1237 if (ClientCfg.IsInvalidated)
1238 updateFromClientCfg();
1241 // Update the event listener
1242 EventsListener.update ();
1246 EventsListener.updateMouseSmoothing(); // IMPORTANT: this should be called before updateClientTime && events handling in the frame
1249 // Update Time.
1250 updateClientTime();
1253 // Grab Inputs.
1254 CInputHandlerManager::getInstance()->pumpEvents();
1256 CLandscapePolyDrawer::getInstance().deletePolygons();
1257 CDecalRenderList::getInstance().clearRenderList();
1260 // Update the Interface Manager Events.
1261 pIMinstance = CInterfaceManager::getInstance();
1264 // NB: must update frame events, even if ShowInterface==0, else may OutOfMemory (cause vector<> never cleared).
1265 pIMinstance->updateFrameEvents ();
1268 if ((ContinentMngr.cur()) && (UserEntity != NULL))
1269 ContinentMngr.cur()->FoW.explore((float)UserEntity->pos().x, (float)UserEntity->pos().y);
1271 // Check if the window size has changed.
1272 OldWidth = Width; OldHeight = Height;
1273 Driver->getWindowSize(Width, Height);
1276 // if yes, must update the camera perspective
1277 if(OldWidth!=Width || OldHeight!=Height)
1278 updateCameraPerspective();
1280 // Get Mouse Position.
1281 OldMouseX = MouseX; OldMouseY = MouseY;
1283 #ifdef RYZOM_BG_DOWNLOADER
1284 updateBGDownloaderUI();
1285 #endif
1288 // Get the pointer pos
1289 if(pIMinstance)
1291 H_AUTO_USE ( RZ_Client_Main_Loop_Cursor )
1293 // Change only if screen is not minimized
1294 if(!CViewRenderer::getInstance()->isMinimized())
1296 // Get the cursor instance
1297 CViewPointer *cursor = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
1298 if(cursor)
1300 // Get the pointer position (in pixel)
1301 sint32 x, y;
1302 cursor->getPointerPos(x, y);
1304 uint32 w, h;
1305 CViewRenderer &viewRender = *CViewRenderer::getInstance();
1306 viewRender.getScreenSize(w, h);
1308 if(w)
1309 MouseX = (float)x/(float)w;
1310 else
1311 MouseX = 0;
1312 if(h)
1313 MouseY = (float)y/(float)h;
1314 else
1315 MouseY = 0;
1320 ///////////////////////
1321 // PROCESS THE FRAME //
1322 ///////////////////////
1323 // NetWork Update.
1327 NetMngr.update();
1328 IngameDbMngr.flushObserverCalls();
1329 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1330 bool prevDatabaseInitStatus = IngameDbMngr.initInProgress();
1331 IngameDbMngr.setChangesProcessed();
1332 bool newDatabaseInitStatus = IngameDbMngr.initInProgress();
1333 if ((!newDatabaseInitStatus) && prevDatabaseInitStatus)
1335 // When database received, activate allegiance buttons (for neutral state) in fame window
1336 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1337 CInterfaceGroup *group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:fame:content:you"));
1338 if (group)
1339 group->updateAllLinks();
1340 // send a msg to lua for specific ui update
1341 CLuaManager::getInstance().executeLuaScript("game:onInGameDbInitialized()");
1346 // For Debug (after netmngr update). Log entity stage change.
1347 EntitiesMngr.logStageChange(T1);
1349 // Update Ryzom Time.
1351 H_AUTO_USE ( RZ_Client_Main_Loop_Time_Update )
1352 if (!ClientCfg.Local)
1354 if(NetMngr.getCurrentServerTick() > LastGameCycle)
1355 RT.updateRyzomClock(NetMngr.getCurrentServerTick());
1357 else if (ClientCfg.SimulateServerTick)
1359 SimulatedServerDate += DT;
1360 uint numTicks = (uint) floor(SimulatedServerDate * 10);
1361 SimulatedServerTick += numTicks;
1362 SimulatedServerDate = (float)((double)SimulatedServerDate - (double) numTicks * 0.1);
1363 RT.updateRyzomClock((uint32)SimulatedServerTick);
1367 updateDayNightCycleHour();
1371 updateSmoothedTime();
1373 if (!ClientCfg.Light)
1375 // Call a function for a demo to update.
1376 if(ClientCfg.Local)
1378 updateDemo( (double)(T1-T0)*0.001 );
1382 // R2ED pre render update
1383 if (ClientCfg.R2EDEnabled)
1385 R2::getEditor().updatePreCamera();
1389 * Update position of all the primitives. Make a PACS move.
1391 EntitiesMngr.updatePreCamera();
1393 // Snap the user entity on the ground
1394 UserEntity->snapToGround();
1397 // update bot chat
1398 CBotChatManager::getInstance()->update();
1399 IngameDbMngr.flushObserverCalls();
1400 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1402 // updateItemEdition
1403 CInterfaceItemEdition::getInstance()->update();
1406 * Update user controls and compute the camera position
1408 UserControls.update();
1410 // Update Landscape RefineCenter
1411 if (Landscape) Landscape->setRefineCenterUser(View.refinePos());
1413 // Update camera recorder, possibly replacing current view
1414 updateCameraRecorder();
1416 // Update Camera Position/Orientation.
1417 CVector currViewPos = View.currentViewPos();
1418 MainCam.setTransformMode(UTransformable::RotQuat);
1420 CVector cameraMoves = UserEntity->getCameraMoves();
1422 currViewPos.z += cameraMoves.z;
1423 MainCam.setPos(currViewPos);
1424 MainCam.setRotQuat(View.currentViewQuat());
1426 if (cameraMoves.x)
1428 CMatrix viewMatrix;
1429 viewMatrix = MainCam.getMatrix();
1430 viewMatrix.rotateZ(cameraMoves.x);
1431 MainCam.setRotQuat(viewMatrix.getRot());
1434 UserEntity->setCameraMoves(CVector(0, 0, 0));
1436 if (StereoHMD)
1438 CMatrix camMatrix;
1439 camMatrix.translate(MainCam.getMatrix().getPos());
1440 CVector dir = MainCam.getMatrix().getJ();
1441 dir.z = 0;
1442 dir.normalize();
1443 if (dir.y < 0)
1444 camMatrix.rotateZ(float(NLMISC::Pi+asin(dir.x)));
1445 else
1446 camMatrix.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x)));
1448 StereoHMD->setInterfaceMatrix(camMatrix);
1450 NLMISC::CQuat hmdOrient = StereoHMD->getOrientation();
1451 // NLMISC::CMatrix camMatrix = MainCam.getMatrix();
1452 NLMISC::CMatrix hmdMatrix;
1453 hmdMatrix.setRot(hmdOrient);
1454 NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future
1455 posMatrix.translate(StereoHMD->getEyePosition());
1456 NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix);
1457 MainCam.setPos(mat.getPos());
1458 MainCam.setRotQuat(mat.getRot());
1460 if (true) // TODO: ClientCfg.Headphone
1462 // NOTE: non-(StereoHMD+Headphone) impl in user_entity.cpp
1463 SoundMngr->setListenerPos(mat.getPos()); // TODO: Move ears back ... :)
1464 SoundMngr->setListenerOrientation(mat.getJ(), mat.getK());
1467 if (StereoDisplay)
1469 StereoDisplay->updateCamera(0, &MainCam);
1470 if (SceneRoot)
1472 UCamera cam = SceneRoot->getCam();
1473 StereoDisplay->updateCamera(1, &cam);
1477 // see if camera is below water (useful for sort order)
1478 if (ContinentMngr.cur())
1480 float waterHeight;
1481 bool splashEnabled;
1482 if (ContinentMngr.cur()->WaterMap.getWaterHeight(CVector2f(currViewPos.x, currViewPos.y), waterHeight, splashEnabled))
1484 // camera is above / below a water surface
1485 Scene->setLayersRenderingOrder(currViewPos.z > waterHeight);
1486 UserEntity->setOrderingLayer(currViewPos.z > waterHeight ? 0 : 2);
1488 else
1490 UserEntity->setOrderingLayer(2);
1491 Scene->setLayersRenderingOrder(true);
1495 // Build the camera clipping planes
1496 vector<CPlane> planes;
1497 buildCameraClippingPyramid (planes);
1500 * Clip the entities.
1501 * Update display for visible entities.
1502 * Update display for clipped entities at a lower frequency.
1504 static uint clippedUpdateTime = 0;
1505 EntitiesMngr.updatePostCamera(clippedUpdateTime, planes, MainCam.getPos());
1506 clippedUpdateTime++;
1507 clippedUpdateTime&=RZ_CLIPPED_UPDATE_TIME_MASK;
1509 // Update the position for the vision.
1510 NetMngr.setReferencePosition(UserEntity->pos());
1512 // For Debug (after entities update). Log entity stage change.
1513 EntitiesMngr.logStageChange(T1);
1515 if (!ClientCfg.Light)
1517 // Animate all the playlists
1518 EAM->setup (TimeInSec);
1522 // update the sound of the player (walk, run....) if sound is allocated.
1523 updateSound();
1525 if (Landscape)
1527 if (!ClientCfg.Light)
1529 // Not in an indoor ?
1530 if (ContinentMngr.cur() && !ContinentMngr.cur()->Indoor)
1532 // Load Zone in streaming according to the refine position (not necessarily the User Position);
1533 string zoneAdded, zoneRemoved;
1534 const R2::CScenarioEntryPoints::CCompleteIsland *ci = R2::CScenarioEntryPoints::getInstance().getCompleteIslandFromCoords(CVector2f((float) UserEntity->pos().x, (float) UserEntity->pos().y));
1535 Landscape->refreshZonesAround(View.refinePos(), ClientCfg.Vision + ExtraZoneLoadingVision, zoneAdded, zoneRemoved, ci ? &(ci->ZoneIDs) : NULL);
1536 LandscapeIGManager.loadZoneIG(zoneAdded);
1537 LandscapeIGManager.unloadZoneIG(zoneRemoved);
1542 // Update PACS
1543 if(GR)
1544 GR->refreshLrAround (View.refinePos(), LRRefeshRadius);
1546 // load / unload streamable obj (villages ...)
1547 if (ClientCfg.VillagesEnabled)
1549 ContinentMngr.updateStreamable(View.refinePos());
1552 if (!ClientCfg.Light)
1554 // Load / unload streaming Instances textures.
1555 Driver->updateAsyncTexture();
1557 // Manage Fx
1558 manageFxEntities();
1560 // Animate all systems in scene.
1561 Scene->animate(TimeInSec-FirstTimeInSec);
1566 if (!ClientCfg.Light)
1568 CClientDate newDate(RT.getRyzomDay(), DayNightCycleHour);
1569 if (newDate < CTimedFXManager::getInstance().getDate() ||
1570 abs((sint32)RT.getRyzomDay() - CTimedFXManager::getInstance().getDate().Day) > 1)
1572 // The manager make the assumption that no more than one day can occurs between 2 ticks
1573 // This only happens when date is changed manually
1574 if (IGCallbacks)
1576 IGCallbacks->changeSeason(); // the season doesn't change, but this force fxs to be recreated
1579 CTimedFXManager::getInstance().update(newDate, CurrSeason, Scene->getCam().getPos());
1581 CProjectileManager::getInstance().update();
1583 // temp temp : for debug
1584 //TestGroundFX.update();
1588 // Set the right camera cluster.
1589 if(GR)
1591 UInstanceGroup *pPlayerClusterSystem = NULL;
1593 // Normal Mode
1594 if(UserControls.mode() != CUserControls::ThirdMode)
1596 // get the Pacs global position of the camera
1597 UGlobalPosition gPos;
1598 if((UserControls.mode() != CUserControls::AIMode)
1599 && UserEntity->getPrimitive())
1600 UserEntity->getPrimitive()->getGlobalPosition(gPos, dynamicWI);
1601 else
1602 gPos = GR->retrievePosition(View.viewPos());
1604 // get the cluster IG associated to this pacs position
1605 pPlayerClusterSystem = getCluster(gPos);
1606 MainCam.setClusterSystem(pPlayerClusterSystem);
1608 // important to update this each frame, for shadow map consideration against the "matis serre bug"
1609 CollisionManager->setPlayerInside(pPlayerClusterSystem!=NULL);
1611 // Camera 3rd person complex mode
1612 else
1614 UGlobalPosition gPos;
1615 if(UserEntity->getPrimitive())
1616 UserEntity->getPrimitive()->getGlobalPosition(gPos, dynamicWI);
1617 // get the cluster IG associated to this pacs position
1618 pPlayerClusterSystem = getCluster(gPos);
1620 // set the one found in CView::updateCameraCollision()
1621 MainCam.setClusterSystem(View.getThirdPersonClusterSystem());
1623 // important to update this each frame, for shadow map consideration against the "matis serre bug"
1624 CollisionManager->setPlayerInside(pPlayerClusterSystem!=NULL);
1626 // For debug only
1627 View.getCamera3rdPersonSetup(LastDebugClusterCameraThirdPersonStart,
1628 LastDebugClusterCameraThirdPersonEnd,
1629 LastDebugClusterCameraThirdPersonTestStart);
1630 LastDebugClusterCameraThirdPersonResult= View.currentViewPos();
1631 LastDebugClusterCameraThirdPersonPelvisPos= View.viewPos() + CVector(0.f,0.f,1.f);
1632 LastDebugClusterCameraThirdPersonForceFPV= View.forceFirstPersonView();
1633 // TestYoyo
1634 //CameraThirPersonGraph.addOneValue ((startPos - endPos).norm());
1637 // If we are flushing open all doors
1638 if (SkipFrame > 0)
1640 // update only the cluster system where the player is!
1641 if (pPlayerClusterSystem != NULL)
1643 static vector<string> PortalsName;
1644 PortalsName.clear();
1645 pPlayerClusterSystem->getDynamicPortals(PortalsName);
1646 for (uint32 i = 0; i < PortalsName.size(); ++i)
1647 pPlayerClusterSystem->setDynamicPortal (PortalsName[i], true);
1653 // R2ED pre render update
1654 if (ClientCfg.R2EDEnabled)
1656 R2::getEditor().updateBeforeRender();
1659 if (!ClientCfg.Light)
1661 // Render
1662 if(Render)
1664 // Update water env map (happens when continent changed etc)
1665 updateWaterEnvMap();
1667 // Update weather
1668 updateWeather();
1672 uint i = 0;
1673 CTextureUser *effectRenderTarget = NULL;
1674 bool haveEffects = Render && Driver->getPolygonMode() == UDriver::Filled
1675 && (ClientCfg.Bloom || FXAA);
1676 bool defaultRenderTarget = false;
1677 if (haveEffects)
1679 if (!StereoDisplay)
1681 Driver->beginDefaultRenderTarget();
1682 defaultRenderTarget = true;
1684 if (ClientCfg.Bloom)
1686 CBloomEffect::getInstance().setSquareBloom(ClientCfg.SquareBloom);
1687 CBloomEffect::getInstance().setDensityBloom((uint8)ClientCfg.DensityBloom);
1690 bool fullDetail = false;
1691 while ((!StereoDisplay && i == 0) || (StereoDisplay && StereoDisplay->nextPass()))
1693 ++i;
1694 ///////////////////
1695 // SETUP CAMERAS //
1696 ///////////////////
1698 if (StereoDisplay)
1700 // modify cameras for stereo display
1701 const CViewport &vp = StereoDisplay->getCurrentViewport();
1702 Driver->setViewport(vp);
1703 nlassert(Scene);
1704 Scene->setViewport(vp);
1705 if (SceneRoot)
1707 SceneRoot->setViewport(vp);
1709 //MainCam.setTransformMode(UTransformable::DirectMatrix);
1710 StereoDisplay->getCurrentMatrix(0, &MainCam);
1711 StereoDisplay->getCurrentFrustum(0, &MainCam);
1712 if (SceneRoot)
1714 // matrix updated during commitCamera from maincam
1715 UCamera cam = SceneRoot->getCam();
1716 StereoDisplay->getCurrentFrustum(1, &cam);
1720 // Commit camera changes
1721 commitCamera();
1723 //////////////////////////
1724 // RENDER THE FRAME 3D //
1725 //////////////////////////
1727 bool stereoRenderTarget = (StereoDisplay != NULL) && StereoDisplay->beginRenderTarget();
1729 if (!StereoDisplay || StereoDisplay->wantClear())
1731 // Clear buffers
1732 clearBuffers();
1735 if (!StereoDisplay || StereoDisplay->wantScene())
1737 if (!ClientCfg.Light && Render)
1739 if (!StereoDisplay || StereoDisplay->isSceneFirst())
1741 // nb : force full detail if a screenshot is asked
1742 // todo : move outside render code
1743 if (!fullDetail)
1745 fullDetail = ScreenshotRequest != ScreenshotRequestNone && ClientCfg.ScreenShotFullDetail;
1746 if (fullDetail)
1748 s_ForceFullDetail.backup();
1749 s_ForceFullDetail.set();
1754 // Render scene
1755 bool wantTraversals = !StereoDisplay || StereoDisplay->isSceneFirst();
1756 bool keepTraversals = StereoDisplay && !StereoDisplay->isSceneLast();
1757 doRenderScene(wantTraversals, keepTraversals);
1759 if (!StereoDisplay || StereoDisplay->isSceneLast())
1761 if (fullDetail)
1763 s_ForceFullDetail.restore();
1764 fullDetail = false;
1770 if (!StereoDisplay || StereoDisplay->wantSceneEffects())
1772 if (!ClientCfg.Light && Render && haveEffects)
1774 if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
1775 UCamera pCam = Scene->getCam();
1776 Driver->setMatrixMode2D11();
1777 if (FXAA) FXAA->applyEffect();
1778 if (ClientCfg.Bloom) CBloomEffect::instance().applyBloom();
1779 Driver->setMatrixMode3D(pCam);
1780 if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport());
1784 if (!StereoDisplay || StereoDisplay->wantInterface3D())
1786 if (!ClientCfg.Light)
1788 // Render
1789 if (Render)
1791 // for that frame and
1792 // tmp : display height grid
1793 //static volatile bool displayHeightGrid = true;
1794 /*if (displayHeightGrid)
1796 HeightGrid.display(*Driver);
1798 // display results?
1799 if(Scene_Profile)
1801 displaySceneProfiles();
1802 Scene_Profile= false;
1804 // Render the primitives
1806 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1807 PrimFiles.display (*Driver);
1809 } /* if (Render) */
1811 // Draw Extra 3D Objects
1812 Driver->setMatrixMode3D(MainCam);
1813 Driver->setModelMatrix(CMatrix::Identity);
1815 // Display PACS borders.
1816 if (PACSBorders)
1818 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1819 displayPACSBorders();
1820 displayPACSPrimitive();
1823 // Display PACS borders only (for ARK).
1824 if (ARKPACSBorders)
1826 displayPACSPrimitive();
1829 // display Sound box
1830 if (SoundBox)
1832 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1833 displaySoundBox();
1836 // display Debug of Clusters
1837 if (DebugClusters)
1839 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1840 displayDebugClusters();
1842 } /* if (!ClientCfg.Light) */
1843 else
1845 // static UTextureFile *backgroundBitmap = NULL;
1846 // if (backgroundBitmap == NULL)
1847 // backgroundBitmap = Driver->createTextureFile("temp_background.tga");
1848 // Driver->setMatrixMode2D11();
1849 // Driver->drawBitmap (0.f, 0.f, 1024.f/1024.f, 1024.f/768.f, (UTexture&)*backgroundBitmap);
1850 // Driver->setMatrixMode3D(MainCam);
1852 Driver->clearBuffers(CRGBA (0,0,0,0));
1853 displayPACSBorders();
1854 displayPACSPrimitive();
1857 if (!ClientCfg.Light && !Landscape)
1859 displayPACSBorders();
1862 // Display some things not in the scene like the name, the entity path, etc.
1863 EntitiesMngr.updatePostRender();
1865 // Render the stat graphs if needed
1867 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1868 CGraph::render (ShowInfos);
1871 } /* if (!StereoDisplay || StereoDisplay->wantInterface3D()) */
1873 if (!StereoDisplay || StereoDisplay->wantInterface2D())
1875 // Render in 2D Mode to display 2D Interfaces and 2D texts.
1876 Driver->setMatrixMode2D11();
1878 // draw a big quad to represent thunder strokes
1879 /*if (Render && WeatherManager.getThunderLevel() != 0.f)
1881 H_AUTO_USE ( RZ_Client_Main_Loop_Render_Thunder )
1882 Driver->drawQuad(0, 0, 1, 1, ThunderColor);
1884 // TODO : boris : add sound here !
1885 // Needs more explosions
1888 // Update the contextual menu
1890 H_AUTO_USE ( RZ_Client_Main_Loop_Interface )
1892 // Update the game cursor.
1893 ContextCur.check();
1894 GameContextMenu.update();
1896 // validate dialogs
1897 validateDialogs(GameContextMenu);
1899 // Display interface v3
1900 Driver->enableFog (false);
1901 if (!Driver->isLost())
1903 if(ShowInterface)
1904 pIMinstance->updateFrameViews (MainCam);
1905 if(DebugUIView)
1906 pIMinstance->displayUIViewBBoxs(DebugUIFilter);
1907 if(DebugUICtrl)
1908 pIMinstance->displayUICtrlBBoxs(DebugUIFilter);
1909 if(DebugUIGroup)
1910 pIMinstance->displayUIGroupBBoxs(DebugUIFilter);
1913 // special case in OpenGL : all scene has been display in render target,
1914 // now, final texture is display with a quad
1915 /*if (!ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) // NO VR BLOOMZ
1917 // End bloom effect system after drawing the 3d interface (z buffer related).
1918 if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
1919 CBloomEffect::instance().endInterfacesDisplayBloom();
1920 if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport());
1921 bloomStage = 0;
1926 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
1927 if (!Driver->isLost())
1929 // If show information is Active.
1930 if(ShowInfos == 1)
1931 displayDebug();
1933 // If show information is Active.
1934 if(ShowInfos == 2)
1935 displayNetDebug();
1937 // If show information is Active.
1938 if(ShowInfos == 4)
1939 displayDebugFps();
1941 // If show information is Active.
1942 if(ShowInfos == 5)
1943 displayDebugUIUnderMouse();
1945 // If show information is Active.
1946 displayStreamingDebug();
1948 // If Show Help is active -> Display an help.
1949 if(ShowHelp)
1950 displayHelp();
1952 // Yoyo: indicate profiling state
1953 if( Profiling )
1954 displaySpecialTextProgress("Profiling");
1956 // Display frame rate
1958 // Create a shadow when displaying a text.
1959 TextContext->setShaded(true);
1960 TextContext->setShadeOutline(false);
1961 // Set the font size.
1962 TextContext->setFontSize(10);
1963 // Set the text color
1964 TextContext->setColor(CRGBA(255,255,255));
1966 // temporary values for conversions
1967 float x, y, width, height;
1969 for(uint i = 0; i < ClientCfg.Logos.size(); i++)
1971 std::vector<string> res;
1972 explode(ClientCfg.Logos[i],std::string(":"), res);
1973 if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL)
1975 fromString(res[5], x);
1976 fromString(res[6], y);
1977 fromString(res[7], width);
1978 fromString(res[8], height);
1979 Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]);
1985 // FPS
1987 static TTicks oldTick = CTime::getPerformanceTime();
1988 TTicks newTick = CTime::getPerformanceTime();
1989 double deltaTime = CTime::ticksToSecond (newTick-oldTick);
1990 oldTick = newTick;
1991 smoothFPS.addValue((float)deltaTime);
1992 moreSmoothFPS.addValue((float)deltaTime);
1993 deltaTime = smoothFPS.getSmoothValue ();
1994 if (deltaTime > 0.0)
1996 CCDBNodeLeaf *pNL = s_FpsLeaf ? &*s_FpsLeaf
1997 : &*(s_FpsLeaf = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:FPS"));
1998 pNL->setValue64((sint64)(1.f/deltaTime));
2002 // R2ED post render update
2003 if (ClientCfg.R2EDEnabled)
2005 // IMPORTANT : this should be called after CEntitiesMngr::updatePostRender() because
2006 // entity may be added / removed there !
2007 R2::getEditor().updateAfterRender();
2010 // Update FXs (remove them).
2011 FXMngr.update();
2013 // Detect disconnection / server down: display information text
2014 // but keep the rendering so that the player can remember where he is
2015 // and what he was doing. He can't move because the connection quality returns false.
2017 if ((connectionState == CNetworkConnection::Disconnect) && (lastConnectionState != CNetworkConnection::Disconnect) && (!FarTP.isFarTPInProgress()))
2019 UserControls.stopFreeLook(); // let the player click on Exit
2020 pIMinstance->messageBoxWithHelp(CI18N::get("uiDisconnected"));
2022 // If we have started a Far TP sequence and are waiting for onServerQuitOK()
2023 // from the EGS, resume the sequence because the EGS is down and won't reply.
2024 FarTP.onServerQuitOk();
2027 // Yoyo: MovieShooter.
2028 if(MovieShooterSaving)
2030 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
2032 // Add the buffer frame to the movie.
2033 if(!MovieShooter.addFrame(TimeInSec, Driver))
2035 // Fail to add the frame => abort.
2036 endMovieShooting();
2038 else
2040 // Ok, just add a display.
2041 displaySpecialTextProgress("MovieShooting");
2045 if (isRecordingCamera())
2047 displaySpecialTextProgress("CameraRecording");
2050 // Temp for weather test
2051 if (ClientCfg.ManualWeatherSetup)
2053 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
2054 static float displayHourDelta = 0.04f; // static for edition during debug..
2056 // Display weather function
2057 if (DisplayWeatherFunction)
2059 uint64 currDay = RT.getRyzomDay();
2060 float currHour = DayNightCycleHour;
2061 float singleHourDelta = fmodf(currHour, 1.f);
2062 uint32 wndWidth, wndHeight;
2063 Driver->getWindowSize(wndWidth, wndHeight);
2064 Driver->setMatrixMode2D(CFrustum(0, 800, 600, 0, 0, 1, false));
2065 const float lineHeight = 100.f;
2067 // draw the weather function
2068 for(uint x = 0; x < wndWidth; ++x)
2070 float weatherValue;
2071 if(ContinentMngr.cur())
2072 weatherValue = ::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction);
2073 else
2074 weatherValue = ::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, 0);
2076 NLMISC::clamp(weatherValue, 0.f, 1.f);
2077 CRGBA seasonToColor[EGSPD::CSeason::Invalid] =
2079 CRGBA::Green,
2080 CRGBA::Yellow,
2081 CRGBA::Red,
2082 CRGBA::Blue
2084 Driver->drawLine((float) x, 0.f, (float) x, lineHeight * weatherValue, seasonToColor[CRyzomTime::getSeasonByDay((uint32)currDay)]);
2085 currHour += displayHourDelta;
2086 if (currHour >= 24.f)
2088 ++currDay;
2089 currHour -= 24.f;
2091 singleHourDelta += displayHourDelta;
2092 if (singleHourDelta >= 1.f)
2094 singleHourDelta -= 1.f;
2095 Driver->drawLine((float) x, 100.f, (float) x, 130, CRGBA::Red);
2099 if(ContinentMngr.cur())
2101 // draw lines for current weather setups
2102 uint numWeatherSetups = ContinentMngr.cur()->WeatherFunction[CurrSeason].getNumWeatherSetups();
2103 for (uint y = 0; y < numWeatherSetups; ++y)
2105 float py = lineHeight * (y / (float) numWeatherSetups);
2106 Driver->drawLine(0.f, py, 800.f, py, CRGBA::Magenta);
2111 // Ctrl+ & Ctrl- change the weather value
2112 if (Actions.valide ("inc_time"))
2114 ManualWeatherValue += DT * 0.04f;
2116 if (Actions.valide ("dec_time"))
2118 ManualWeatherValue -= DT * 0.04f;
2120 NLMISC::clamp(ManualWeatherValue, 0.f, 1.f);
2122 if (ForcedDayNightCycleHour < 0) // if time is forced then can't change it manually ...
2124 // Ctrl-K increase hour
2125 if (Actions.valide ("inc_hour"))
2127 RT.increaseTickOffset( (uint32)(2000 * displayHourDelta) );
2128 RT.updateRyzomClock(NetMngr.getCurrentServerTick());
2131 // Ctrl-L decrease hour
2132 if (Actions.valide ("dec_hour"))
2134 RT.decreaseTickOffset( (uint32)(2000 * displayHourDelta) );
2135 RT.updateRyzomClock(NetMngr.getCurrentServerTick());
2136 CTimedFXManager::getInstance().setDate(CClientDate(RT.getRyzomDay(), (float) RT.getRyzomTime()));
2137 if (IGCallbacks)
2139 IGCallbacks->changeSeason(); // the season doesn't change, but this force fxs to be recreated
2144 // Ctrl-M generate statistics in a file
2146 if (Actions.valide ("weather_stats"))
2148 // Only usable if there is a continent loaded.
2149 if(ContinentMngr.cur())
2150 CPredictWeather::generateWeatherStats("weather_stats.csv", WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction);
2153 // Ctrl-B decrease display factor
2154 if (Actions.valide ("dec_display_factor"))
2156 displayHourDelta *= 0.90f;
2158 // Ctrl-J increase display factor
2159 if (Actions.valide ("inc_display_factor"))
2161 displayHourDelta *= 1.1f;
2162 displayHourDelta = std::min(1000.f, displayHourDelta);
2166 // Ctrl-AltGR-Z show timed FXs
2167 if (ShowTimedFX)
2169 if (!Driver->isLost())
2171 CTimedFXManager::getInstance().displayFXBoxes(ShowTimedFXMode);
2175 #if !FINAL_VERSION
2176 CVector2f camPos(Scene->getCam().getPos().x, Scene->getCam().getPos().y);
2177 if (!ClientCfg.Light)
2179 if (DisplayMicroLifeZones)
2181 CMicroLifeManager::getInstance().renderMLZones(camPos);
2184 if (DisplayWaterMap)
2186 if (ContinentMngr.cur())
2188 ContinentMngr.cur()->WaterMap.render(camPos);
2191 #endif
2193 #ifdef NL_DEBUG
2194 if (!ClientCfg.Light)
2196 if (DisplayMicroLifeActiveTiles)
2198 CMicroLifeManager::getInstance().renderActiveTiles();
2201 #endif
2202 // tmp : debug of ground fxs
2203 //TestGroundFX.displayFXBoxes();
2205 // Temp for sound debug
2207 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
2209 if (SoundMngr != 0)
2211 static bool drawSound = false;
2212 static float camHeigh = 150.0f;
2214 #if FINAL_VERSION
2215 if (ClientCfg.ExtendedCommands)
2216 #endif
2217 if (Actions.valide ("draw_sound"))
2218 drawSound = !drawSound;
2220 if (Actions.valide ("inc_camera_height"))
2221 camHeigh -= 10.0f;
2222 if (Actions.valide ("dec_camera_height"))
2223 camHeigh += 10.0f;
2225 if (drawSound)
2226 SoundMngr->drawSounds(camHeigh);
2229 } /* if (!StereoDisplay || StereoDisplay->wantInterface2D()) */
2231 if (StereoDisplay)
2233 StereoDisplay->endRenderTarget();
2235 } /* stereo pass */
2237 if (defaultRenderTarget)
2239 // draw final result to backbuffer
2240 Driver->endDefaultRenderTarget(Scene);
2243 // Draw to screen.
2244 static CQuat MainCamOri;
2245 if (FirstFrame)
2247 // Frame to skip before swap buffer
2248 SkipFrame = RYZOM_FIRST_FRAME_TO_SKIP;
2249 FirstFrame = false;
2250 MainCam.getRotQuat(MainCamOri);
2253 if (SkipFrame == 0)
2255 if (StartPlayTime == 0)
2257 StartPlayTime = NLMISC::CTime::getLocalTime();
2260 // Start background sound play now ! (nb: restarted if load just ended, or if sound re-enabled)
2261 if (SoundMngr)
2263 H_AUTO_USE ( RZ_Client_Main_Loop_Sound )
2265 // fade out loading music
2266 if (SoundMngr->getEventMusicPlayed() == LoadingMusic)
2268 SoundMngr->stopEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade);
2271 SoundMngr->playBackgroundSound();
2273 // Fade in Game Sound now (before endLoading)
2274 // fade in game sound
2275 SoundMngr->fadeInGameSound(ClientCfg.SoundTPFade);
2278 // end loading (if previous load)
2279 endLoading ();
2281 // if a screenshot request was made then do it now
2282 switch(ScreenshotRequest)
2284 case ScreenshotRequestTGA:
2285 screenShotTGA();
2286 ScreenshotRequest = ScreenshotRequestNone;
2287 break;
2288 case ScreenshotRequestJPG:
2289 screenShotJPG();
2290 ScreenshotRequest = ScreenshotRequestNone;
2291 break;
2292 case ScreenshotRequestPNG:
2293 screenShotPNG();
2294 ScreenshotRequest = ScreenshotRequestNone;
2295 break;
2296 default:
2297 break;
2300 // TMP TMP
2301 static volatile bool dumpValidPolys = false;
2302 if (dumpValidPolys) { tempDumpValidPolys(); dumpValidPolys = false; }
2304 // TMP TMP
2305 static volatile bool dumpColPolys = false;
2306 if (dumpColPolys) { tempDumpColPolys(); }
2308 if (ClientCfg.R2EDEnabled)
2310 R2::getEditor().updateBeforeSwapBuffer();
2313 Driver->swapBuffers();
2315 if(Profiling)
2317 ++ ProfileNumFrame;
2318 if (ProfileNumFrame == ClientCfg.NumFrameForProfile)
2320 WantProfiling = true;
2324 // If the device is lost then no rendering will occur, so let some time to other applications
2325 if (Driver->isLost())
2327 nlSleep(50);
2328 nldebug("lost device");
2331 else
2333 SkipFrame--;
2335 // Turn the camera to make a 360 degree turn
2336 // UTransformable::TTransformMode m = MainCam.getTransformMode();
2337 if (SkipFrame == 0)
2339 MainCam.setRotQuat(MainCamOri);
2341 else
2343 CMatrix mat = CMatrix::Identity;
2344 mat.setRot(MainCamOri);
2345 mat.rotateZ(2*(float)Pi*((float)(SkipFrame)/(float)RYZOM_FIRST_FRAME_TO_SKIP));
2346 CQuat qTmp;
2347 mat.getRot(qTmp);
2348 MainCam.setRotQuat(qTmp);
2353 // Force the client to sleep a bit.
2354 if(ClientCfg.Sleep >= 0)
2356 H_AUTO_USE ( RZ_Client_Main_Loop_Debug )
2357 nlSleep(ClientCfg.Sleep);
2360 //++MainLoopCounter;
2362 // Send new data Only when server tick changed.
2363 if(NetMngr.getCurrentServerTick() > LastGameCycle)
2365 H_AUTO_USE ( RZ_Client_Main_Loop_Net )
2366 // Put here things you have to send to the server only once per tick like user position.
2367 // UPDATE COMPASS
2368 NLMISC::CCDBNodeLeaf *node = s_UiDirectionLeaf ? (&*s_UiDirectionLeaf)
2369 : &*(s_UiDirectionLeaf = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DIRECTION"));
2370 CInterfaceProperty prop;
2371 prop.setNodePtr(node);
2372 if(CompassMode == 1)
2374 double camDir = atan2(View.view().y, View.view().x);
2375 prop.setDouble(camDir);
2377 else
2378 prop.setDouble(atan2(UserEntity->front().y, UserEntity->front().x));
2379 // Update the server with our position and orientation.
2381 CBitMemStream out;
2382 if(UserEntity->sendToServer(out))
2383 NetMngr.push(out);
2385 // Give information to the server about the combat position (ability to strike).
2387 CBitMemStream out;
2388 if(UserEntity->msgForCombatPos(out))
2389 NetMngr.push(out);
2392 // Create the message for the server to move the user (except in combat mode).
2393 if(Ping.rdyToPing())
2395 CBitMemStream out;
2396 if(GenericMsgHeaderMngr.pushNameToStream("DEBUG:PING", out))
2398 const TTime mask = 0xFFFFFFFF;
2399 uint32 localTime = (uint32)(mask&ryzomGetLocalTime ());
2400 out.serial(localTime);
2401 NetMngr.push(out);
2403 Ping.rdyToPing(false);
2405 else
2406 nlwarning("mainloop: unknown message named 'DEBUG:PING'.");
2409 // Send the Packet.
2410 NetMngr.send(NetMngr.getCurrentServerTick());
2411 // Update the Last tick received from the server.
2412 LastGameCycle = NetMngr.getCurrentServerTick();
2415 if (ClientCfg.AutoReloadFiles)
2417 // Check for files update.
2418 CFile::checkFileChange();
2420 // Check for configuration files update.
2421 CConfigFile::checkConfigFiles();
2424 // Get the Connection State.
2425 lastConnectionState = connectionState;
2426 connectionState = NetMngr.getConnectionState();
2428 // Update movie shooter
2429 updateMovieShooting();
2431 // Update the bubble manager
2432 InSceneBubbleManager.update();
2434 // Update the NPC icon system
2435 CNPCIconCache::getInstance().update();
2437 // Update Phrase Manager
2438 CSPhraseManager *pPM= CSPhraseManager::getInstance();
2439 pPM->updateEquipInvalidation(NetMngr.getCurrentServerTick());
2440 pPM->updateAllActionRegen();
2442 // Update ingame duration and stat report sending
2443 updateStatReport ();
2445 // Auto play once on character login
2446 if (musicTriggerAutoPlay)
2448 musicTriggerAutoPlay = false;
2449 if (ClientCfg.SoundOn && ClientCfg.MediaPlayerAutoPlay)
2451 MusicPlayer.stop();
2452 CAHManager::getInstance()->runActionHandler("music_player", NULL, "play_songs");
2453 MusicPlayer.play();
2456 // Update the music player
2457 MusicPlayer.update ();
2459 // Memory Debug
2460 if (ClientCfg.CheckMemoryEveryNFrame != -1)
2462 static int frameToSkip = ClientCfg.CheckMemoryEveryNFrame;
2463 if (frameToSkip == 0)
2465 frameToSkip = ClientCfg.CheckMemoryEveryNFrame;
2466 //NLMEMORY::CheckHeap (true);
2468 else
2469 frameToSkip--;
2472 ///////////////
2473 // FAR_TP -> //
2474 ///////////////
2475 // Enter a network loop during the FarTP process, without doing the whole real main loop.
2476 // This code must remain at the very end of the main loop.
2477 if(LoginSM.getCurrentState() == CLoginStateMachine::st_enter_far_tp_main_loop)
2479 CLuaManager::getInstance().executeLuaScript("game:onFarTpStart()");
2480 // Will loop the network until the end of the relogging process
2481 FarTP.farTPmainLoop();
2483 if( FarTP.isReselectingChar() )
2485 if ( game_exit ) // check if the user has decided to quit
2486 break;
2488 // we have just completed init main loop, after reselecting character
2489 // repeat the steps before the main loop itself
2491 // new char, retrigger music autoplay
2492 musicTriggerAutoPlay = true;
2494 // pre main loop in mainLoop
2495 resetIngameTime ();
2497 game_exit = false;
2498 game_exit_request = false;
2499 FarTP.setMainLoopEntered();
2501 // Get the Width and Height of the window and set the Old values..
2502 Driver->getWindowSize(Width, Height);
2503 OldWidth = Width; OldHeight = Height;
2505 CGraph::init( Driver );
2506 CGraph::Display = false;
2508 T1 = ryzomGetLocalTime();
2509 TSend = ((T1+DTSend)/DTSend)*DTSend;
2511 SetMouseFreeLook ();
2512 SetMouseCursor ();
2513 // Set the cursor.
2514 ContextCur.context("STAND BY");
2515 UserControls.reset();
2517 // set the default box for keyboard
2518 CChatWindow *defaultChatWindow;
2519 if (ClientCfg.R2EDEnabled)
2521 defaultChatWindow = PeopleInterraction.DebugInfo;
2523 else
2525 defaultChatWindow = PeopleInterraction.ChatGroup.Window;
2527 setDefaultChatWindow(defaultChatWindow);
2529 // Init GameContextMenu.
2530 GameContextMenu.init("");
2532 // Active inputs
2533 Actions.enable(true);
2534 EditActions.enable(true);
2536 // check for banned player
2537 if (testPermanentBanMarkers())
2539 setPermanentBanMarkers(true); // re-set any marker that could have been removed by the trouble maker
2540 applyPermanentBanPunishment();
2541 PermanentlyBanned = true;
2545 // For stoping the outgame music, start after 30 frames, and duration of 3 seconds
2546 outgameFader = CMusicFader(60, 3);
2548 // Short reinit of the main loop after farTP or character reselection
2549 Ping.init();
2550 updateLightDesc();
2552 // R2ED enabled ?
2553 R2::getEditor().autoConfigInit(IsInRingSession);
2555 // TODO: temporary commented, CEditor must be initialized before to call next lines
2556 // if (!IsInRingSession)
2557 // R2::getEditor().registerLuaFunc();
2559 CurrSeason = computeCurrSeason();
2561 // Get the Connection State (must be done after any Far TP to prevent the uiDisconnected box to be displayed)
2562 lastConnectionState = CNetworkConnection::Connected;
2563 connectionState = NetMngr.getConnectionState();
2565 CLuaManager::getInstance().executeLuaScript("game:onFarTpEnd()");
2567 ///////////////
2568 // <- FAR_TP //
2569 ///////////////
2571 } // end of main loop
2573 CInterfaceManager *im = CInterfaceManager::getInstance();
2574 if (CLuaManager::getInstance().getLuaState())
2576 CLuaManager::getInstance().executeLuaScript("game:onMainLoopEnd()");
2579 // Stop Running Profiles (kick result)
2580 if(Profiling)
2582 WantProfiling= false;
2583 Profiling= false;
2584 CHTimer::endBench();
2585 Driver->endBench();
2587 if(ProfilingVBLock)
2589 WantProfilingVBLock= false;
2590 ProfilingVBLock= false;
2591 vector<string> strs;
2592 Driver->endProfileVBHardLock(strs);
2595 if ( ! FarTP.isReselectingChar() ) // skip some parts if the user wants to quit in the middle of a char reselect
2597 // Saving ingame resolution when in windowed mode
2598 saveIngameResolution();
2600 // Release the structure for the ping.
2601 Ping.release ();
2603 // Disable inputs
2604 Actions.enable(false);
2605 EditActions.enable(false);
2607 CWidgetManager::getInstance()->setDefaultCaptureKeyboard(NULL);
2609 // Interface saving
2610 CInterfaceManager::getInstance()->uninitInGame0();
2611 CItemGroupManager::getInstance()->uninit();
2613 /////////////////////////////////
2614 // Display the end background. //
2615 /////////////////////////////////
2616 // Create the loading texture.
2617 loadBackgroundBitmap (EndBackground);
2619 // TTime endTime = ryzomGetLocalTime () + (TTime)(ClientCfg.EndScreenTimeOut*1000.f);
2620 // do
2621 // {
2622 // // Grab Inputs.
2623 // CInputHandlerManager::getInstance()->pumpEventsNoIM();
2624 // Display the background
2625 drawLoadingBitmap (0);
2626 // Display to screen.
2627 Driver->swapBuffers();
2628 // } while(ryzomGetLocalTime () < endTime);
2630 // Destroy the Loading Background.
2631 destroyLoadingBitmap ();
2633 IngameDbMngr.resetInitState();
2636 ryzom_exit = true;
2638 return ryzom_exit || (Driver == NULL) || (!Driver->isActive ());
2639 }// mainLoop //
2641 //---------------------------------------------------
2642 // Just Display some text with ... anim at some place.
2643 //---------------------------------------------------
2644 void displaySpecialTextProgress(const char *text)
2646 // Create a shadow when displaying a text.
2647 TextContext->setShaded(true);
2648 TextContext->setShadeOutline(false);
2649 // Set the font size.
2650 TextContext->setFontSize(12);
2651 // Set the text color
2652 TextContext->setColor(CRGBA(255,255,255));
2654 TextContext->setHotSpot(UTextContext::BottomLeft);
2656 // cool .... anim.
2657 const uint MaxDot= 8;
2658 static uint counter=0;
2659 counter= (counter+1) % (MaxDot+1);
2660 // format counter.
2661 char str[MaxDot+1];
2662 uint i;
2663 for(i=0;i<counter;i++)
2664 str[i]= '.';
2665 str[counter]= 0;
2666 // display text
2667 TextContext->printfAt(0.05f,0.80f,"%s%s", text, str );
2671 //---------------------------------------------------
2672 // MovieShooter methods
2673 //---------------------------------------------------
2676 void endMovieShooting()
2678 MovieShooterSaving= false;
2681 bool MovieShooterReplay = false;
2682 bool MovieShooterSave = false;
2684 void updateMovieShooting()
2686 #ifdef _MOVIE_SHOOTER_ON_
2687 if (MovieShooterReplay)
2689 if(!MovieShooter.enabled())
2691 Driver->systemMessageBox("MovieShooter not enabled", "MovieShooter");
2693 else
2695 if( !MovieShooterSaving )
2699 MovieShooter.replayMovie(Driver, TextContext);
2701 catch (const Exception &e)
2703 Driver->systemMessageBox(e.what(), "MovieShooter");
2707 MovieShooterReplay = false;
2710 if (MovieShooterSave)
2712 if(!MovieShooter.enabled())
2714 Driver->systemMessageBox("MovieShooter not enabled", "MovieShooter");
2716 else
2718 if( !MovieShooterSaving )
2722 // Create a New Dir
2723 string theDir;
2724 uint num= 0;
2727 num++;
2728 char tmp[256];
2729 sprintf(tmp, "%03d", num);
2730 theDir= ClientCfg.MovieShooterPath + "/" + "Movie" + tmp;
2732 while( CFile::isDirectory(theDir) );
2733 // create the dir
2734 CFile::createDirectory(theDir);
2736 // Save the movie.
2737 MovieShooter.saveMovie(Driver, TextContext, theDir.c_str(), ClientCfg.MovieShooterFramePeriod, ClientCfg.MovieShooterBlend, ClientCfg.MovieShooterPrefix.c_str());
2739 catch (const Exception &e)
2741 Driver->systemMessageBox(e.what(), "MovieShooter");
2745 MovieShooterSave = false;
2747 #endif // _MOVIE_SHOOTER_ON_
2751 //---------------------------------------------------
2752 // updateSound :
2753 // update the listener pos and user walk/run/idle sound (stereo)
2754 //---------------------------------------------------
2755 void updateSound()
2757 if(SoundMngr)
2759 SoundMngr->update ();
2761 }// updateSound //
2766 //===================================================================================================
2767 void updateLightDesc()
2769 if (!ClientCfg.Light)
2771 // Update the lighting description (when season change, or for first setup)
2772 static bool init = false;
2773 EGSPD::CSeason::TSeason season = CurrSeason;
2774 if (!init || season != CurrSeason)
2776 CLightCycleDesc desc;
2777 buildLightCycleDesc(desc, CurrSeason);
2778 LightCycleManager.setLightDesc(desc);
2779 init = true;
2781 if (CurrSeason != season)
2783 CurrSeason = season;
2784 // also update seasonal fxs
2785 if (IGCallbacks)
2787 IGCallbacks->changeSeason();
2793 //===================================================================================================
2794 static void updateCloudScape(const CCloudState &desc, const CWeatherContext &wc, float /* wind */, float dayNight, float updateDelay, bool mustInit)
2796 if (!CloudScape) return;
2797 SCloudScapeSetup css;
2798 NLMISC::clamp(dayNight, 0.f, 1.f);
2799 css.CloudSpeed = desc.DiffusionSpeed;
2800 float duskRatio = LightCycleManager.getLightDesc().DuskRatio;
2801 switch(LightCycleManager.getState())
2803 case CLightCycleManager::DayToNight:
2804 if (dayNight < duskRatio) // day->dusk
2806 float blendFactor = duskRatio != 0 ? dayNight / duskRatio : 0.f;
2807 css.Ambient.blendFromui(desc.AmbientDay, desc.AmbientDusk, (uint) (256.f * blendFactor));
2808 css.Diffuse.blendFromui(desc.DiffuseDay, desc.DiffuseDusk, (uint) (256.f * blendFactor));
2810 else // dusk->night
2812 float blendFactor = duskRatio != 1 ? (dayNight - duskRatio) / (1.f - duskRatio) : 0.f;
2813 css.Ambient.blendFromui(desc.AmbientDusk, desc.AmbientNight, (uint) (256.f * blendFactor));
2814 css.Diffuse.blendFromui(desc.DiffuseDusk, desc.DiffuseNight, (uint) (256.f * blendFactor));
2816 break;
2817 default: // not a day->night transition, so no step for dusk
2818 css.Ambient.blendFromui(desc.AmbientDay, desc.AmbientNight, (uint) (256.f * dayNight));
2819 css.Diffuse.blendFromui(desc.DiffuseDay, desc.DiffuseNight, (uint) (256.f * dayNight));
2820 break;
2823 css.NbCloud = desc.NumClouds;
2824 css.WindSpeed = WeatherManager.getCurrWeatherState().WindIntensity * wc.WFP->CloudWindSpeedFactor + wc.WFP->CloudMinSpeed;
2825 if (mustInit)
2827 css.TimeToChange = 0;
2828 CloudScape->init(&css);
2829 CloudScape->setNbCloudToUpdateIn80ms (ClientCfg.CloudUpdate);
2830 CloudScape->setQuality (ClientCfg.CloudQuality);
2832 else
2834 css.TimeToChange = updateDelay;
2835 CloudScape->set(css);
2839 //===================================================================================================
2840 void updateClouds()
2842 // build a weather context
2843 CWeatherContext wc;
2844 wc.GR = GR;
2845 if(ContinentMngr.cur())
2846 wc.WF = ContinentMngr.cur()->WeatherFunction;
2847 else
2848 wc.WF = NULL;
2850 if (ClientCfg.ManualWeatherSetup && !ForceTrueWeatherValue)
2852 // Try to update the clouds quickly for manual test
2853 if (CloudScape)
2855 CCloudState cs;
2856 WeatherManager.computeCloudState(ManualWeatherValue, CurrSeason, cs, wc.WF);
2857 updateCloudScape(cs, wc, WeatherManager.getCurrWeatherState().WindIntensity, LightCycleManager.getLightLevel(), 1.f, InitCloudScape);
2858 InitCloudScape = false;
2861 else
2863 // update the clouds
2864 if (InitCloudScape)
2866 InitCloudScape = false;
2867 // 1 ) set current state
2868 CCloudState cs;
2869 WeatherManager.computeCloudState(RT.getRyzomDay(), DayNightCycleHour, wc, cs);
2870 updateCloudScape(cs, wc, WeatherManager.getCurrWeatherState().WindIntensity, LightCycleManager.getLightLevel(), 0.f, true);
2871 // 2 )set next state
2872 // compute date of next update
2873 const CLightCycleDesc &lcd = LightCycleManager.getLightDesc();
2874 float updateDelay = 0.f;
2875 if (lcd.RealDayLength != 0.f)
2877 updateDelay = CloudUpdatePeriod / lcd.RealDayLength * lcd.NumHours;
2879 WeatherManager.computeCloudState(RT.getRyzomDay(), DayNightCycleHour + updateDelay, wc, cs);
2880 updateCloudScape(cs, wc, WeatherManager.getCurrWeatherState().WindIntensity, LightCycleManager.getLightLevel(), 0.f, true);
2881 DelayBeforeCloudUpdate = CloudUpdatePeriod;
2883 else
2885 DelayBeforeCloudUpdate -= DT;
2886 if (DelayBeforeCloudUpdate <= 0.f)
2888 DelayBeforeCloudUpdate += CloudUpdatePeriod;
2889 if (DelayBeforeCloudUpdate <= 0.f)
2891 DelayBeforeCloudUpdate = CloudUpdatePeriod;
2893 // set next state
2894 // compute date of next update
2895 const CLightCycleDesc &lcd = LightCycleManager.getLightDesc();
2896 float updateDelay = 0.f;
2897 if (lcd.RealDayLength != 0.f)
2899 updateDelay = DelayBeforeCloudUpdate / lcd.RealDayLength * lcd.NumHours;
2901 CCloudState cs;
2902 WeatherManager.computeCloudState(RT.getRyzomDay(), DayNightCycleHour + updateDelay, wc, cs);
2903 updateCloudScape(cs, wc, WeatherManager.getCurrWeatherState().WindIntensity, LightCycleManager.getLightLevel(), updateDelay, false);
2910 //-----------------------------------------------
2911 // displayPACSBorders :
2912 // Display Borders from PACS.
2913 //-----------------------------------------------
2914 void displayPACSBorders()
2916 static std::vector<std::pair<NLMISC::CLine, uint8> > edges;
2917 if(UserEntity->getPrimitive())
2919 UGlobalPosition gPos;
2920 UserEntity->getPrimitive()->getGlobalPosition(gPos, dynamicWI);
2921 if (GR) GR->getBorders(gPos, edges);
2923 CLineColor line;
2924 // ...
2925 for(uint i=0; i<edges.size(); ++i)
2927 line = (edges[i].first);
2928 // Choose the color according to the edge type.
2929 switch(edges[i].second)
2931 // Block
2932 case 0:
2933 line.Color0 = CRGBA::Red;
2934 line.Color1 = CRGBA::Red;
2935 break;
2936 // Surmountable
2937 case 1:
2938 line.Color0 = CRGBA::Green;
2939 line.Color1 = CRGBA::Green;
2940 break;
2941 // Link
2942 case 2:
2943 line.Color0 = CRGBA::Yellow;
2944 line.Color1 = CRGBA::Yellow;
2945 break;
2946 // Waterline
2947 case 3:
2948 line.Color0 = CRGBA::Blue;
2949 line.Color1 = CRGBA::Blue;
2950 break;
2951 case 4: // Exterior
2952 line.Color0 = CRGBA::Magenta;
2953 line.Color1 = CRGBA::Magenta;
2954 break;
2955 case 5: // Exterior door
2956 line.Color0 = CRGBA(127, 127, 127);
2957 line.Color1 = CRGBA(127, 127, 127);
2958 break;
2959 // Unknown
2960 default:
2961 line.Color0 = CRGBA::White;
2962 line.Color1 = CRGBA::White;
2963 break;
2965 // Draw the line.
2966 Driver->drawLine(line, GenericMat);
2969 // Clear the vetor.
2970 edges.clear();
2971 }// displayPACSBorders //
2973 const uint PacsBoxPointCount = 24;
2975 CVector PacsBox[PacsBoxPointCount] =
2977 CVector( -0.5f, -0.5f, 0), CVector( 0.5f, -0.5f, 0),
2978 CVector( 0.5f, -0.5f, 0), CVector( 0.5f, 0.5f, 0),
2979 CVector( 0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 0),
2980 CVector( -0.5f, 0.5f, 0), CVector( -0.5f, -0.5f, 0),
2982 CVector( -0.5f, -0.5f, 1), CVector( 0.5f, -0.5f, 1),
2983 CVector( 0.5f, -0.5f, 1), CVector( 0.5f, 0.5f, 1),
2984 CVector( 0.5f, 0.5f, 1), CVector( -0.5f, 0.5f, 1),
2985 CVector( -0.5f, 0.5f, 1), CVector( -0.5f, -0.5f, 1),
2987 CVector( -0.5f, -0.5f, 0), CVector( -0.5f, -0.5f, 1),
2988 CVector( 0.5f, -0.5f, 0), CVector( 0.5f, -0.5f, 1),
2989 CVector( 0.5f, 0.5f, 0), CVector( 0.5f, 0.5f, 1),
2990 CVector( -0.5f, 0.5f, 0), CVector( -0.5f, 0.5f, 1),
2993 const uint PacsCylPointCount = 48;
2995 CVector PacsCyl[PacsCylPointCount] =
2997 CVector( 0, 1, 0),CVector( 0.7071067f, 0.7071067f, 0),
2998 CVector( 0.7071067f, 0.7071067f, 0),CVector( 1, 0, 0),
2999 CVector( 1, 0, 0),CVector( 0.7071067f, -0.7071067f,0),
3000 CVector( 0.7071067f, -0.7071067f,0),CVector( 0, -1, 0),
3001 CVector( 0, -1, 0),CVector( -0.7071067f,-0.7071067f,0),
3002 CVector( -0.7071067f,-0.7071067f,0),CVector( -1, 0, 0),
3003 CVector( -1, 0, 0),CVector( -0.7071067f,0.7071067f, 0),
3004 CVector( -0.7071067f,0.7071067f, 0),CVector( 0, 1, 0),
3006 CVector( 0, 1, 1),CVector( 0.7071067f, 0.7071067f, 1),
3007 CVector( 0.7071067f, 0.7071067f, 1),CVector( 1, 0, 1),
3008 CVector( 1, 0, 1),CVector( 0.7071067f, -0.7071067f,1),
3009 CVector( 0.7071067f, -0.7071067f,1),CVector( 0, -1, 1),
3010 CVector( 0, -1, 1),CVector( -0.7071067f,-0.7071067f,1),
3011 CVector( -0.7071067f,-0.7071067f,1),CVector( -1, 0, 1),
3012 CVector( -1, 0, 1),CVector( -0.7071067f,0.7071067f, 1),
3013 CVector( -0.7071067f,0.7071067f, 1),CVector( 0, 1, 1),
3015 CVector( 0, 1, 1),CVector( 0, 1, 0),
3016 CVector( 0.7071067f, 0.7071067f, 1),CVector( 0.7071067f, 0.7071067f, 0),
3017 CVector( 1, 0, 1),CVector( 1, 0, 0),
3018 CVector( 0.7071067f, -0.7071067f,1),CVector( 0.7071067f, -0.7071067f,0),
3019 CVector( 0, -1, 1),CVector( 0, -1, 0),
3020 CVector( -0.7071067f,-0.7071067f,1),CVector( -0.7071067f,-0.7071067f,0),
3021 CVector( -1, 0, 1),CVector( -1, 0, 0),
3022 CVector( -0.7071067f,0.7071067f, 1),CVector( -0.7071067f,0.7071067f, 0),
3025 void displayPACSPrimitive()
3027 std::vector<const UMovePrimitive*> movePrimitives;
3029 // if no continent selected, skip
3030 if(!PACS)
3031 return;
3033 PACS->getPrimitives(movePrimitives);
3035 uint i;
3036 for (i=0; i<movePrimitives.size(); i++)
3038 // World image
3039 const UMovePrimitive *prim = movePrimitives[i];
3040 uint8 wI = prim->getFirstWorldImageV();
3042 // Distance
3043 CVector position = prim->getFinalPosition(wI);
3044 if ((position-UserEntity->pos()).sqrnorm() < (200*200))
3046 // Choose a color
3047 CLineColor line;
3048 if (prim->isCollisionable())
3050 // Static collision
3051 if (prim->getReactionType() == UMovePrimitive::DoNothing)
3053 line.Color0 = CRGBA::Red;
3055 else
3057 line.Color0 = CRGBA::Yellow;
3060 else
3062 // Trigger
3063 line.Color0 = CRGBA::White;
3065 line.Color1 = line.Color0;
3067 // Lines
3068 CVector *lines;
3070 // Line count
3071 uint linecount;
3073 // Transform matrix
3074 CMatrix scale;
3075 scale.identity();
3076 CMatrix rot;
3077 rot.identity();
3079 // Draw the primitive
3080 if (prim->getPrimitiveType() == UMovePrimitive::_2DOrientedBox)
3082 lines = PacsBox;
3083 linecount = PacsBoxPointCount/2;
3084 float width;
3085 float depth;
3086 prim->getSize (width, depth);
3087 scale.scale(CVector (width, depth, prim->getHeight()));
3088 rot.rotateZ((float)prim->getOrientation(wI));
3090 else
3092 lines = PacsCyl;
3093 linecount = PacsCylPointCount/2;
3094 float radius = prim->getRadius ();
3095 scale.scale(CVector (radius, radius, prim->getHeight()));
3098 CMatrix pos;
3099 pos.identity();
3100 pos.setPos (position);
3101 pos = pos*rot*scale;
3103 // Draw the primitive
3104 uint j;
3105 for (j=0; j<linecount; j++)
3107 line.V0 = pos * lines[j*2];
3108 line.V1 = pos * lines[j*2+1];
3110 // Draw the line.
3111 Driver->drawLine(line, GenericMat);
3117 //-----------------------------------------------
3118 // displaySoundBox :
3119 //-----------------------------------------------
3120 void displaySoundBox()
3122 if (SoundMngr != 0)
3124 SoundMngr->drawSounds(50.f);
3129 //-----------------------------------------------
3130 // displaySceneProfiles();
3131 // nlinfo the Scene Profile results
3132 //-----------------------------------------------
3133 string buildStrVBFormat(uint32 format)
3135 // Yoyo: Uggly: hardcoded :)
3136 string res;
3138 if(format & 0x0001)
3139 res+= "Vertex";
3140 if(format & 0x0002)
3141 res+= "|Normal";
3142 if(format & 0x0004)
3143 res+= "|TexCoord0";
3144 if(format & 0x0008)
3145 res+= "|TexCoord1 ";
3146 if(format & 0x0010)
3147 res+= "|TexCoord2";
3148 if(format & 0x0020)
3149 res+= "|TexCoord3 ";
3150 if(format & 0x0040)
3151 res+= "|TexCoord4 ";
3152 if(format & 0x0080)
3153 res+= "|TexCoord5 ";
3154 if(format & 0x0100)
3155 res+= "|TexCoord6 ";
3156 if(format & 0x0200)
3157 res+= "|TexCoord7";
3158 if(format & 0x0400)
3159 res+= "|PrimaryColor";
3160 if(format & 0x0800)
3161 res+= "|SecondaryColor";
3162 if(format & 0x1000)
3163 res+= "|Weight";
3164 if(format & 0x2000)
3165 res+= "|PaletteSkin";
3166 if(format & 0x4000)
3167 res+= "|Fog";
3169 return res;
3171 void displaySceneProfiles()
3173 // **** Scene Profile
3174 UScene::CBenchResults res;
3175 Scene->getProfileResults(res);
3177 static uint id=0;
3178 nlinfo("****** Scene Profile Result: %d *******", id );
3179 id++;
3181 // Display Mesh PerVertexFormat Benchs
3182 nlinfo(" * Mesh Per VertexFormat:");
3183 std::map<uint32, uint32>::iterator it;
3184 for(it=res.MeshProfileTriVBFormat.begin();it!=res.MeshProfileTriVBFormat.end();it++)
3186 // build the format
3187 string format= buildStrVBFormat(it->first);
3188 nlinfo(" NumTris: %5d. Format: %s", it->second, format.c_str() );
3191 // Display MeshMRM PerVertexFormat Benchs
3192 nlinfo(" * MeshMRM Per VertexFormat:");
3193 for(it=res.MeshMRMProfileTriVBFormat.begin();it!=res.MeshMRMProfileTriVBFormat.end();it++)
3195 // build the format
3196 string format= buildStrVBFormat(it->first);
3197 nlinfo(" NumTris: %5d. Format: %s", it->second, format.c_str() );
3200 // Display BlockRendering Information
3201 nlinfo(" * Mesh BlockRender Info:");
3202 nlinfo(" NumMeshRdrNormal: %d", res.NumMeshRdrNormal);
3203 nlinfo(" NumMeshRdrBlock: %d", res.NumMeshRdrBlock);
3204 nlinfo(" NumMeshRdrBlockWithVBHeap: %d", res.NumMeshRdrBlockWithVBHeap);
3205 nlinfo(" NumMeshRdrNormal TriCount: %d", res.NumMeshTriRdrNormal);
3206 nlinfo(" NumMeshRdrBlock TriCount: %d", res.NumMeshTriRdrBlock);
3207 nlinfo(" NumMeshRdrBlockWithVBHeap TriCount: %d", res.NumMeshTriRdrBlockWithVBHeap);
3209 nlinfo(" * MeshMRM BlockRender Info:");
3210 nlinfo(" NumMeshMRMRdrNormal: %d", res.NumMeshMRMRdrNormal);
3211 nlinfo(" NumMeshMRMRdrBlock: %d", res.NumMeshMRMRdrBlock);
3212 nlinfo(" NumMeshMRMRdrBlockWithVBHeap: %d", res.NumMeshMRMRdrBlockWithVBHeap);
3213 nlinfo(" NumMeshMRMRdrNormal TriCount: %d", res.NumMeshMRMTriRdrNormal);
3214 nlinfo(" NumMeshMRMRdrBlock TriCount: %d", res.NumMeshMRMTriRdrBlock);
3215 nlinfo(" NumMeshMRMRdrBlockWithVBHeap TriCount: %d", res.NumMeshMRMTriRdrBlockWithVBHeap);
3217 // Display VBHard usage Information
3218 nlinfo(" * VBHard usage Info:");
3219 nlinfo(" NumMeshVBufferStd: %d", res.NumMeshVBufferStd);
3220 nlinfo(" NumMeshVBufferHard: %d", res.NumMeshVBufferHard);
3221 nlinfo(" NumMeshMRMVBufferStd: %d", res.NumMeshMRMVBufferStd);
3222 nlinfo(" NumMeshMRMVBufferHard: %d", res.NumMeshMRMVBufferHard);
3225 nlinfo("****** END Scene Profile Result *******");
3227 // **** Additionaly, display QuadGridClipManager profile
3228 Scene->profileQuadGridClipManager();
3230 // **** Additionaly, display List of Landscape IG Loaded
3231 if (Landscape)
3233 nlinfo("****** Land IG Profile *******");
3234 std::vector<std::pair<UInstanceGroup *, std::string> > igList;
3235 LandscapeIGManager.getAllIGWithNames(igList);
3236 // For all ig
3237 for(uint i=0;i<igList.size();i++)
3239 string igName= CFile::getFilenameWithoutExtension(igList[i].second);
3240 if( LandscapeIGManager.isIGAddedToScene(igName) )
3241 nlinfo("%s", igList[i].second.c_str() );
3244 nlinfo("****** END Land IG Profile *******");
3249 //-----------------------------------------------
3250 // validateDialogs();
3251 // validate current dialogs by checking the distance between the two talking entities. End dialogs if they are too far
3252 //-----------------------------------------------
3253 void validateDialogs(const CGameContextMenu &gcm)
3256 if ( UserEntity->trader() != CLFECOMMON::INVALID_SLOT )
3258 CEntityCL * trader = EntitiesMngr.entity(UserEntity->trader());
3259 if (trader)
3261 CVectorD vect1 = trader->pos();
3262 CVectorD vect2 = UserEntity->pos();
3264 double distanceSquare = pow(vect1.x-vect2.x,2) + pow(vect1.y-vect2.y,2);
3266 if (gcm.isBuilding())
3268 if (distanceSquare > MaxTalkingOutpostBuildingDistSquare)
3270 // Prevent also the Server of ending bot chat
3271 if (CBotChatManager::getInstance()->getCurrPage())
3272 CBotChatManager::getInstance()->endDialog();
3275 else
3277 if(distanceSquare > MaxTalkingDistSquare)
3279 // Prevent also the Server of ending bot chat
3280 if(CBotChatManager::getInstance()->getCurrPage())
3281 CBotChatManager::getInstance()->endDialog();
3288 NLMISC_DYNVARIABLE(float, FPS, "The second smoothed frame rate per second")
3290 if (get) *pointer = 1.0f/smoothFPS.getSmoothValue ();
3293 // show hide all the debuging of ui
3294 NLMISC_COMMAND(debugUI, "Debug the ui : show/hide quads of bboxs and hotspots", "debugUI 1 or 0")
3296 if (args.size() > 1) return false;
3297 bool on = true;
3298 DebugUIFilter.clear();
3299 if (args.size() == 1)
3301 if(!args[0].empty() && !isdigit(args[0][0]))
3303 on= true;
3304 DebugUIFilter= args[0];
3306 else
3307 fromString(args[0], on);
3310 CGroupCell::setDebugUICell( on );
3311 DebugUIView = on;
3312 DebugUICtrl = on;
3313 DebugUIGroup = on;
3314 return true;
3318 // show hide the debuging of ui
3319 NLMISC_COMMAND(debugUIView, "Debug the ui : show/hide quads of bboxs and hotspots for views", "")
3321 DebugUIView = !DebugUIView;
3322 return true;
3325 // show hide the debuging of ui
3326 NLMISC_COMMAND(debugUICtrl, "Debug the ui : show/hide quads of bboxs and hotspots for ctrl", "")
3328 DebugUICtrl = !DebugUICtrl;
3329 return true;
3332 // show hide the debuging of ui
3333 NLMISC_COMMAND(debugUIGroup, "Debug the ui : show/hide quads of bboxs and hotspots for group", "")
3335 DebugUIGroup = !DebugUIGroup;
3336 return true;
3339 // show hide the debuging of cells
3340 NLMISC_COMMAND(debugUICell, "Debug the ui : show/hide quads of bboxs for cells", "")
3342 CGroupCell::setDebugUICell( !CGroupCell::getDebugUICell() );
3343 return true;
3346 // Set weather value
3347 NLMISC_COMMAND(setWeatherValue, "Set weather value", "")
3349 if (args.size() != 1) return false;
3350 float value;
3351 fromString(args[0], value);
3352 ManualWeatherValue = value / (ContinentMngr.cur()->WeatherFunction[CurrSeason].getNumWeatherSetups() - 1);
3353 return true;
3356 class CHandlerDebugUIGroup : public IActionHandler
3358 virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
3360 DebugUIGroup = !DebugUIGroup;
3363 REGISTER_ACTION_HANDLER( CHandlerDebugUIGroup, "debug_ui_group");
3365 class CHandlerDebugUICtrl : public IActionHandler
3367 virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
3369 DebugUICtrl = !DebugUICtrl;
3372 REGISTER_ACTION_HANDLER( CHandlerDebugUICtrl, "debug_ui_ctrl");
3374 class CHandlerDebugUIView : public IActionHandler
3376 virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
3378 DebugUIView = !DebugUIView;
3381 REGISTER_ACTION_HANDLER( CHandlerDebugUIView, "debug_ui_view");
3384 class CAHShowTimedFX : public IActionHandler
3386 void execute(CCtrlBase * /* pCaller */, const std::string &/* params */)
3388 if (ShowTimedFX)
3390 ShowTimedFXMode = (CTimedFXManager::TDebugDisplayMode) (ShowTimedFXMode + 1);
3391 if (ShowTimedFXMode == CTimedFXManager::DebugModeCount)
3393 ShowTimedFX = false;
3396 else
3398 ShowTimedFX = true;
3399 ShowTimedFXMode = CTimedFXManager::NoText;
3403 // ***************************************************************************
3404 REGISTER_ACTION_HANDLER (CAHShowTimedFX, "show_timed_fx");
3407 // ***************************************************************************
3408 void displayDebugClusters()
3410 // Get the Cluster system where the player (not the camera!) lies
3411 UGlobalPosition gPos;
3412 if(UserEntity->getPrimitive())
3413 UserEntity->getPrimitive()->getGlobalPosition(gPos, dynamicWI);
3414 // get the cluster IG associated to this pacs position
3415 UInstanceGroup *ig = getCluster(gPos);
3417 // Then display debug for it!
3418 if(ig)
3419 ig->displayDebugClusters(Driver, TextContext);
3421 // Draw the last camera 3rd person setuped
3422 CLineColor line;
3424 // start to test start
3425 line.V0= LastDebugClusterCameraThirdPersonStart;
3426 line.V1= LastDebugClusterCameraThirdPersonTestStart;
3427 line.Color0= CRGBA::Blue;
3428 line.Color1= CRGBA::Green;
3429 Driver->drawLine(line, GenericMat);
3431 // test start to result
3432 line.V0= LastDebugClusterCameraThirdPersonTestStart;
3433 if(LastDebugClusterCameraThirdPersonForceFPV)
3434 line.V1= LastDebugClusterCameraThirdPersonEnd;
3435 else
3436 line.V1= LastDebugClusterCameraThirdPersonResult;
3437 line.Color0= CRGBA::Red;
3438 line.Color1= CRGBA::Green;
3439 Driver->drawLine(line, GenericMat);
3441 // result to end
3442 if(!LastDebugClusterCameraThirdPersonForceFPV)
3444 line.V0= LastDebugClusterCameraThirdPersonResult;
3445 line.V1= LastDebugClusterCameraThirdPersonEnd;
3446 line.Color0= CRGBA::Yellow;
3447 line.Color1= CRGBA::Green;
3448 Driver->drawLine(line, GenericMat);
3451 // pelvis pos to test start
3452 line.V0= LastDebugClusterCameraThirdPersonPelvisPos;
3453 line.V1= LastDebugClusterCameraThirdPersonTestStart;
3454 line.Color0= CRGBA::Magenta;
3455 line.Color1= CRGBA::Green;
3456 Driver->drawLine(line, GenericMat);
3460 NLMISC_COMMAND(dumpFontTexture, "Write font texture to file", "")
3462 CInterfaceManager *im = CInterfaceManager::getInstance();
3463 if (TextContext)
3465 std::string fname = CFile::findNewFile("font-texture.tga");
3466 TextContext->dumpCacheTexture(fname.c_str());
3467 im->displaySystemInfo(fname + " created", "SYS");
3469 else
3471 im->displaySystemInfo("Error: TextContext == NULL", "SYS");
3473 return true;
3477 // ***************************************************************************
3478 void inGamePatchUncompleteWarning()
3480 CInterfaceManager *im = CInterfaceManager::getInstance();
3481 CLuaManager::getInstance().executeLuaScript("bgdownloader:inGamePatchUncompleteWarning()");
3483 CInterfaceManager *im = CInterfaceManager::getInstance();
3484 CGroupContainer *gc = dynamic_cast<CGroupContainer *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:bg_downloader"));
3485 if (gc)
3487 gc->setActive(true);
3488 CWidgetManager::getInstance()->setTopWindow(gc);
3489 gc->enableBlink(2);
3491 im->messageBoxWithHelp(CI18N::get("uiBGD_InGamePatchIncomplete"));
3492 im->displaySystemInfo(CI18N::get("uiBGD_InGamePatchIncompleteBC"), "BC");