1
0
forked from mirrors/0ad

rough but functional loading progress bar support.

numerous TODOs remaining - initial update instead of only after
completing first job; fix GUI overdraw issue; decrease granularity
(currently only 3 updates)

This was SVN commit r2033.
This commit is contained in:
janwas
2005-03-22 02:17:55 +00:00
parent 5e3b0f06ec
commit 6d792365aa
13 changed files with 246 additions and 45 deletions
+28
View File
@@ -16,6 +16,7 @@
#include "Pyrogenesis.h"
#include "Hotkey.h"
#include "ConfigDB.h"
#include "Loader.h"
#include "Quaternion.h"
#include "Unit.h"
@@ -69,6 +70,7 @@ CGameView::~CGameView()
UnloadResources();
}
void CGameView::Initialize(CGameAttributes *pAttribs)
{
CConfigValue* cfg;
@@ -96,6 +98,32 @@ void CGameView::Initialize(CGameAttributes *pAttribs)
InitResources();
}
struct ThunkParams
{
CGameView* const this_;
CGameAttributes* const pAttribs;
ThunkParams(CGameView* this__, CGameAttributes* pAttribs_)
: this_(this__), pAttribs(pAttribs_) {}
};
static int LoadThunk(void* param, double time_left)
{
const ThunkParams* p = (const ThunkParams*)param;
CGameView* const this_ = p->this_;
CGameAttributes* const pAttribs = p->pAttribs;
this_->Initialize(pAttribs);
delete p;
return 0;
}
void CGameView::RegisterInit(CGameAttributes *pAttribs)
{
void* param = new ThunkParams(this, pAttribs);
THROW_ERR(LDR_Register(LoadThunk, param, L"CGameView", 1000));
}
void CGameView::Render()
{
g_Renderer.SetCamera(m_Camera);
+2 -1
View File
@@ -60,8 +60,9 @@ public:
CGameView(CGame *pGame);
~CGameView();
void RegisterInit(CGameAttributes *pAttribs);
void Initialize(CGameAttributes *pGameAttributes);
// Update: Update all the view information (i.e. rotate camera, scroll,
// whatever). This will *not* change any World information - only the
// *presentation*
+11
View File
@@ -118,6 +118,17 @@ STMT(\
)
#endif
#define THROW_ERR(func)\
STMT(\
int err__ = (int)((func) & UINT_MAX);\
if(err__ < 0)\
{\
assert(0 && "FYI: CHECK_ERR reports that a function failed."\
"feel free to ignore or suppress this warning.");\
throw err__;\
}\
)
// useful because VC6 may return 0 on failure, instead of throwing.
+48 -5
View File
@@ -26,8 +26,8 @@
#endif
#include "lib/res/cursor.h"
#include "ps/Loader.h"
#include "ps/Font.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
@@ -53,6 +53,7 @@
#include "EntityManager.h"
#include "PathfindEngine.h"
#include "Scheduler.h"
#include "StringConvert.h"
#include "scripting/ScriptingHost.h"
#include "scripting/JSInterface_Entity.h"
@@ -481,7 +482,7 @@ static void Render()
oglCheck();
if (g_Game)
if (g_Game && g_Game->IsGameStarted())
{
g_Game->GetView()->Render();
@@ -943,6 +944,45 @@ TIMER(InitRenderer)
g_Renderer.SetViewport(vp);
}
static int ProgressiveLoad()
{
wchar_t description[100];
int progress_percent;
int ret = LDR_ProgressiveLoad(100e-3, description, ARRAY_SIZE(description), &progress_percent);
switch(ret)
{
// no load active => no-op (skip code below)
case 1:
return 1;
// current task isn't complete (we don't care about this distinction)
case ERR_TIMED_OUT:
break;
// just finished loading
case 0:
g_Game->ReallyStartGame();
wcscpy_s(description, ARRAY_SIZE(description), L"Game is starting..");
// LDR_ProgressiveLoad returns L""; set to valid text to
// avoid problems in converting to JSString
break;
// error!
default:
CHECK_ERR(ret);
// can't do this above due to legit ERR_TIMED_OUT
break;
}
// display progress / description in loading screen
CStrW i18n_description = translate(description);
JSString* js_desc = StringConvert::wstring_to_jsstring(g_ScriptingHost.getContext(), i18n_description);
g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(progress_percent));
g_ScriptingHost.SetGlobal("g_LoadDescription", STRING_TO_JSVAL(js_desc));
g_GUI.SendEventToAll("progress");
return 0;
}
u64 PREVTSC;
static void Shutdown()
@@ -1227,6 +1267,9 @@ PREVTSC=CURTSC;
}
#endif
}
static void Frame()
@@ -1244,11 +1287,11 @@ static void Frame()
assert(TimeSinceLastFrame >= 0.0f);
MICROLOG(L"reload files");
res_reload_changed_files();
MICROLOG(L"input");
ProgressiveLoad();
MICROLOG(L"input");
in_get_events();
g_SessionManager.Poll();
@@ -1259,7 +1302,7 @@ static void Frame()
if (g_Game && g_Game->IsGameStarted())
{
g_Game->Update(TimeSinceLastFrame);
if (!g_FixedFrameTiming)
g_Game->GetView()->Update(float(TimeSinceLastFrame));
+38 -15
View File
@@ -6,6 +6,7 @@
#include "gui/CGUI.h"
#endif
#include "timer.h"
#include "Loader.h"
CGame *g_Game=NULL;
@@ -39,6 +40,42 @@ CGame::~CGame()
debug_out("CGame::~CGame(): Game object DESTROYED\n");
}
PSRETURN CGame::RegisterInit(CGameAttributes* pAttribs)
{
LDR_BeginRegistering();
// RC, 040804 - GameView needs to be initialised before World, otherwise GameView initialisation
// overwrites anything stored in the map file that gets loaded by CWorld::Initialize with default
// values. At the minute, it's just lighting settings, but could be extended to store camera position.
// Storing lighting settings in the gameview seems a little odd, but it's no big deal; maybe move it at
// some point to be stored in the world object?
m_GameView.RegisterInit(pAttribs);
m_World.RegisterInit(pAttribs);
m_Simulation.RegisterInit(pAttribs);
LDR_EndRegistering();
return 0;
}
PSRETURN CGame::ReallyStartGame()
{
jsval rval;
JSBool ok = JS_CallFunctionName(g_ScriptingHost.getContext(),
g_GUI.GetScriptObject(), "reallyStartGame", 0, NULL, &rval);
assert(ok);
debug_out("GAME STARTED, ALL INIT COMPLETE\n");
m_GameStarted=true;
#ifndef NO_GUI
g_GUI.SendEventToAll("sessionstart");
#endif
return 0;
}
PSRETURN CGame::StartGame(CGameAttributes *pAttribs)
{
try
@@ -54,21 +91,7 @@ PSRETURN CGame::StartGame(CGameAttributes *pAttribs)
m_pLocalPlayer=m_Players[1];
// RC, 040804 - GameView needs to be initialised before World, otherwise GameView initialisation
// overwrites anything stored in the map file that gets loaded by CWorld::Initialize with default
// values. At the minute, it's just lighting settings, but could be extended to store camera position.
// Storing lighting settings in the gameview seems a little odd, but it's no big deal; maybe move it at
// some point to be stored in the world object?
m_GameView.Initialize(pAttribs);
m_World.Initialize(pAttribs);
m_Simulation.Initialize(pAttribs);
debug_out("GAME STARTED, ALL INIT COMPLETE\n");
m_GameStarted=true;
#ifndef NO_GUI
g_GUI.SendEventToAll("sessionstart");
#endif
RegisterInit(pAttribs);
}
catch (PSERROR_Game e)
{
+5 -1
View File
@@ -41,7 +41,8 @@ public:
Return: 0 on OK - a PSRETURN code otherwise
*/
PSRETURN StartGame(CGameAttributes *pGameAttributes);
PSRETURN ReallyStartGame();
/*
Perform all per-frame updates
*/
@@ -74,6 +75,9 @@ public:
{ return &m_GameView; }
inline CSimulation *GetSimulation()
{ return &m_Simulation; }
private:
PSRETURN RegisterInit(CGameAttributes* pAttribs);
};
extern CGame *g_Game;
+6 -4
View File
@@ -158,7 +158,7 @@ static bool HaveTimeForNextTask(double time_left, double time_budget, int estima
// (if it's less than that, we won't check the next task length)
if(time_left < 0.40*time_budget)
{
const double estimated_duration = estimated_duration_ms * 1e-3;
const double estimated_duration = estimated_duration_ms*1e-3;
// .. and the upcoming task is expected to be long -
// leave it for the next timeslice.
if(estimated_duration > time_left + time_budget*0.20)
@@ -201,10 +201,10 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description_,
while(!load_requests.empty())
{
const double time_left = end_time - get_time();
const LoadRequest& lr = load_requests.front();
double time_left = end_time - get_time();
// do actual work of loading
const LoadRequest& lr = load_requests.front();
ret = lr.func(lr.param, time_left);
// .. either finished entirely, or failed => remove from queue
if(ret != ERR_TIMED_OUT)
@@ -228,6 +228,7 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description_,
// check if we're out of time; take into account next task length.
// note: do this at the end of the loop to make sure there's
// progress even if the timer is low-resolution (=> time_left = 0).
time_left = end_time - get_time();
if(!HaveTimeForNextTask(time_left, time_budget, lr.estimated_duration_ms))
{
ret = ERR_TIMED_OUT;
@@ -237,7 +238,6 @@ int LDR_ProgressiveLoad(double time_budget, wchar_t* description_,
// queue is empty, we just finished.
state = IDLE;
assert(progress_percent == 100);
ret = 0;
// set output params (there are several return points above)
@@ -250,5 +250,7 @@ done:
description = load_requests.front().description.c_str();
wcscpy_s(description_, max_chars, description);
debug_out("LDR_ProgressiveLoad RETURNING; desc=%ls progress=%d\n", description_, progress_percent);
return ret;
}
+27
View File
@@ -12,6 +12,7 @@
#include "BaseEntityCollection.h"
#include "EntityManager.h"
#include "timer.h"
#include "Loader.h"
#define LOG_CATEGORY "world"
@@ -41,6 +42,32 @@ void CWorld::Initialize(CGameAttributes *pAttribs)
}
}
struct ThunkParams
{
CWorld* const this_;
CGameAttributes* const pAttribs;
ThunkParams(CWorld* this__, CGameAttributes* pAttribs_)
: this_(this__), pAttribs(pAttribs_) {}
};
static int LoadThunk(void* param, double time_left)
{
const ThunkParams* p = (const ThunkParams*)param;
CWorld* const this_ = p->this_;
CGameAttributes* const pAttribs = p->pAttribs;
this_->Initialize(pAttribs);
delete p;
return 0;
}
void CWorld::RegisterInit(CGameAttributes *pAttribs)
{
void* param = new ThunkParams(this, pAttribs);
THROW_ERR(LDR_Register(LoadThunk, param, L"CWorld", 1000));
}
CWorld::~CWorld()
{
// The Entity Manager should perhaps be converted into a CWorld member..
+5 -2
View File
@@ -18,6 +18,7 @@ class CWorld
// been converted
CUnitManager &m_UnitManager;
CEntityManager &m_EntityManager;
public:
inline CWorld(CGame *pGame):
m_pGame(pGame),
@@ -28,11 +29,13 @@ public:
~CWorld();
void RegisterInit(CGameAttributes *pGameAttributes);
/*
Initialize the World - load the map and all objects
Initialize the World - load the map and all objects
*/
void Initialize(CGameAttributes *pGameAttributes);
inline CTerrain *GetTerrain()
{ return &m_Terrain; }
inline CUnitManager *GetUnitManager()
+29
View File
@@ -12,6 +12,7 @@
#include "CConsole.h"
#include "Unit.h"
#include "Model.h"
#include "Loader.h"
#include "gui/CGUI.h"
@@ -37,6 +38,34 @@ void CSimulation::Initialize(CGameAttributes *pAttribs)
g_EntityManager.InitializeAll();
}
struct ThunkParams
{
CSimulation* const this_;
CGameAttributes* const pAttribs;
ThunkParams(CSimulation* this__, CGameAttributes* pAttribs_)
: this_(this__), pAttribs(pAttribs_) {}
};
static int LoadThunk(void* param, double time_left)
{
const ThunkParams* p = (const ThunkParams*)param;
CSimulation* const this_ = p->this_;
CGameAttributes* const pAttribs = p->pAttribs;
this_->Initialize(pAttribs);
delete p;
return 0;
}
void CSimulation::RegisterInit(CGameAttributes *pAttribs)
{
void* param = new ThunkParams(this, pAttribs);
THROW_ERR(LDR_Register(LoadThunk, param, L"CSimulation", 1000));
}
void CSimulation::Update(double frameTime)
{
m_DeltaTime += frameTime;
+2 -1
View File
@@ -33,8 +33,9 @@ public:
inline CTurnManager *GetTurnManager()
{ return m_pTurnManager; }
void RegisterInit(CGameAttributes *pGameAttributes);
void Initialize(CGameAttributes *pGameAttributes);
// Perform all CSimulation updates for the specified elapsed time.
void Update(double frameTime);