From f6e758a9d611f222909eaf145beb2e5932632051 Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 6 Dec 2018 09:58:29 +1100 Subject: [PATCH] Added a phase and optional iteration index/max-iteration to renderGUI to allow for smooth display of progress bar. --- src/main_loop.cpp | 29 ++++++++++++-- src/main_loop.hpp | 2 +- src/modes/world.cpp | 19 +++++---- src/physics/triangle_mesh.cpp | 3 ++ src/race/race_manager.cpp | 12 +++--- src/tracks/drive_graph.cpp | 5 +++ src/tracks/track.cpp | 75 +++++++++++++++++++++-------------- 7 files changed, 97 insertions(+), 48 deletions(-) diff --git a/src/main_loop.cpp b/src/main_loop.cpp index abf9c6c33..819750963 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -531,17 +531,38 @@ void MainLoop::run() } // run // ---------------------------------------------------------------------------- -void MainLoop::renderGUI() +/** Renders the GUI. This function is used during loading a track to get a + * responsive GUI, and allow GUI animations (like a progress bar) to be + * shown. + * \param phase An integer indicated a phase. The maximum number of phases + * is used to show a progress bar. + * \param loop_index If the call is from a loop, the current loop index. + * \param loop_size The number of loop iterations. Used to smooth update + * e.g. a progress bar. + */ +void MainLoop::renderGUI(int phase, int loop_index, int loop_size) { + // TODO: Rendering past 7000 causes the minimap to not work + // on higher graphical settings + //if(phase>7000) return; + uint64_t now = StkTime::getRealTimeMs(); float dt = (now - m_curr_time)/1000.0f; + // TODO: re-enable: Don't render if there frame rate would be too high (which would + // slow down loading time). + // if(dt<1.0/30.0f) return; + m_curr_time = now; - Log::verbose("mainloop", "Rendergui t %llu dt %f", - now, dt); + + // TODO: remove debug output + Log::verbose("mainloop", "Rendergui t %llu dt %f phase %d index %d / %d", + now, dt, phase, loop_index, loop_size); irr_driver->update(dt, /*is_loading*/true); - input_manager->update(dt); GUIEngine::update(dt); + //TODO: remove debug output + uint64_t now2 = StkTime::getRealTimeMs(); + Log::verbose("mainloop", " duration t %llu dt %llu", now, now2-now); } // renderGUI /* EOF */ diff --git a/src/main_loop.hpp b/src/main_loop.hpp index 3e36a9fb0..ebc60973d 100644 --- a/src/main_loop.hpp +++ b/src/main_loop.hpp @@ -58,7 +58,7 @@ public: void requestAbort() { m_request_abort = true; } void setThrottleFPS(bool throttle) { m_throttle_fps = throttle; } void setAllowLargeDt(bool enable) { m_allow_large_dt = enable; } - void renderGUI(); + void renderGUI(int phase, int loop_index=-1, int loop_size=-1); // ------------------------------------------------------------------------ /** Returns true if STK is to be stoppe. */ bool isAborted() const { return m_abort; } diff --git a/src/modes/world.cpp b/src/modes/world.cpp index efd264328..1b6ac9587 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -169,9 +169,9 @@ void World::init() // mode class, which would not have been constructed at the time that this // constructor is called, so the wrong race gui would be created. createRaceGUI(); - main_loop->renderGUI(); + main_loop->renderGUI(1000); RewindManager::create(); - main_loop->renderGUI(); + main_loop->renderGUI(1100); // Grab the track file Track *track = track_manager->getTrack(race_manager->getTrackName()); Scripting::ScriptEngine::getInstance(); @@ -185,10 +185,10 @@ void World::init() std::string script_path = track->getTrackFile("scripting.as"); Scripting::ScriptEngine::getInstance()->loadScript(script_path, true); - main_loop->renderGUI(); + main_loop->renderGUI(1200); // Create the physics Physics::getInstance(); - main_loop->renderGUI(); + main_loop->renderGUI(1300); unsigned int num_karts = race_manager->getNumberOfKarts(); //assert(num_karts > 0); @@ -197,12 +197,14 @@ void World::init() // This also defines the static Track::getCurrentTrack function. track->loadTrackModel(race_manager->getReverseTrack()); + main_loop->renderGUI(6998); if (gk > 0) { ReplayPlay::get()->load(); for (unsigned int k = 0; k < gk; k++) m_karts.push_back(ReplayPlay::get()->getGhostKart(k)); } + main_loop->renderGUI(6999); // Assign team of AIs for team mode before createKart if (hasTeam()) @@ -210,6 +212,7 @@ void World::init() for(unsigned int i=0; irenderGUI(7000, i, num_karts); if (race_manager->getKartType(i) == RaceManager::KT_GHOST) continue; std::string kart_ident = history->replayHistory() ? history->getKartIdent(i) @@ -233,15 +236,15 @@ void World::init() m_karts.push_back(new_kart); } // for i - main_loop->renderGUI(); + main_loop->renderGUI(7050); // Load other custom models if needed loadCustomModels(); - main_loop->renderGUI(); + main_loop->renderGUI(7100); // Must be called after all karts are created m_race_gui->init(); powerup_manager->computeWeightsForRace(race_manager->getNumberOfKarts()); - main_loop->renderGUI(); + main_loop->renderGUI(7200); if (UserConfigParams::m_particles_effects > 1) { Weather::getInstance(); // create Weather instance @@ -260,7 +263,7 @@ void World::init() } // if server with graphics of is watching replay } // if getNumCameras()==0 initTeamArrows(); - main_loop->renderGUI(); + main_loop->renderGUI(7300); } // init //----------------------------------------------------------------------------- diff --git a/src/physics/triangle_mesh.cpp b/src/physics/triangle_mesh.cpp index a8ed8ce4f..4b9d0c6d0 100644 --- a/src/physics/triangle_mesh.cpp +++ b/src/physics/triangle_mesh.cpp @@ -19,6 +19,7 @@ #include "physics/triangle_mesh.hpp" #include "config/stk_config.hpp" +#include "main_loop.hpp" #include "physics/physics.hpp" #include "utils/constants.hpp" #include "utils/time.hpp" @@ -187,6 +188,8 @@ void TriangleMesh::createPhysicalBody(float friction, // We need the collision shape, but not the collision object (since // this will be created when the dynamics body is anyway). createCollisionShape(/*create_collision_object*/false, serializedBhv); + main_loop->renderGUI(5583); + btTransform startTransform; startTransform.setIdentity(); m_motion_state = new btDefaultMotionState(startTransform); diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 5ac49af72..90fdbc53c 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -473,7 +473,7 @@ void RaceManager::startNew(bool from_overworld) void RaceManager::startNextRace() { - main_loop->renderGUI(); + main_loop->renderGUI(0); // Uncomment to debug audio leaks // sfx_manager->dump(); @@ -540,7 +540,7 @@ void RaceManager::startNextRace() } } - main_loop->renderGUI(); + main_loop->renderGUI(100); // the constructor assigns this object to the global // variable world. Admittedly a bit ugly, but simplifies @@ -579,21 +579,21 @@ void RaceManager::startNextRace() Log::error("RaceManager", "Could not create given race mode."); assert(0); } - main_loop->renderGUI(); + main_loop->renderGUI(200); // A second constructor phase is necessary in order to be able to // call functions which are overwritten (otherwise polymorphism // will fail and the results will be incorrect). Also in init() functions // can be called that use World::getWorld(). World::getWorld()->init(); - main_loop->renderGUI(); + main_loop->renderGUI(8000); // Now initialise all values that need to be reset from race to race // Calling this here reduces code duplication in init and restartRace() // functions. World::getWorld()->reset(); irr_driver->onLoadWorld(); - main_loop->renderGUI(); + main_loop->renderGUI(8100); // Save the current score and set last time to zero. This is necessary // if someone presses esc after finishing a gp, and selects restart: @@ -605,7 +605,7 @@ void RaceManager::startNextRace() m_kart_status[i].m_last_score = m_kart_status[i].m_score; m_kart_status[i].m_last_time = 0; } - main_loop->renderGUI(); + main_loop->renderGUI(8200); } // startNextRace //----------------------------------------------------------------------------- diff --git a/src/tracks/drive_graph.cpp b/src/tracks/drive_graph.cpp index 91007a3c7..fbce3806f 100644 --- a/src/tracks/drive_graph.cpp +++ b/src/tracks/drive_graph.cpp @@ -21,6 +21,7 @@ #include "config/user_config.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" +#include "main_loop.hpp" #include "modes/world.hpp" #include "race/race_manager.hpp" #include "tracks/check_lap.hpp" @@ -103,6 +104,8 @@ void DriveGraph::load(const std::string &quad_file_name, // Each quad is part of the graph exactly once now. for (unsigned int i = 0; i < quad->getNumNodes(); i++) { + main_loop->renderGUI(3331, i, quad->getNumNodes()); + const XMLNode *xml_node = quad->getNode(i); if (!(xml_node->getName() == "quad" || xml_node->getName() == "height-testing")) { @@ -184,6 +187,8 @@ void DriveGraph::load(const std::string &quad_file_name, // the node definitions, before the edges can be set. for(unsigned int node_index=0; node_indexgetNumNodes(); node_index++) { + main_loop->renderGUI(3333, node_index, xml->getNumNodes()); + const XMLNode *xml_node = xml->getNode(node_index); // Load the definition of edges between the graph nodes: // ----------------------------------------------------- diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a57aa8e88..b6cd49efa 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -850,6 +850,8 @@ void Track::createPhysicsModel(unsigned int main_track_count) // (like invisible walls). for (unsigned int i = 0; irenderGUI(5550, i, m_static_physics_only_nodes.size()); + convertTrackToBullet(m_static_physics_only_nodes[i]); if (UserConfigParams::m_physics_debug && m_static_physics_only_nodes[i]->getType() == scene::ESNT_MESH) @@ -869,11 +871,13 @@ void Track::createPhysicsModel(unsigned int main_track_count) else irr_driver->removeNode(m_static_physics_only_nodes[i]); } + main_loop->renderGUI(5560); if (!UserConfigParams::m_physics_debug) m_static_physics_only_nodes.clear(); for (unsigned int i = 0; irenderGUI(5565, i, m_static_physics_only_nodes.size()); convertTrackToBullet(m_object_physics_only_nodes[i]); m_object_physics_only_nodes[i]->setVisible(false); m_object_physics_only_nodes[i]->grab(); @@ -884,11 +888,16 @@ void Track::createPhysicsModel(unsigned int main_track_count) m_gfx_effect_mesh->removeAll(); for(unsigned int i=main_track_count; irenderGUI(5570, i, m_all_nodes.size()); convertTrackToBullet(m_all_nodes[i]); uploadNodeVertexBuffer(m_all_nodes[i]); } + main_loop->renderGUI(5580); m_track_mesh->createPhysicalBody(m_friction); + main_loop->renderGUI(5585); m_gfx_effect_mesh->createCollisionShape(); + main_loop->renderGUI(5590); + } // createPhysicsModel // ----------------------------------------------------------------------------- @@ -1218,7 +1227,7 @@ bool Track::loadMainTrack(const XMLNode &root) // m_all_cached_meshes. m_all_cached_meshes.push_back(tangent_mesh); irr_driver->grabAllTextures(tangent_mesh); - main_loop->renderGUI(); + main_loop->renderGUI(4000); #ifdef DEBUG std::string debug_name=model_name+" (main track, octtree)"; @@ -1253,7 +1262,7 @@ bool Track::loadMainTrack(const XMLNode &root) { for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++) { - main_loop->renderGUI(); + main_loop->renderGUI(4100, i, lod_xml_node->getNumNodes()); const XMLNode* lod_group_xml = lod_xml_node->getNode(i); for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++) @@ -1262,11 +1271,11 @@ bool Track::loadMainTrack(const XMLNode &root) } } } - main_loop->renderGUI(); + main_loop->renderGUI(4200); for (unsigned int i=0; igetNumNodes(); i++) { - main_loop->renderGUI(); + main_loop->renderGUI(4300, i, track_node->getNumNodes()); const XMLNode *n=track_node->getNode(i); // Animated textures have already been handled @@ -1437,9 +1446,11 @@ bool Track::loadMainTrack(const XMLNode &root) // This will (at this stage) only convert the main track model. for(unsigned int i=0; irenderGUI(4350, i, m_all_nodes.size()); convertTrackToBullet(m_all_nodes[i]); + main_loop->renderGUI(4360, i, m_all_nodes.size()); uploadNodeVertexBuffer(m_all_nodes[i]); - main_loop->renderGUI(); + main_loop->renderGUI(4400, i, m_all_nodes.size()); } // Free the tangent (track mesh) after converting to physics @@ -1454,7 +1465,7 @@ bool Track::loadMainTrack(const XMLNode &root) m_gfx_effect_mesh->createCollisionShape(); scene_node->setMaterialFlag(video::EMF_LIGHTING, true); scene_node->setMaterialFlag(video::EMF_GOURAUD_SHADING, true); - main_loop->renderGUI(); + main_loop->renderGUI(4500); return true; } // loadMainTrack @@ -1749,7 +1760,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) { reverse_track = false; } - main_loop->renderGUI(); + main_loop->renderGUI(3000); CheckManager::create(); assert(m_all_cached_meshes.size()==0); if(UserConfigParams::logMemory()) @@ -1789,7 +1800,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) // Add the track directory to the texture search path file_manager->pushTextureSearchPath(m_root, unique_id); file_manager->pushModelSearchPath(m_root); - main_loop->renderGUI(); + main_loop->renderGUI(3100); #ifndef SERVER_ONLY if (CVS->isGLSL()) @@ -1797,7 +1808,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) SP::SPShaderManager::get()->loadSPShaders(m_root); } #endif - main_loop->renderGUI(); + main_loop->renderGUI(3200); // First read the temporary materials.xml file if it exists try @@ -1817,7 +1828,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) // no temporary materials.xml file, ignore (void)e; } - main_loop->renderGUI(); + main_loop->renderGUI(3300); // Start building the scene graph // Soccer field with navmesh requires it @@ -1859,11 +1870,13 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } } // for igetNumNodes() } + main_loop->renderGUI(3320); if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadDriveGraph(mode_id, reverse_track); else if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh) loadArenaGraph(*root); + main_loop->renderGUI(3340); if (NetworkConfig::get()->isNetworking()) NetworkItemManager::create(); @@ -1873,6 +1886,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) ItemManager::updateRandomSeed((uint32_t)StkTime::getTimeSinceEpoch()); ItemManager::create(); } + main_loop->renderGUI(3360); // Set the default start positions. Node that later the default // positions can still be overwritten. @@ -1906,7 +1920,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) sidewards_distance, upwards_distance); } - main_loop->renderGUI(); + main_loop->renderGUI(3400); // we need to check for fog before loading the main track model if (const XMLNode *node = root->getNode("sun")) @@ -1923,7 +1937,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) node->get("fog-start-height", &m_fog_height_start); node->get("fog-end-height", &m_fog_height_end); } - main_loop->renderGUI(); + main_loop->renderGUI(3500); #ifndef SERVER_ONLY if (!ProfileWorld::isNoGraphics() && CVS->isGLSL() && m_use_fog) @@ -1950,7 +1964,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) SP::resetEmptyFogColor(); } #endif - main_loop->renderGUI(); + main_loop->renderGUI(3600); if (const XMLNode *node = root->getNode("lightshaft")) { @@ -1961,12 +1975,12 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } loadMainTrack(*root); - main_loop->renderGUI(); + main_loop->renderGUI(4700); unsigned int main_track_count = (unsigned int)m_all_nodes.size(); ModelDefinitionLoader model_def_loader(this); - main_loop->renderGUI(); + main_loop->renderGUI(4800); // Load LOD groups const XMLNode *lod_xml_node = root->getNode("lod"); @@ -1974,7 +1988,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) { for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++) { - main_loop->renderGUI(); + main_loop->renderGUI(4900, i, lod_xml_node->getNumNodes()); const XMLNode* lod_group_xml = lod_xml_node->getNode(i); for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++) @@ -1985,7 +1999,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } loadObjects(root, path, model_def_loader, true, NULL, NULL); - main_loop->renderGUI(); + main_loop->renderGUI(5000); // Correct the parenting of meta library for (auto& p : m_meta_library) @@ -1998,19 +2012,19 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) meta_ln->getNode()->setParent(ln->getNode()); recursiveUpdatePosition(meta_ln->getNode()); recursiveUpdatePhysics(p.second->getChildren()); - main_loop->renderGUI(); + main_loop->renderGUI(5050); } model_def_loader.cleanLibraryNodesAfterLoad(); - main_loop->renderGUI(); + main_loop->renderGUI(5100); Scripting::ScriptEngine::getInstance()->compileLoadedScripts(); - main_loop->renderGUI(); + main_loop->renderGUI(5200); // Init all track objects m_track_object_manager->init(); - main_loop->renderGUI(); + main_loop->renderGUI(5300); // ---- Fog @@ -2043,6 +2057,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) m_sky_sphere_percent); for(unsigned int i=0; igetMaterialCount(); i++) { + main_loop->renderGUI(5350, i, node->getMaterialCount()); + video::SMaterial &irrMaterial=node->getMaterial(i); for(unsigned int j=0; jsetClearbackBufferColor(m_sky_color); } #endif - main_loop->renderGUI(); + main_loop->renderGUI(5400); // ---- Set ambient color m_ambient_color = m_default_ambient_color; @@ -2107,10 +2123,10 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) m_sun->grab(); } #endif - main_loop->renderGUI(); + main_loop->renderGUI(5500); createPhysicsModel(main_track_count); - main_loop->renderGUI(); + main_loop->renderGUI(5600); freeCachedMeshVertexBuffer(); @@ -2131,7 +2147,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } } // for igetNumNodes() } - main_loop->renderGUI(); + main_loop->renderGUI(5700); if (m_is_ctf && race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG) @@ -2147,7 +2163,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } // for igetNumNodes() } delete root; - main_loop->renderGUI(); + main_loop->renderGUI(5800); if (NetworkConfig::get()->isNetworking() && NetworkConfig::get()->isClient()) @@ -2155,7 +2171,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) static_cast(NetworkItemManager::get()) ->initClientConfirmState(); } - main_loop->renderGUI(); + main_loop->renderGUI(5900); if (UserConfigParams::m_track_debug && Graph::get() && !m_is_cutscene) Graph::get()->createDebugMesh(); @@ -2184,7 +2200,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) { DriveGraph::get()->computeChecklineRequirements(); } - main_loop->renderGUI(); + main_loop->renderGUI(6000); EasterEggHunt *easter_world = dynamic_cast(world); if(easter_world) @@ -2192,7 +2208,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) std::string dir = StringUtils::getPath(m_filename); easter_world->readData(dir+"/easter_eggs.xml"); } - main_loop->renderGUI(); + main_loop->renderGUI(6100); STKTexManager::getInstance()->unsetTextureErrorMessage(); #ifndef SERVER_ONLY @@ -2227,6 +2243,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, for (unsigned int i = 0; i < node_count; i++) { + main_loop->renderGUI(4950, i, node_count); const XMLNode *node = root->getNode(i); const std::string name = node->getName(); // The track object was already converted before the loop, and the