First draft of a GPG3-style profiler (including tracing into scripts, after a fashion)
This was SVN commit r2090.
This commit is contained in:
parent
9ce31a5c5c
commit
bb7a22f32a
BIN
binaries/data/crashlog.dmp
Normal file
BIN
binaries/data/crashlog.dmp
Normal file
Binary file not shown.
BIN
binaries/data/crashlog.txt
Normal file
BIN
binaries/data/crashlog.txt
Normal file
Binary file not shown.
@ -17,8 +17,10 @@
|
||||
#include "Hotkey.h"
|
||||
#include "ConfigDB.h"
|
||||
#include "Loader.h"
|
||||
#include "Profile.h"
|
||||
#include "LoaderThunks.h"
|
||||
|
||||
|
||||
#include "Quaternion.h"
|
||||
#include "Unit.h"
|
||||
#include "Model.h"
|
||||
@ -121,9 +123,13 @@ void CGameView::Render()
|
||||
g_Renderer.SetCamera(m_Camera);
|
||||
|
||||
MICROLOG(L"render terrain");
|
||||
PROFILE_START( "render terrain" );
|
||||
RenderTerrain(m_pWorld->GetTerrain());
|
||||
PROFILE_END( "render terrain" );
|
||||
MICROLOG(L"render models");
|
||||
PROFILE_START( "render models" );
|
||||
RenderModels(m_pWorld->GetUnitManager());
|
||||
PROFILE_END( "render models" );
|
||||
}
|
||||
|
||||
void CGameView::RenderTerrain(CTerrain *pTerrain)
|
||||
|
@ -191,6 +191,12 @@ void CMapReader::ApplyData()
|
||||
// }
|
||||
}
|
||||
|
||||
// MT: Testing:
|
||||
if( i == 170 )
|
||||
{
|
||||
CStrW tom( "dick, harry" );
|
||||
}
|
||||
|
||||
CUnit* unit = g_UnitMan.CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL);
|
||||
|
||||
if (unit)
|
||||
|
@ -453,6 +453,7 @@ void IGUIObject::ScriptEvent(const CStr& Action)
|
||||
paramData[0] = OBJECT_TO_JSVAL(mouseObj);
|
||||
|
||||
jsval result;
|
||||
|
||||
JSBool ok = JS_CallFunction(g_ScriptingHost.getContext(), jsGuiObject, it->second, 1, paramData, &result);
|
||||
if (!ok)
|
||||
{
|
||||
|
@ -26,6 +26,8 @@
|
||||
#endif
|
||||
#include "lib/res/cursor.h"
|
||||
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/ProfileViewer.h"
|
||||
#include "ps/Loader.h"
|
||||
#include "ps/Font.h"
|
||||
#include "ps/CConsole.h"
|
||||
@ -489,7 +491,9 @@ static void Render()
|
||||
oglCheck();
|
||||
|
||||
MICROLOG(L"flush frame");
|
||||
PROFILE_START( "flush frame" );
|
||||
g_Renderer.FlushFrame();
|
||||
PROFILE_END( "flush frame" );
|
||||
|
||||
glPushAttrib( GL_ENABLE_BIT );
|
||||
glDisable( GL_LIGHTING );
|
||||
@ -498,22 +502,30 @@ static void Render()
|
||||
|
||||
if( g_EntGraph )
|
||||
{
|
||||
PROFILE( "render entity overlays" );
|
||||
glColor3f( 1.0f, 0.0f, 1.0f );
|
||||
|
||||
MICROLOG(L"render entities");
|
||||
g_EntityManager.renderAll(); // <-- collision outlines, pathing routes
|
||||
}
|
||||
|
||||
PROFILE_START( "render selection" );
|
||||
g_Mouseover.renderSelectionOutlines();
|
||||
g_Selection.renderSelectionOutlines();
|
||||
PROFILE_END( "render selection" );
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
else
|
||||
{
|
||||
PROFILE_START( "flush frame" );
|
||||
g_Renderer.FlushFrame();
|
||||
PROFILE_END( "flush frame" );
|
||||
}
|
||||
|
||||
oglCheck();
|
||||
|
||||
PROFILE_START( "render fonts" );
|
||||
MICROLOG(L"render fonts");
|
||||
// overlay mode
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
@ -529,13 +541,17 @@ static void Render()
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
PROFILE_END( "render fonts" );
|
||||
|
||||
oglCheck();
|
||||
|
||||
#ifndef NO_GUI
|
||||
// Temp GUI message GeeTODO
|
||||
glLoadIdentity();
|
||||
MICROLOG(L"render GUI");
|
||||
PROFILE_START( "render gui" );
|
||||
g_GUI.Draw();
|
||||
PROFILE_END( "render gui" );
|
||||
#endif
|
||||
|
||||
oglCheck();
|
||||
@ -552,6 +568,7 @@ static void Render()
|
||||
oglCheck();
|
||||
|
||||
{
|
||||
PROFILE( "render console" );
|
||||
glLoadIdentity();
|
||||
|
||||
MICROLOG(L"render console");
|
||||
@ -562,8 +579,18 @@ static void Render()
|
||||
|
||||
oglCheck();
|
||||
|
||||
|
||||
// Profile information
|
||||
|
||||
PROFILE_START( "render profiling" );
|
||||
RenderProfile();
|
||||
PROFILE_END( "render profiling" );
|
||||
|
||||
oglCheck();
|
||||
|
||||
if (g_Game && g_Game->IsGameStarted())
|
||||
{
|
||||
PROFILE( "render selection overlays" );
|
||||
g_Mouseover.renderOverlays();
|
||||
g_Selection.renderOverlays();
|
||||
}
|
||||
@ -730,6 +757,7 @@ TIMER(InitScripting)
|
||||
CEntity::ScriptingInit();
|
||||
CBaseEntity::ScriptingInit();
|
||||
JSI_Sound::ScriptingInit();
|
||||
CProfileNode::ScriptingInit();
|
||||
|
||||
#ifndef NO_GUI
|
||||
JSI_IGUIObject::init();
|
||||
@ -745,7 +773,6 @@ TIMER(InitScripting)
|
||||
CJSPropertyAccessor<CEntity>::ScriptingInit(); // <-- Doesn't really matter which we use, but we know CJSPropertyAccessor<T> is already being compiled for T = CEntity.
|
||||
CScriptEvent::ScriptingInit();
|
||||
|
||||
|
||||
g_ScriptingHost.DefineConstant( "ORDER_NONE", -1 );
|
||||
g_ScriptingHost.DefineConstant( "ORDER_GOTO", CEntityOrder::ORDER_GOTO );
|
||||
g_ScriptingHost.DefineConstant( "ORDER_PATROL", CEntityOrder::ORDER_PATROL );
|
||||
@ -1223,7 +1250,9 @@ TIMER(init_after_InitRenderer);
|
||||
|
||||
in_add_handler(conInputHandler);
|
||||
|
||||
in_add_handler(hotkeyInputHandler); // <- Leave this one until after all the others.
|
||||
in_add_handler(profilehandler);
|
||||
|
||||
in_add_handler(hotkeyInputHandler);
|
||||
|
||||
// I don't know how much this screws up, but the gui_handler needs
|
||||
// to be after the hotkey, so that input boxes can be typed in
|
||||
@ -1279,7 +1308,10 @@ static void Frame()
|
||||
{
|
||||
MICROLOG(L"In frame");
|
||||
|
||||
|
||||
PROFILE_START( "update music" );
|
||||
MusicPlayer.update();
|
||||
PROFILE_END( "update music" );
|
||||
|
||||
static double last_time;
|
||||
const double time = get_time();
|
||||
@ -1289,31 +1321,47 @@ static void Frame()
|
||||
// first call: set last_time and return
|
||||
assert(TimeSinceLastFrame >= 0.0f);
|
||||
|
||||
PROFILE_START( "reload changed files" );
|
||||
MICROLOG(L"reload files");
|
||||
res_reload_changed_files();
|
||||
PROFILE_END( "reload changed files" );
|
||||
|
||||
PROFILE_START( "progressive load" );
|
||||
ProgressiveLoad();
|
||||
PROFILE_END( "progressive load" );
|
||||
|
||||
PROFILE_START( "input" );
|
||||
MICROLOG(L"input");
|
||||
in_get_events();
|
||||
g_SessionManager.Poll();
|
||||
PROFILE_END( "input" );
|
||||
|
||||
PROFILE_START( "gui tick" );
|
||||
#ifndef NO_GUI
|
||||
g_GUI.TickObjects();
|
||||
#endif
|
||||
PROFILE_END( "gui tick" );
|
||||
|
||||
PROFILE_START( "game logic" );
|
||||
if (g_Game && g_Game->IsGameStarted())
|
||||
{
|
||||
PROFILE_START( "simulation update" );
|
||||
g_Game->Update(TimeSinceLastFrame);
|
||||
PROFILE_END( "simulation update" );
|
||||
|
||||
if (!g_FixedFrameTiming)
|
||||
{
|
||||
PROFILE( "camera update" );
|
||||
g_Game->GetView()->Update(float(TimeSinceLastFrame));
|
||||
}
|
||||
|
||||
PROFILE_START( "selection and interaction ui" );
|
||||
// TODO Where does GameView end and other things begin?
|
||||
g_Mouseover.update( TimeSinceLastFrame );
|
||||
g_Selection.update();
|
||||
PROFILE_END( "selection and interaction ui" );
|
||||
|
||||
|
||||
PROFILE_START( "sound update" );
|
||||
CCamera* camera = g_Game->GetView()->GetCamera();
|
||||
CMatrix3D& orientation = camera->m_Orientation;
|
||||
|
||||
@ -1322,6 +1370,7 @@ static void Frame()
|
||||
float* up = &orientation._data[4];
|
||||
if(snd_update(pos, dir, up) < 0)
|
||||
debug_out("snd_update failed\n");
|
||||
PROFILE_END( "sound update" );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1332,7 +1381,11 @@ static void Frame()
|
||||
debug_out("snd_update (pos=0 version) failed\n");
|
||||
}
|
||||
|
||||
PROFILE_END( "game logic" );
|
||||
|
||||
PROFILE_START( "update console" );
|
||||
g_Console->Update(TimeSinceLastFrame);
|
||||
PROFILE_END( "update console" );
|
||||
|
||||
// ugly, but necessary. these are one-shot events, have to be reset.
|
||||
|
||||
@ -1349,6 +1402,7 @@ static void Frame()
|
||||
mouseButtons[SDL_BUTTON_WHEELUP] = false;
|
||||
mouseButtons[SDL_BUTTON_WHEELDOWN] = false;
|
||||
|
||||
PROFILE_START( "render" );
|
||||
if(g_active)
|
||||
{
|
||||
MICROLOG(L"render");
|
||||
@ -1361,6 +1415,10 @@ static void Frame()
|
||||
else
|
||||
SDL_Delay(10);
|
||||
|
||||
PROFILE_END( "render" );
|
||||
|
||||
g_Profiler.Frame();
|
||||
|
||||
calc_fps();
|
||||
if (g_FixedFrameTiming && frameCount==100) quit=true;
|
||||
}
|
||||
@ -1371,6 +1429,8 @@ static void Frame()
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
new CProfileManager;
|
||||
|
||||
MICROLOG(L"In main");
|
||||
|
||||
MICROLOG(L"Init");
|
||||
@ -1393,6 +1453,8 @@ int main(int argc, char* argv[])
|
||||
MICROLOG(L"Shutdown");
|
||||
Shutdown();
|
||||
|
||||
delete &g_Profiler;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,182 @@
|
||||
#include "gui/CGUI.h"
|
||||
#endif
|
||||
#include "timer.h"
|
||||
#include "Profile.h"
|
||||
#include "Loader.h"
|
||||
|
||||
CGame *g_Game=NULL;
|
||||
|
||||
/*
|
||||
<<<<<<< .mine
|
||||
namespace PlayerArray_JS
|
||||
{
|
||||
JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
CGameAttributes *pInstance=(CGameAttributes *)JS_GetPrivate(cx, obj);
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_FALSE;
|
||||
uint index=g_ScriptingHost.ValueToInt(id);
|
||||
|
||||
// Clamp to a preset upper bound.
|
||||
// FIXME I guess we'll ultimately have max players as a config variable
|
||||
if (pInstance->m_NumPlayers > PS_MAX_PLAYERS)
|
||||
pInstance->m_NumPlayers = PS_MAX_PLAYERS;
|
||||
|
||||
// Resize array according to new number of players (note that the array
|
||||
// size will go up to PS_MAX_PLAYERS, but will never be made smaller -
|
||||
// this to avoid losing player pointers and make sure they are all
|
||||
// reclaimed in the end - it's just simpler that way ;-) )
|
||||
if (pInstance->m_NumPlayers+1 > pInstance->m_Players.size())
|
||||
{
|
||||
for (size_t i=pInstance->m_Players.size();i<=index;i++)
|
||||
{
|
||||
CPlayer *pNewPlayer=new CPlayer((uint)i);
|
||||
pNewPlayer->SetUpdateCallback(pInstance->m_PlayerUpdateCB, pInstance->m_PlayerUpdateCBData);
|
||||
pInstance->m_Players.push_back(pNewPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (index > pInstance->m_NumPlayers)
|
||||
return JS_FALSE;
|
||||
|
||||
*vp=OBJECT_TO_JSVAL(pInstance->m_Players[index]->GetScript());
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool SetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSClass Class = {
|
||||
"PlayerArray", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
GetProperty, SetProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
JSBool Construct( JSContext* cx, JSObject* obj, uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
if (argc != 0)
|
||||
return JS_FALSE;
|
||||
|
||||
JSObject *newObj=JS_NewObject(cx, &Class, NULL, obj);
|
||||
*rval=OBJECT_TO_JSVAL(newObj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
CGameAttributes::CGameAttributes():
|
||||
m_UpdateCB(NULL),
|
||||
m_MapFile("test01.pmp"),
|
||||
m_NumPlayers(2)
|
||||
{
|
||||
ONCE(
|
||||
g_ScriptingHost.DefineCustomObjectType(&PlayerArray_JS::Class,
|
||||
PlayerArray_JS::Construct, 0, NULL, NULL, NULL, NULL);
|
||||
|
||||
ScriptingInit();
|
||||
);
|
||||
|
||||
m_PlayerArrayJS=g_ScriptingHost.CreateCustomObject("PlayerArray");
|
||||
JS_SetPrivate(g_ScriptingHost.GetContext(), m_PlayerArrayJS, this);
|
||||
|
||||
AddSynchedProperty(L"mapFile", &m_MapFile);
|
||||
AddSynchedProperty(L"numPlayers", &m_NumPlayers);
|
||||
|
||||
m_Players.resize(4);
|
||||
for (int i=0;i<4;i++)
|
||||
m_Players[i]=new CPlayer(i);
|
||||
|
||||
m_Players[0]->SetName(L"Gaia");
|
||||
m_Players[0]->SetColour(SPlayerColour(0.2f, 0.7f, 0.2f));
|
||||
|
||||
m_Players[1]->SetName(L"Acumen");
|
||||
m_Players[1]->SetColour(SPlayerColour(1.0f, 0.0f, 0.0f));
|
||||
|
||||
m_Players[2]->SetName(L"Boco the Insignificant");
|
||||
m_Players[2]->SetColour(SPlayerColour(0.0f, 0.0f, 1.0f));
|
||||
|
||||
m_Players[3]->SetName(L"NoMonkey");
|
||||
m_Players[3]->SetColour(SPlayerColour(0.5f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
CGameAttributes::~CGameAttributes()
|
||||
{
|
||||
std::vector<CPlayer *>::iterator it=m_Players.begin();
|
||||
while (it != m_Players.end())
|
||||
{
|
||||
delete *it;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
jsval CGameAttributes::JSGetPlayers()
|
||||
{
|
||||
return OBJECT_TO_JSVAL(m_PlayerArrayJS);
|
||||
}
|
||||
|
||||
void CGameAttributes::SetValue(CStrW name, CStrW value)
|
||||
{
|
||||
ISynchedJSProperty *prop=GetSynchedProperty(name);
|
||||
if (prop)
|
||||
{
|
||||
prop->FromString(value);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameAttributes::Update(CStrW name, ISynchedJSProperty *attrib)
|
||||
{
|
||||
if (m_UpdateCB)
|
||||
m_UpdateCB(name, attrib->ToString(), m_UpdateCBData);
|
||||
}
|
||||
|
||||
void CGameAttributes::SetPlayerUpdateCallback(CPlayer::UpdateCallback *cb, void *userdata)
|
||||
{
|
||||
m_PlayerUpdateCB=cb;
|
||||
m_PlayerUpdateCBData=userdata;
|
||||
|
||||
for (size_t i=0;i<m_Players.size();i++)
|
||||
{
|
||||
m_Players[i]->SetUpdateCallback(cb, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameAttributes::ScriptingInit()
|
||||
{
|
||||
AddClassProperty(L"players", (GetFn)&CGameAttributes::JSGetPlayers);
|
||||
CJSObject<CGameAttributes>::ScriptingInit( "Game" );
|
||||
|
||||
}
|
||||
|
||||
/*void CGameAttributes::CreateJSObject()
|
||||
{
|
||||
CAttributeMap::CreateJSObject();
|
||||
|
||||
ONCE(
|
||||
g_ScriptingHost.DefineCustomObjectType(&PlayerArray_JS::Class,
|
||||
PlayerArray_JS::Construct, 0, NULL, NULL, NULL, NULL);
|
||||
);
|
||||
|
||||
m_PlayerArrayJS=g_ScriptingHost.CreateCustomObject("PlayerArray");
|
||||
JS_SetPrivate(g_ScriptingHost.GetContext(), m_PlayerArrayJS, this);
|
||||
int flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT;
|
||||
JS_DefineProperty(g_ScriptingHost.GetContext(), m_JSObject, "players",
|
||||
OBJECT_TO_JSVAL(m_PlayerArrayJS), NULL, NULL, flags);
|
||||
}
|
||||
|
||||
JSBool CGameAttributes::GetJSProperty(jsval id, jsval *ret)
|
||||
{
|
||||
CStr name=g_ScriptingHost.ValueToString(id);
|
||||
if (name == CStr("players"))
|
||||
return JS_TRUE;
|
||||
return CAttributeMap::GetJSProperty(id, ret);
|
||||
}*//*
|
||||
|
||||
=======
|
||||
>>>>>>> .r2037
|
||||
*/
|
||||
// Disable "warning C4355: 'this' : used in base member initializer list".
|
||||
// "The base-class constructors and class member constructors are called before
|
||||
// this constructor. In effect, you've passed a pointer to an unconstructed
|
||||
@ -37,6 +209,8 @@ CGame::CGame():
|
||||
|
||||
CGame::~CGame()
|
||||
{
|
||||
// Again, the in-game call tree is going to be different to the main menu one.
|
||||
g_Profiler.StructuralReset();
|
||||
debug_out("CGame::~CGame(): Game object DESTROYED\n");
|
||||
}
|
||||
|
||||
@ -63,14 +237,19 @@ PSRETURN CGame::ReallyStartGame()
|
||||
{
|
||||
#ifndef NO_GUI
|
||||
jsval rval;
|
||||
|
||||
JSBool ok = JS_CallFunctionName(g_ScriptingHost.getContext(),
|
||||
g_GUI.GetScriptObject(), "reallyStartGame", 0, NULL, &rval);
|
||||
|
||||
assert(ok);
|
||||
#endif
|
||||
|
||||
debug_out("GAME STARTED, ALL INIT COMPLETE\n");
|
||||
m_GameStarted=true;
|
||||
|
||||
// The call tree we've built for pregame probably isn't useful in-game.
|
||||
g_Profiler.StructuralReset();
|
||||
|
||||
#ifndef NO_GUI
|
||||
g_GUI.SendEventToAll("sessionstart");
|
||||
#endif
|
||||
|
@ -18,6 +18,59 @@ ERROR_GROUP(Game);
|
||||
// This may be overriden by system.cfg ("max_players")
|
||||
#define PS_MAX_PLAYERS 6
|
||||
|
||||
/*
|
||||
<<<<<<< .mine
|
||||
namespace PlayerArray_JS
|
||||
{
|
||||
JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
};
|
||||
|
||||
#define g_GameAttributes CGameAttributes::GetSingleton()
|
||||
class CGameAttributes:
|
||||
public CSynchedJSObject<CGameAttributes>,
|
||||
public Singleton<CGameAttributes>
|
||||
{
|
||||
public:
|
||||
typedef void (UpdateCallback)(CStrW name, CStrW newValue, void *data);
|
||||
|
||||
private:
|
||||
friend JSBool PlayerArray_JS::GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
|
||||
virtual void Update(CStrW name, ISynchedJSProperty *attrib);
|
||||
|
||||
UpdateCallback *m_UpdateCB;
|
||||
void *m_UpdateCBData;
|
||||
|
||||
CPlayer::UpdateCallback *m_PlayerUpdateCB;
|
||||
void *m_PlayerUpdateCBData;
|
||||
|
||||
jsval JSGetPlayers();
|
||||
|
||||
public:
|
||||
CStrW m_MapFile;
|
||||
uint m_NumPlayers;
|
||||
|
||||
CGameAttributes();
|
||||
virtual ~CGameAttributes();
|
||||
|
||||
void SetValue(CStrW name, CStrW value);
|
||||
|
||||
inline void SetUpdateCallback(UpdateCallback *cb, void *userdata)
|
||||
{
|
||||
m_UpdateCB=cb;
|
||||
m_UpdateCBData=userdata;
|
||||
}
|
||||
|
||||
void SetPlayerUpdateCallback(CPlayer::UpdateCallback *cb, void *userdata);
|
||||
|
||||
std::vector <CPlayer *> m_Players;
|
||||
JSObject *m_PlayerArrayJS;
|
||||
|
||||
static void ScriptingInit();
|
||||
};
|
||||
=======
|
||||
>>>>>>> .r2037
|
||||
*/
|
||||
class CGame
|
||||
{
|
||||
CWorld m_World;
|
||||
|
@ -22,7 +22,6 @@ CPlayerSlot::CPlayerSlot(int slotID, CPlayer *pPlayer):
|
||||
|
||||
//AddProperty(L"session", (GetFn)&CPlayerSlot::JSI_GetSession);
|
||||
AddReadOnlyProperty(L"session", &m_pSession);
|
||||
AddProperty(L"assignment", (GetFn)&CPlayerSlot::JSI_GetAssignment);
|
||||
AddReadOnlyProperty(L"player", &m_pPlayer);
|
||||
}
|
||||
|
||||
@ -34,6 +33,7 @@ void CPlayerSlot::ScriptingInit()
|
||||
AddMethod<bool, &CPlayerSlot::JSI_AssignClosed>("assignClosed", 0);
|
||||
AddMethod<bool, &CPlayerSlot::JSI_AssignToSession>("assignToSession", 1);
|
||||
AddMethod<bool, &CPlayerSlot::JSI_AssignOpen>("assignOpen", 0);
|
||||
AddClassProperty(L"assignment", (GetFn)&CPlayerSlot::JSI_GetAssignment);
|
||||
// AddMethod<bool, &CPlayerSlot::JSI_AssignAI>("assignAI", <num_args>);
|
||||
|
||||
CJSObject<CPlayerSlot>::ScriptingInit("PlayerSlot");
|
||||
@ -182,8 +182,6 @@ CGameAttributes::CGameAttributes():
|
||||
AddSynchedProperty(L"mapFile", &m_MapFile);
|
||||
AddSynchedProperty(L"numSlots", &m_NumSlots, &CGameAttributes::OnNumSlotsUpdate);
|
||||
|
||||
AddProperty(L"slots", (GetFn)&CGameAttributes::JSI_GetPlayerSlots);
|
||||
|
||||
m_Players.resize(9);
|
||||
for (int i=0;i<9;i++)
|
||||
m_Players[i]=new CPlayer(i);
|
||||
@ -248,6 +246,7 @@ void CGameAttributes::ScriptingInit()
|
||||
PlayerSlotArray_JS::Construct, 0, NULL, NULL, NULL, NULL);
|
||||
|
||||
AddMethod<jsval, &CGameAttributes::JSI_GetOpenSlot>("getOpenSlot", 0);
|
||||
AddClassProperty(L"slots", (GetFn)&CGameAttributes::JSI_GetPlayerSlots);
|
||||
|
||||
CJSObject<CGameAttributes>::ScriptingInit("GameAttributes");
|
||||
}
|
||||
|
@ -534,7 +534,8 @@ void CSelectedEntities::contextOrder( bool pushQueue )
|
||||
|
||||
|
||||
for( it = m_selected.begin(); it < m_selected.end(); it++ )
|
||||
if( (*it)->acceptsOrder( m_contextOrder, g_Mouseover.m_target ) )
|
||||
if( ( (*it)->GetPlayer() == g_Game->GetLocalPlayer() ) &&
|
||||
( (*it)->acceptsOrder( m_contextOrder, g_Mouseover.m_target ) ) )
|
||||
{
|
||||
contextRandomized = context;
|
||||
do
|
||||
@ -605,7 +606,7 @@ void CMouseoverEntities::update( float timestep )
|
||||
std::vector<HEntity>::iterator it;
|
||||
|
||||
for( it = onscreen->begin(); it < onscreen->end(); it++ )
|
||||
if( (*it)->m_extant )
|
||||
if( (*it)->m_extant && ( (*it)->GetPlayer() == g_Game->GetLocalPlayer() ) )
|
||||
m_mouseover.push_back( SMouseoverFader( *it, m_fademaximum, false ) );
|
||||
|
||||
delete( onscreen );
|
||||
@ -634,6 +635,10 @@ void CMouseoverEntities::update( float timestep )
|
||||
if( !(*it)->m_extant )
|
||||
continue;
|
||||
|
||||
// Can only bandbox units the local player controls.
|
||||
if( (*it)->GetPlayer() != g_Game->GetLocalPlayer() )
|
||||
continue;
|
||||
|
||||
CVector3D worldspace = (*it)->m_graphics_position;
|
||||
|
||||
float x, y;
|
||||
@ -723,6 +728,23 @@ void CMouseoverEntities::update( float timestep )
|
||||
|
||||
void CMouseoverEntities::addSelection()
|
||||
{
|
||||
// Rules for shift-click selection:
|
||||
|
||||
// If selecting a non-allied unit, you can only select one. You can't
|
||||
// select a mix of allied and non-allied units. Therefore:
|
||||
// Forbid shift-click of enemy units unless the selection is empty
|
||||
// Forbid shift-click of allied units if the selection contains one
|
||||
// or more enemy units.
|
||||
|
||||
if( ( m_mouseover.size() != 0 ) &&
|
||||
( m_mouseover.front().entity->GetPlayer() != g_Game->GetLocalPlayer() ) &&
|
||||
( g_Selection.m_selected.size() != 0 ) )
|
||||
return;
|
||||
|
||||
if( ( g_Selection.m_selected.size() != 0 ) &&
|
||||
( g_Selection.m_selected.front()->GetPlayer() != g_Game->GetLocalPlayer() ) )
|
||||
return;
|
||||
|
||||
std::vector<SMouseoverFader>::iterator it;
|
||||
for( it = m_mouseover.begin(); it < m_mouseover.end(); it++ )
|
||||
if( it->isActive && !g_Selection.isSelected( it->entity ) )
|
||||
@ -745,7 +767,8 @@ void CMouseoverEntities::setSelection()
|
||||
|
||||
void CMouseoverEntities::expandAcrossScreen()
|
||||
{
|
||||
std::vector<HEntity>* activeset = g_EntityManager.matches( isMouseoverType, isOnScreen );
|
||||
std::vector<HEntity>* activeset = g_EntityManager.matches(
|
||||
CEntityManager::EntityPredicateLogicalAnd<isMouseoverType,isOnScreen> );
|
||||
m_mouseover.clear();
|
||||
std::vector<HEntity>::iterator it;
|
||||
for( it = activeset->begin(); it < activeset->end(); it++ )
|
||||
@ -987,7 +1010,7 @@ int interactInputHandler( const SDL_Event* ev )
|
||||
return( EV_PASS );
|
||||
}
|
||||
|
||||
bool isOnScreen( CEntity* ev )
|
||||
bool isOnScreen( CEntity* ev, void* userdata )
|
||||
{
|
||||
CCamera *pCamera=g_Game->GetView()->GetCamera();
|
||||
|
||||
@ -1000,7 +1023,7 @@ bool isOnScreen( CEntity* ev )
|
||||
return( frustum.IsBoxVisible( ev->m_graphics_position, CBound() ) );
|
||||
}
|
||||
|
||||
bool isMouseoverType( CEntity* ev )
|
||||
bool isMouseoverType( CEntity* ev, void* userdata )
|
||||
{
|
||||
std::vector<SMouseoverFader>::iterator it;
|
||||
for( it = g_Mouseover.m_mouseover.begin(); it < g_Mouseover.m_mouseover.end(); it++ )
|
||||
@ -1010,29 +1033,3 @@ bool isMouseoverType( CEntity* ev )
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
|
||||
/*
|
||||
void pushCameraTarget( const CVector3D& target )
|
||||
{
|
||||
// Save the current position
|
||||
cameraTargets.push_back( g_Camera.m_Orientation.GetTranslation() );
|
||||
// And set the camera
|
||||
setCameraTarget( target );
|
||||
}
|
||||
|
||||
void setCameraTarget( const CVector3D& target )
|
||||
{
|
||||
// Maintain the same orientation and level of zoom, if we can
|
||||
// (do this by working out the point the camera is looking at, saving
|
||||
// the difference beteen that position and the camera point, and restoring
|
||||
// that difference to our new target)
|
||||
|
||||
cameraDelta = target - g_Camera.GetFocus();
|
||||
}
|
||||
|
||||
void popCameraTarget()
|
||||
{
|
||||
cameraDelta = cameraTargets.back() - g_Camera.m_Orientation.GetTranslation();
|
||||
cameraTargets.pop_back();
|
||||
}
|
||||
*/
|
||||
|
@ -118,8 +118,8 @@ struct CMouseoverEntities : public Singleton<CMouseoverEntities>
|
||||
void stopBandbox();
|
||||
};
|
||||
|
||||
bool isMouseoverType( CEntity* ev );
|
||||
bool isOnScreen( CEntity* ev );
|
||||
bool isMouseoverType( CEntity* ev, void* userdata );
|
||||
bool isOnScreen( CEntity* ev, void* userdata );
|
||||
|
||||
int interactInputHandler( const SDL_Event* ev );
|
||||
|
||||
|
@ -43,17 +43,6 @@ CNetClient::CNetClient(CGame *pGame, CGameAttributes *pGameAttribs):
|
||||
|
||||
m_pGame->GetSimulation()->SetTurnManager(this);
|
||||
|
||||
AddProperty(L"onStartGame", &m_OnStartGame);
|
||||
AddProperty(L"onChat", &m_OnChat);
|
||||
AddProperty(L"onConnectComplete", &m_OnConnectComplete);
|
||||
AddProperty(L"onDisconnect", &m_OnDisconnect);
|
||||
AddProperty(L"onClientConnect", &m_OnClientConnect);
|
||||
AddProperty(L"onClientDisconnect", &m_OnClientDisconnect);
|
||||
|
||||
AddProperty(L"password", &m_Password);
|
||||
AddProperty(L"playerName", &m_Name);
|
||||
AddProperty(L"sessions", &m_JSI_ServerSessions);
|
||||
|
||||
g_ScriptingHost.SetGlobal("g_NetClient", OBJECT_TO_JSVAL(GetScript()));
|
||||
}
|
||||
|
||||
@ -66,6 +55,20 @@ void CNetClient::ScriptingInit()
|
||||
{
|
||||
AddMethod<bool, &CNetClient::JSI_BeginConnect>("beginConnect", 1);
|
||||
|
||||
|
||||
|
||||
AddClassProperty(L"onStartGame", &CNetClient::m_OnStartGame);
|
||||
AddClassProperty(L"onChat", &CNetClient::m_OnChat);
|
||||
AddClassProperty(L"onConnectComplete", &CNetClient::m_OnConnectComplete);
|
||||
AddClassProperty(L"onDisconnect", &CNetClient::m_OnDisconnect);
|
||||
AddClassProperty(L"onClientConnect", &CNetClient::m_OnClientConnect);
|
||||
AddClassProperty(L"onClientDisconnect", &CNetClient::m_OnClientDisconnect);
|
||||
|
||||
|
||||
AddClassProperty(L"password", &CNetClient::m_Password);
|
||||
AddClassProperty<CStrW>(L"playerName", &CNetClient::m_Name);
|
||||
|
||||
AddClassProperty(L"sessions", &CNetClient::m_JSI_ServerSessions);
|
||||
CJSMap<SessionMap>::ScriptingInit("NetClient_SessionMap");
|
||||
CJSObject<CNetClient>::ScriptingInit("NetClient");
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
class CNetSession: public CMessageSocket
|
||||
{
|
||||
friend class CNetClient;
|
||||
protected:
|
||||
/*
|
||||
The MessageHandler callback follows the contract of HandleMessage, see
|
||||
|
@ -12,8 +12,6 @@ CPlayer::CPlayer(uint playerID):
|
||||
m_Colour(0.7f, 0.7f, 0.7f),
|
||||
m_UpdateCB(0)
|
||||
{
|
||||
AddReadOnlyProperty( L"id", &m_PlayerID );
|
||||
AddProperty( L"controlled", (GetFn)&CPlayer::JSI_GetControlledEntities);
|
||||
AddSynchedProperty( L"name", &m_Name );
|
||||
// HACK - since we have to use setColour to update this, we don't want to
|
||||
// expose a colour property. Meanwhile, we want to have a property "colour"
|
||||
@ -22,6 +20,7 @@ CPlayer::CPlayer(uint playerID):
|
||||
// to CJSObject's list
|
||||
ISynchedJSProperty *prop=new CSynchedJSProperty<SPlayerColour>(L"colour", &m_Colour, this);
|
||||
m_SynchedProperties[L"colour"]=prop;
|
||||
|
||||
}
|
||||
|
||||
CPlayer::~CPlayer()
|
||||
@ -35,6 +34,14 @@ void CPlayer::ScriptingInit()
|
||||
{
|
||||
AddMethod<jsval, &CPlayer::JSI_ToString>( "toString", 0 );
|
||||
AddMethod<jsval, &CPlayer::JSI_SetColour>( "setColour", 1);
|
||||
|
||||
AddReadOnlyClassProperty( L"id", &CPlayer::m_PlayerID );
|
||||
// MT: Work out how this fits with the Synched stuff...
|
||||
|
||||
// AddClassProperty( L"name", &CPlayer::m_Name );
|
||||
// AddClassProperty( L"colour", &CPlayer::m_Colour );
|
||||
AddClassProperty( L"controlled", (IJSObject::GetFn)JSI_GetControlledEntities );
|
||||
|
||||
CJSObject<CPlayer>::ScriptingInit( "Player" );
|
||||
}
|
||||
|
||||
|
250
source/ps/Profile.cpp
Normal file
250
source/ps/Profile.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "Profile.h"
|
||||
|
||||
// Note: As with the GPG profiler, name is assumed to be a pointer to a constant string; only pointer equality is checked.
|
||||
CProfileNode::CProfileNode( const char* _name, CProfileNode* _parent )
|
||||
{
|
||||
name = _name;
|
||||
recursion = 0;
|
||||
calls_total = 0;
|
||||
calls_frame_current = 0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
int i;
|
||||
for( i = 0; i < PROFILE_AMORTIZE_FRAMES; i++ )
|
||||
{
|
||||
calls_frame_buffer[i] = 0;
|
||||
time_frame_buffer[i] = 0.0;
|
||||
}
|
||||
calls_frame_last = calls_frame_buffer;
|
||||
calls_frame_amortized = 0.0f;
|
||||
#else
|
||||
calls_frame_last = 0;
|
||||
#endif
|
||||
time_total = 0.0;
|
||||
time_frame_current = 0.0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
time_frame_last = time_frame_buffer;
|
||||
time_frame_amortized = 0.0;
|
||||
#else
|
||||
time_frame_last = 0.0;
|
||||
#endif
|
||||
parent = _parent;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
CProfileNode::~CProfileNode()
|
||||
{
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
delete( *it );
|
||||
for( it = script_children.begin(); it != script_children.end(); it++ )
|
||||
delete( *it );
|
||||
}
|
||||
|
||||
const CProfileNode* CProfileNode::GetChild( const char* childName ) const
|
||||
{
|
||||
const_profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
if( (*it)->name == childName )
|
||||
return( *it );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
const CProfileNode* CProfileNode::GetScriptChild( const char* childName ) const
|
||||
{
|
||||
const_profile_iterator it;
|
||||
for( it = script_children.begin(); it != script_children.end(); it++ )
|
||||
if( (*it)->name == childName )
|
||||
return( *it );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
CProfileNode* CProfileNode::GetChild( const char* childName )
|
||||
{
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
if( (*it)->name == childName )
|
||||
return( *it );
|
||||
|
||||
CProfileNode* newNode = new CProfileNode( childName, this );
|
||||
children.push_back( newNode );
|
||||
return( newNode );
|
||||
}
|
||||
|
||||
CProfileNode* CProfileNode::GetScriptChild( const char* childName )
|
||||
{
|
||||
profile_iterator it;
|
||||
for( it = script_children.begin(); it != script_children.end(); it++ )
|
||||
if( (*it)->name == childName )
|
||||
return( *it );
|
||||
|
||||
CProfileNode* newNode = new CProfileNode( childName, this );
|
||||
script_children.push_back( newNode );
|
||||
return( newNode );
|
||||
}
|
||||
|
||||
bool CProfileNode::CanExpand()
|
||||
{
|
||||
return( !( children.empty() && script_children.empty() ) );
|
||||
}
|
||||
|
||||
void CProfileNode::Reset()
|
||||
{
|
||||
calls_total = 0;
|
||||
calls_frame_current = 0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
int i;
|
||||
for( i = 0; i < PROFILE_AMORTIZE_FRAMES; i++ )
|
||||
{
|
||||
calls_frame_buffer[i] = 0;
|
||||
time_frame_buffer[i] = 0.0;
|
||||
}
|
||||
calls_frame_last = calls_frame_buffer;
|
||||
calls_frame_amortized = 0.0f;
|
||||
#else
|
||||
calls_frame_last = 0;
|
||||
#endif
|
||||
time_total = 0.0;
|
||||
time_frame_current = 0.0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
time_frame_last = time_frame_buffer;
|
||||
time_frame_amortized = 0.0;
|
||||
#else
|
||||
time_frame_last = 0.0;
|
||||
#endif
|
||||
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
(*it)->Reset();
|
||||
for( it = script_children.begin(); it != script_children.end(); it++ )
|
||||
(*it)->Reset();
|
||||
}
|
||||
|
||||
void CProfileNode::Frame()
|
||||
{
|
||||
calls_total += calls_frame_current;
|
||||
time_total += time_frame_current;
|
||||
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
calls_frame_amortized -= *calls_frame_last;
|
||||
*calls_frame_last = calls_frame_current;
|
||||
calls_frame_amortized += calls_frame_current;
|
||||
time_frame_amortized -= *time_frame_last;
|
||||
*time_frame_last = time_frame_current;
|
||||
time_frame_amortized += time_frame_current;
|
||||
if( ++calls_frame_last == ( calls_frame_buffer + PROFILE_AMORTIZE_FRAMES ) )
|
||||
calls_frame_last = calls_frame_buffer;
|
||||
if( ++time_frame_last == ( time_frame_buffer + PROFILE_AMORTIZE_FRAMES ) )
|
||||
time_frame_last = time_frame_buffer;
|
||||
#else
|
||||
calls_frame_last = calls_frame_current;
|
||||
time_frame_last = time_frame_current;
|
||||
#endif
|
||||
|
||||
calls_frame_current = 0;
|
||||
time_frame_current = 0.0;
|
||||
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
(*it)->Frame();
|
||||
for( it = script_children.begin(); it != script_children.end(); it++ )
|
||||
(*it)->Frame();
|
||||
}
|
||||
|
||||
void CProfileNode::Call()
|
||||
{
|
||||
calls_frame_current++;
|
||||
if( recursion++ == 0 )
|
||||
start = get_time();
|
||||
}
|
||||
|
||||
bool CProfileNode::Return()
|
||||
{
|
||||
if( !parent ) return( false );
|
||||
|
||||
if( ( --recursion == 0 ) && ( calls_frame_current != 0 ) )
|
||||
time_frame_current += ( get_time() - start );
|
||||
return( recursion == 0 );
|
||||
}
|
||||
|
||||
void CProfileNode::ScriptingInit()
|
||||
{
|
||||
AddClassProperty( L"name", (IJSObject::GetFn)CProfileNode::JS_GetName );
|
||||
/*
|
||||
AddReadOnlyClassProperty( L"callsTotal", &CProfileNode::calls_total );
|
||||
AddReadOnlyClassProperty( L"callsPerFrame", &CProfileNode::calls_frame_last );
|
||||
AddReadOnlyClassProperty( L"timeTotal", &CProfileNode::time_total );
|
||||
AddReadOnlyClassProperty( L"timePerFrame", &CProfileNode::time_frame_last );
|
||||
*/
|
||||
CJSObject<CProfileNode, true>::ScriptingInit( "ProfilerNode" );
|
||||
}
|
||||
|
||||
CProfileManager::CProfileManager()
|
||||
{
|
||||
root = new CProfileNode( "root", NULL );
|
||||
current = root;
|
||||
frame_start = 0.0;
|
||||
}
|
||||
|
||||
CProfileManager::~CProfileManager()
|
||||
{
|
||||
delete( root );
|
||||
}
|
||||
|
||||
void CProfileManager::Start( const char* name )
|
||||
{
|
||||
if( name != current->GetName() )
|
||||
current = current->GetChild( name );
|
||||
current->Call();
|
||||
}
|
||||
|
||||
void CProfileManager::StartScript( const char* name )
|
||||
{
|
||||
if( name != current->GetName() )
|
||||
current = current->GetScriptChild( name );
|
||||
current->Call();
|
||||
}
|
||||
|
||||
void CProfileManager::Stop()
|
||||
{
|
||||
if( current->Return() )
|
||||
current = current->GetParent();
|
||||
}
|
||||
|
||||
void CProfileManager::Reset()
|
||||
{
|
||||
root->Reset();
|
||||
start = get_time();
|
||||
frame_start = get_time();
|
||||
}
|
||||
|
||||
void CProfileManager::Frame()
|
||||
{
|
||||
root->time_frame_current = ( get_time() - frame_start );
|
||||
root->Frame();
|
||||
|
||||
frame_start = get_time();
|
||||
}
|
||||
|
||||
void CProfileManager::StructuralReset()
|
||||
{
|
||||
delete( root );
|
||||
root = new CProfileNode( "root", NULL );
|
||||
current = root;
|
||||
ResetProfileViewer();
|
||||
}
|
||||
|
||||
double CProfileManager::GetTime()
|
||||
{
|
||||
return( get_time() - start );
|
||||
}
|
||||
|
||||
double CProfileManager::GetFrameTime()
|
||||
{
|
||||
return( get_time() - frame_start );
|
||||
}
|
||||
|
147
source/ps/Profile.h
Normal file
147
source/ps/Profile.h
Normal file
@ -0,0 +1,147 @@
|
||||
// Profile.h
|
||||
//
|
||||
// GPG3-style hierarchical profiler
|
||||
//
|
||||
// Mark Thompson (mark@wildfiregames.com / mot20@cam.ac.uk)
|
||||
|
||||
#include <vector>
|
||||
#include "Singleton.h"
|
||||
#include "scripting/ScriptableObject.h"
|
||||
#include "timer.h"
|
||||
|
||||
// TODO: Shouldn't depend on this.
|
||||
#include "ProfileViewer.h"
|
||||
|
||||
#define PROFILE_AMORTIZE
|
||||
#define PROFILE_AMORTIZE_FRAMES 50
|
||||
|
||||
class CProfileManager;
|
||||
|
||||
class CProfileNode : public CJSObject<CProfileNode, true>
|
||||
{
|
||||
friend class CProfileManager;
|
||||
|
||||
const char* name;
|
||||
int calls_total;
|
||||
int calls_frame_current;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
int calls_frame_buffer[PROFILE_AMORTIZE_FRAMES];
|
||||
int* calls_frame_last;
|
||||
float calls_frame_amortized;
|
||||
#else
|
||||
int calls_frame_last;
|
||||
#endif
|
||||
double time_total;
|
||||
double time_frame_current;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
double time_frame_buffer[PROFILE_AMORTIZE_FRAMES];
|
||||
double* time_frame_last;
|
||||
double time_frame_amortized;
|
||||
#else
|
||||
double time_frame_last;
|
||||
#endif
|
||||
|
||||
double start;
|
||||
int recursion;
|
||||
|
||||
CProfileNode* parent;
|
||||
std::vector<CProfileNode*> children;
|
||||
std::vector<CProfileNode*> script_children;
|
||||
|
||||
public:
|
||||
typedef std::vector<CProfileNode*>::iterator profile_iterator;
|
||||
typedef std::vector<CProfileNode*>::const_iterator const_profile_iterator;
|
||||
|
||||
CProfileNode( const char* name, CProfileNode* parent );
|
||||
~CProfileNode();
|
||||
|
||||
const char* GetName() const { return( name ); }
|
||||
int GetCalls() const { return( calls_total ); }
|
||||
double GetTime() const { return( time_total ); }
|
||||
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
float GetFrameCalls() const { return( calls_frame_amortized / PROFILE_AMORTIZE_FRAMES ); }
|
||||
double GetFrameTime() const { return( time_frame_amortized / PROFILE_AMORTIZE_FRAMES ); }
|
||||
#else
|
||||
int GetFrameCalls() const { return( calls_frame_last ); }
|
||||
double GetFrameTime() const { return( time_frame_last ); }
|
||||
#endif
|
||||
|
||||
const CProfileNode* GetChild( const char* name ) const;
|
||||
const CProfileNode* GetScriptChild( const char* name ) const;
|
||||
const std::vector<CProfileNode*>* GetChildren() const { return( &children ); }
|
||||
const std::vector<CProfileNode*>* GetScriptChildren() const { return( &script_children ); }
|
||||
|
||||
bool CanExpand();
|
||||
|
||||
CProfileNode* GetChild( const char* name );
|
||||
CProfileNode* GetScriptChild( const char* name );
|
||||
CProfileNode* GetParent() const { return( parent ); }
|
||||
|
||||
// Resets timing information for this node and all its children
|
||||
void Reset();
|
||||
// Resets frame timings for this node and all its children
|
||||
void Frame();
|
||||
// Enters the node
|
||||
void Call();
|
||||
// Leaves the node. Returns true if the node has actually been left
|
||||
bool Return();
|
||||
|
||||
// Javascript stuff...
|
||||
|
||||
static void ScriptingInit();
|
||||
jsval JS_GetName() { return( ToJSVal( CStrW( name ) ) ); }
|
||||
};
|
||||
|
||||
class CProfileManager : public Singleton<CProfileManager>
|
||||
{
|
||||
CProfileNode* root;
|
||||
CProfileNode* current;
|
||||
double start;
|
||||
double frame_start;
|
||||
|
||||
public:
|
||||
CProfileManager();
|
||||
~CProfileManager();
|
||||
|
||||
// Begins timing for a named subsection
|
||||
void Start( const char* name );
|
||||
void StartScript( const char* name );
|
||||
|
||||
// Ends timing for the current subsection
|
||||
void Stop();
|
||||
|
||||
// Resets all timing information
|
||||
void Reset();
|
||||
// Resets frame timing information
|
||||
void Frame();
|
||||
// Resets absolutely everything
|
||||
void StructuralReset();
|
||||
|
||||
inline const CProfileNode* GetCurrent() { return( current ); }
|
||||
inline const CProfileNode* GetRoot() { return( root ); }
|
||||
double GetTime();
|
||||
double GetFrameTime();
|
||||
};
|
||||
|
||||
#define g_Profiler CProfileManager::GetSingleton()
|
||||
|
||||
class CProfileSample
|
||||
{
|
||||
public:
|
||||
CProfileSample( const char* name )
|
||||
{
|
||||
g_Profiler.Start( name );
|
||||
}
|
||||
~CProfileSample()
|
||||
{
|
||||
g_Profiler.Stop();
|
||||
}
|
||||
};
|
||||
|
||||
// Put a PROFILE( xyz ) block at the start of all code to be profiled.
|
||||
// Profile blocks last until the end of the containing scope.
|
||||
#define PROFILE( name ) CProfileSample __profile( name )
|
||||
// Cheat a bit to make things slightly easier on the user
|
||||
#define PROFILE_START( name ) { CProfileSample __profile( name )
|
||||
#define PROFILE_END( name ) }
|
196
source/ps/ProfileViewer.cpp
Normal file
196
source/ps/ProfileViewer.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "precompiled.h"
|
||||
#include "ProfileViewer.h"
|
||||
#include "Profile.h"
|
||||
#include "Renderer.h"
|
||||
#include "res/unifont.h"
|
||||
#include "Hotkey.h"
|
||||
|
||||
bool profileVisible = true;
|
||||
extern int g_xres, g_yres;
|
||||
|
||||
const CProfileNode* currentNode = NULL;
|
||||
|
||||
void ResetProfileViewer()
|
||||
{
|
||||
currentNode = NULL;
|
||||
}
|
||||
|
||||
void RenderProfileNode( CProfileNode* node, int currentNodeid )
|
||||
{
|
||||
glPushMatrix();
|
||||
if( node->CanExpand() )
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef( -15.0f, 0.0f, 0.0f );
|
||||
glwprintf( L"%d", currentNodeid );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glwprintf( L"%hs", node->GetName() );
|
||||
glPopMatrix();
|
||||
glTranslatef( 230.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
glwprintf( L"%.3f", node->GetFrameCalls() );
|
||||
#else
|
||||
glwprintf( L"%d", node->GetFrameCalls() );
|
||||
#endif
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%.3f", node->GetFrameTime() * 1000.0f );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
|
||||
glwprintf( L"%.1f", node->GetFrameTime() * 100.0 / g_Profiler.GetRoot()->GetFrameTime() );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%.1f", node->GetFrameTime() * 100.0 / currentNode->GetFrameTime() );
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
|
||||
glTranslatef( 0.0f, 20.0f, 0.0f );
|
||||
}
|
||||
|
||||
void RenderProfile()
|
||||
{
|
||||
if( !profileVisible ) return;
|
||||
if( !currentNode ) currentNode = g_Profiler.GetRoot();
|
||||
|
||||
glPushMatrix();
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
|
||||
glTranslatef(2.0f, g_yres - 20.0f, 0.0f );
|
||||
glScalef(1.0f, -1.0f, 1.0f);
|
||||
|
||||
glPushMatrix();
|
||||
glwprintf( L"Profiling Information for: %hs (Time in node: %.3f msec/frame)", currentNode->GetName(), currentNode->GetFrameTime() * 1000.0f );
|
||||
glPopMatrix();
|
||||
glTranslatef( 20.0f, 20.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glPushMatrix();
|
||||
glwprintf( L"Name" );
|
||||
glPopMatrix();
|
||||
glTranslatef( 230.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"calls/frame" );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"msec/frame" );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%%/frame" );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%%/parent" );
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
CProfileNode::const_profile_iterator it;
|
||||
|
||||
glTranslatef( 0.0f, 20.0f, 0.0f );
|
||||
|
||||
float unlogged = currentNode->GetFrameTime();
|
||||
|
||||
int currentNodeid = 1;
|
||||
|
||||
for( it = currentNode->GetChildren()->begin(); it != currentNode->GetChildren()->end(); it++, currentNodeid++ )
|
||||
{
|
||||
unlogged -= (*it)->GetFrameTime();
|
||||
RenderProfileNode( *it, currentNodeid );
|
||||
}
|
||||
glColor3f( 1.0f, 0.5f, 0.5f );
|
||||
for( it = currentNode->GetScriptChildren()->begin(); it != currentNode->GetScriptChildren()->end(); it++, currentNodeid++ )
|
||||
{
|
||||
unlogged -= (*it)->GetFrameTime();
|
||||
RenderProfileNode( *it, currentNodeid );
|
||||
}
|
||||
glColor3f( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
glTranslatef( 0.0f, 20.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glwprintf( L"unlogged" );
|
||||
glPopMatrix();
|
||||
glTranslatef( 330.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%.3f", unlogged * 1000.0f );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%.1f", ( unlogged / g_Profiler.GetRoot()->GetFrameTime() ) * 100.0f );
|
||||
glPopMatrix();
|
||||
glTranslatef( 100.0f, 0.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glwprintf( L"%.1f", ( unlogged / currentNode->GetFrameTime() ) * 100.0f );
|
||||
glPopMatrix();
|
||||
glPopMatrix();
|
||||
|
||||
if( currentNode->GetParent() )
|
||||
{
|
||||
glTranslatef( 0.0f, 20.0f, 0.0f );
|
||||
glPushMatrix();
|
||||
glPushMatrix();
|
||||
glTranslatef( -15.0f, 0.0f, 0.0f );
|
||||
glwprintf( L"0" );
|
||||
glPopMatrix();
|
||||
glwprintf( L"back to parent" );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
int profilehandler( const SDL_Event* ev )
|
||||
{
|
||||
switch( ev->type )
|
||||
{
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
if( profileVisible )
|
||||
{
|
||||
int k = ev->key.keysym.sym - SDLK_0;
|
||||
if( k == 0 )
|
||||
{
|
||||
if( currentNode->GetParent() )
|
||||
currentNode = currentNode->GetParent();
|
||||
}
|
||||
else if( ( k >= 1 ) && ( k <= 9 ) )
|
||||
{
|
||||
k--;
|
||||
CProfileNode::const_profile_iterator it;
|
||||
for( it = currentNode->GetChildren()->begin(); it != currentNode->GetChildren()->end(); it++, k-- )
|
||||
if( (*it)->CanExpand() && !k )
|
||||
{
|
||||
currentNode = (*it);
|
||||
return( EV_HANDLED );
|
||||
}
|
||||
for( it = currentNode->GetScriptChildren()->begin(); it != currentNode->GetScriptChildren()->end(); it++, k-- )
|
||||
if( (*it)->CanExpand() && !k )
|
||||
{
|
||||
currentNode = (*it);
|
||||
return( EV_HANDLED );
|
||||
}
|
||||
return( EV_HANDLED );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_HOTKEYDOWN:
|
||||
if( ev->user.code == HOTKEY_PROFILE_TOGGLE )
|
||||
{
|
||||
profileVisible = !profileVisible;
|
||||
return( EV_HANDLED );
|
||||
}
|
||||
break;
|
||||
}
|
||||
return( EV_PASS );
|
||||
}
|
14
source/ps/ProfileViewer.h
Normal file
14
source/ps/ProfileViewer.h
Normal file
@ -0,0 +1,14 @@
|
||||
// ProfileViewer.h
|
||||
//
|
||||
// A temporary interface for viewing profile information
|
||||
|
||||
#ifndef PROFILE_VIEWER_INCLUDED
|
||||
#define PROFILE_VIEWER_INCLUDED
|
||||
|
||||
#include "input.h"
|
||||
|
||||
void ResetProfileViewer();
|
||||
void RenderProfile();
|
||||
int profilehandler( const SDL_Event* ev );
|
||||
|
||||
#endif
|
@ -32,6 +32,7 @@ void CWorld::Initialize(CGameAttributes *pAttribs)
|
||||
mapfilename += (CStr)pAttribs->m_MapFile;
|
||||
|
||||
CMapReader* reader = 0;
|
||||
|
||||
try {
|
||||
reader = new CMapReader;
|
||||
reader->LoadMap(mapfilename, &m_Terrain, &m_UnitManager, &g_LightEnv);
|
||||
|
@ -140,6 +140,13 @@ template<> bool ToPrimitive<bool>( JSContext* cx, jsval v, bool& Storage );
|
||||
template<> jsval ToJSVal<bool>( const bool& Native );
|
||||
template<> jsval ToJSVal<bool>( bool& Native );
|
||||
|
||||
/*
|
||||
// char*
|
||||
template<> bool ToPrimitive<char*>( JSContext* cx, jsval v, char*& Storage );
|
||||
template<> jsval ToJSVal<char*>( const char* Native );
|
||||
template<> jsval ToJSVal<char*>( char* Native );
|
||||
*/
|
||||
|
||||
// CStrW
|
||||
template<> bool ToPrimitive<CStrW>( JSContext* cx, jsval v, CStrW& Storage );
|
||||
template<> jsval ToJSVal<CStrW>( const CStrW& Native );
|
||||
|
@ -42,17 +42,17 @@ JSBool Point2d_Constructor(JSContext* UNUSEDPARAM(cx), JSObject* obj, uintN argc
|
||||
|
||||
void SColour::SColourInit( float _r, float _g, float _b, float _a )
|
||||
{
|
||||
AddProperty( L"r", &r );
|
||||
AddProperty( L"g", &g );
|
||||
AddProperty( L"b", &b );
|
||||
AddProperty( L"a", &a );
|
||||
|
||||
r = _r; g = _g; b = _b; a = _a;
|
||||
}
|
||||
|
||||
void SColour::ScriptingInit()
|
||||
{
|
||||
AddMethod<jsval, &SColour::ToString>( "toString", 0 );
|
||||
AddClassProperty<float>( L"r", (float IJSObject::*)&SColour::r );
|
||||
AddClassProperty<float>( L"g", (float IJSObject::*)&SColour::g );
|
||||
AddClassProperty<float>( L"b", (float IJSObject::*)&SColour::b );
|
||||
AddClassProperty<float>( L"a", (float IJSObject::*)&SColour::a );
|
||||
|
||||
CJSObject<SColour>::ScriptingInit( "Colour", SColour::Construct, 3 );
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,8 @@ JSPropertySpec ScriptGlobalTable[] =
|
||||
{ "console", GLOBAL_CONSOLE, JSPROP_PERMANENT | JSPROP_READONLY, JSI_Console::getConsole, NULL },
|
||||
{ "entities", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetEntitySet, NULL },
|
||||
{ "players", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetPlayerSet, NULL },
|
||||
{ "localPlayer", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetLocalPlayer, NULL },
|
||||
{ "localPlayer", 0, JSPROP_PERMANENT, GetLocalPlayer, SetLocalPlayer },
|
||||
{ "gaiaPlayer", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetGaiaPlayer, NULL },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@ -191,7 +192,7 @@ JSBool GetEntitySet( JSContext* context, JSObject* globalObject, jsval argv, jsv
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool GetPlayerSet( JSContext* cx, JSObject* globalObject, jsval argv, jsval* vp )
|
||||
JSBool GetPlayerSet( JSContext* cx, JSObject* globalObject, jsval id, jsval* vp )
|
||||
{
|
||||
std::vector<CPlayer*>* players = g_Game->GetPlayers();
|
||||
|
||||
@ -200,10 +201,29 @@ JSBool GetPlayerSet( JSContext* cx, JSObject* globalObject, jsval argv, jsval* v
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool GetLocalPlayer( JSContext* cx, JSObject* globalObject, jsval argv, jsval* vp )
|
||||
JSBool GetLocalPlayer( JSContext* cx, JSObject* globalObject, jsval id, jsval* vp )
|
||||
{
|
||||
*vp = OBJECT_TO_JSVAL( g_Game->GetLocalPlayer()->GetScript() );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool GetGaiaPlayer( JSContext* cx, JSObject* globalObject, jsval id, jsval* vp )
|
||||
{
|
||||
*vp = OBJECT_TO_JSVAL( g_Game->GetPlayer( 0 )->GetScript() );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool SetLocalPlayer( JSContext* context, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
CPlayer* newLocalPlayer = ToNative<CPlayer>( *vp );
|
||||
|
||||
if( !newLocalPlayer )
|
||||
{
|
||||
JS_ReportError( context, "Not a valid Player." );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
g_Game->SetLocalPlayer( newLocalPlayer );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,13 @@ JSFunc WriteLog;
|
||||
// Entity
|
||||
JSFunc getEntityByHandle;
|
||||
JSFunc getEntityTemplate;
|
||||
JSBool GetEntitySet( JSContext* context, JSObject* globalObject, jsval argv, jsval* vp );
|
||||
JSBool GetEntitySet( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
|
||||
// Player
|
||||
JSBool GetPlayerSet( JSContext* context, JSObject* globalObject, jsval argv, jsval* vp );
|
||||
JSBool GetPlayerSet( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
JSBool GetLocalPlayer( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
JSBool SetLocalPlayer( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
JSBool GetGaiaPlayer( JSContext* context, JSObject* globalObject, jsval id, jsval* vp );
|
||||
JSBool GetLocalPlayer( JSContext* context, JSObject* globalObject, jsval argv, jsval* vp );
|
||||
|
||||
// Camera
|
||||
|
@ -41,6 +41,8 @@
|
||||
#ifndef SCRIPTABLE_INCLUDED
|
||||
#define SCRIPTABLE_INCLUDED
|
||||
|
||||
class IJSObject;
|
||||
|
||||
class IJSProperty
|
||||
{
|
||||
public:
|
||||
@ -56,15 +58,15 @@ public:
|
||||
m_Intrinsic(true)
|
||||
{}
|
||||
|
||||
virtual jsval Get( JSContext* cx ) = 0;
|
||||
virtual void Set( JSContext* cx, jsval Value ) = 0;
|
||||
virtual jsval Get( JSContext* cx, IJSObject* owner ) = 0;
|
||||
virtual void Set( JSContext* cx, IJSObject* owner, jsval Value ) = 0;
|
||||
|
||||
// Copies the data directly out of a parent property
|
||||
// Warning: Don't use if you're not certain the properties are not of the same type.
|
||||
virtual void ImmediateCopy( IJSProperty* Copy ) = 0;
|
||||
virtual void ImmediateCopy( IJSObject* CopyTo, IJSObject* CopyFrom, IJSProperty* CopyProperty ) = 0;
|
||||
|
||||
jsval Get() { return( Get( g_ScriptingHost.GetContext() ) ); }
|
||||
void Set( jsval Value ) { return( Set( g_ScriptingHost.GetContext(), Value ) ); }
|
||||
jsval Get( IJSObject* owner ) { return( Get( g_ScriptingHost.GetContext(), owner ) ); }
|
||||
void Set( IJSObject* owner, jsval Value ) { return( Set( g_ScriptingHost.GetContext(), owner, Value ) ); }
|
||||
|
||||
virtual ~IJSProperty() {}
|
||||
};
|
||||
@ -175,7 +177,7 @@ public:
|
||||
Property = Target->HasProperty( Instance->m_PropertyRoot );
|
||||
if( Property )
|
||||
{
|
||||
*rval = Property->Get( cx );
|
||||
*rval = Property->Get( cx, Target );
|
||||
break;
|
||||
}
|
||||
Target = Target->m_Parent;
|
||||
@ -199,7 +201,7 @@ public:
|
||||
Property = Target->HasProperty( Instance->m_PropertyRoot );
|
||||
if( Property )
|
||||
{
|
||||
str = JS_ValueToString( cx, Property->Get( cx ) );
|
||||
str = JS_ValueToString( cx, Property->Get( cx, Target ) );
|
||||
break;
|
||||
}
|
||||
Target = Target->m_Parent;
|
||||
@ -228,11 +230,10 @@ template<typename T> JSClass CJSPropertyAccessor<T>::JSI_Class = {
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
template<typename T, bool ReadOnly> class CJSProperty : public IJSProperty
|
||||
{
|
||||
T* m_Data;
|
||||
|
||||
IJSObject* m_Owner;
|
||||
template<typename T, bool ReadOnly> class CJSSharedProperty : public IJSProperty
|
||||
{
|
||||
T IJSObject::*m_Data;
|
||||
|
||||
// Function on Owner to call after value is changed
|
||||
IJSObject::NotifyFn m_Update;
|
||||
@ -241,32 +242,71 @@ template<typename T, bool ReadOnly> class CJSProperty : public IJSProperty
|
||||
IJSObject::NotifyFn m_Freshen;
|
||||
|
||||
public:
|
||||
CJSProperty( T* Data, IJSObject* Owner = NULL, bool AllowsInheritance = false, IJSObject::NotifyFn Update = NULL, IJSObject::NotifyFn Freshen = NULL )
|
||||
CJSSharedProperty( T IJSObject::*Data, bool AllowsInheritance = false, IJSObject::NotifyFn Update = NULL, IJSObject::NotifyFn Freshen = NULL )
|
||||
{
|
||||
m_Data = Data;
|
||||
m_AllowsInheritance = AllowsInheritance;
|
||||
m_Update = Update;
|
||||
m_Freshen = Freshen;
|
||||
m_Intrinsic = true;
|
||||
m_Inherited = true;
|
||||
}
|
||||
jsval Get( JSContext* cx, IJSObject* owner )
|
||||
{
|
||||
if( m_Freshen ) (owner->*m_Freshen)();
|
||||
return( ToJSVal( owner->*m_Data ) );
|
||||
}
|
||||
void ImmediateCopy( IJSObject* CopyTo, IJSObject* CopyFrom, IJSProperty* CopyProperty )
|
||||
{
|
||||
assert( "Inheritance not supported for CJSSharedProperties" );
|
||||
}
|
||||
void Set( JSContext* cx, IJSObject* owner, jsval Value )
|
||||
{
|
||||
if( !ReadOnly )
|
||||
{
|
||||
if( m_Freshen ) (owner->*m_Freshen)();
|
||||
if( ToPrimitive( cx, Value, owner->*m_Data ) )
|
||||
if( m_Update ) (owner->*m_Update)();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T, bool ReadOnly> class CJSProperty : public IJSProperty
|
||||
{
|
||||
T* m_Data;
|
||||
|
||||
// Function on Owner to call after value is changed
|
||||
IJSObject::NotifyFn m_Update;
|
||||
|
||||
// Function on Owner to call before reading or writing the value
|
||||
IJSObject::NotifyFn m_Freshen;
|
||||
|
||||
public:
|
||||
CJSProperty( T* Data, bool AllowsInheritance = false, IJSObject::NotifyFn Update = NULL, IJSObject::NotifyFn Freshen = NULL )
|
||||
{
|
||||
assert( !( !Owner && ( Freshen || Update ) ) ); // Bad programmer.
|
||||
m_Data = Data;
|
||||
m_Owner = Owner;
|
||||
m_AllowsInheritance = AllowsInheritance;
|
||||
m_Update = Update;
|
||||
m_Freshen = Freshen;
|
||||
m_Intrinsic = true;
|
||||
}
|
||||
jsval Get( JSContext* cx )
|
||||
jsval Get( JSContext* cx, IJSObject* owner )
|
||||
{
|
||||
if( m_Freshen ) (m_Owner->*m_Freshen)();
|
||||
if( m_Freshen ) (owner->*m_Freshen)();
|
||||
return( ToJSVal( *m_Data ) );
|
||||
}
|
||||
void ImmediateCopy( IJSProperty* Copy )
|
||||
void ImmediateCopy( IJSObject* CopyTo, IJSObject* CopyFrom, IJSProperty* CopyProperty )
|
||||
{
|
||||
*m_Data = *( ((CJSProperty<T, ReadOnly>*)Copy)->m_Data );
|
||||
*m_Data = *( ( (CJSProperty*)CopyProperty )->m_Data );
|
||||
}
|
||||
void Set( JSContext* cx, jsval Value )
|
||||
void Set( JSContext* cx, IJSObject* owner, jsval Value )
|
||||
{
|
||||
if( !ReadOnly )
|
||||
{
|
||||
if( m_Freshen ) (m_Owner->*m_Freshen)();
|
||||
if( m_Freshen ) (owner->*m_Freshen)();
|
||||
if( ToPrimitive( cx, Value, *m_Data ) )
|
||||
if( m_Update ) (m_Owner->*m_Update)();
|
||||
if( m_Update ) (owner->*m_Update)();
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +328,7 @@ public:
|
||||
{
|
||||
m_JSAccessor = NULL;
|
||||
m_Intrinsic = false;
|
||||
m_Inherited = false;
|
||||
}
|
||||
};
|
||||
|
||||
@ -322,28 +363,24 @@ public:
|
||||
if( JSVAL_IS_GCTHING( m_Data ) )
|
||||
JS_RemoveRoot( g_ScriptingHost.GetContext(), (void*)&m_Data );
|
||||
}
|
||||
jsval Get( JSContext* cx )
|
||||
jsval Get( JSContext* cx, IJSObject* owner )
|
||||
{
|
||||
return( m_Data );
|
||||
}
|
||||
void Set( JSContext* cx, jsval Value )
|
||||
void Set( JSContext* cx, IJSObject* owner, jsval Value )
|
||||
{
|
||||
Uproot();
|
||||
m_Data = Value;
|
||||
Root();
|
||||
}
|
||||
void ImmediateCopy( IJSProperty* Copy )
|
||||
void ImmediateCopy( IJSObject* CopyTo, IJSObject* CopyFrom, IJSProperty* CopyProperty )
|
||||
{
|
||||
Uproot();
|
||||
m_Data = ((CJSValProperty*)Copy)->m_Data;
|
||||
Root();
|
||||
assert( 0 && "ImmediateCopy called on a CJSValProperty (something's gone wrong with the inheritance on this object)" );
|
||||
}
|
||||
};
|
||||
|
||||
class CJSFunctionProperty : public IJSProperty
|
||||
{
|
||||
IJSObject* m_Owner;
|
||||
|
||||
// Function on Owner to get the value
|
||||
IJSObject::GetFn m_Getter;
|
||||
|
||||
@ -351,28 +388,27 @@ class CJSFunctionProperty : public IJSProperty
|
||||
IJSObject::SetFn m_Setter;
|
||||
|
||||
public:
|
||||
CJSFunctionProperty( IJSObject* Owner, IJSObject::GetFn Getter, IJSObject::SetFn Setter )
|
||||
CJSFunctionProperty( IJSObject::GetFn Getter, IJSObject::SetFn Setter )
|
||||
{
|
||||
m_Inherited = false;
|
||||
m_Intrinsic = true;
|
||||
m_Owner = Owner;
|
||||
m_Getter = Getter;
|
||||
m_Setter = Setter;
|
||||
// Must at least be able to read
|
||||
assert( m_Owner && m_Getter );
|
||||
assert( m_Getter );
|
||||
}
|
||||
jsval Get( JSContext* cx )
|
||||
jsval Get( JSContext* cx, IJSObject* owner )
|
||||
{
|
||||
return( (m_Owner->*m_Getter)() );
|
||||
return( (owner->*m_Getter)() );
|
||||
}
|
||||
void Set( JSContext* cx, jsval Value )
|
||||
void Set( JSContext* cx, IJSObject* owner, jsval Value )
|
||||
{
|
||||
if( m_Setter )
|
||||
(m_Owner->*m_Setter)( Value );
|
||||
(owner->*m_Setter)( Value );
|
||||
}
|
||||
void ImmediateCopy( IJSProperty* Copy )
|
||||
void ImmediateCopy( IJSObject* CopyTo, IJSObject* CopyFrom, IJSProperty* CopyProperty )
|
||||
{
|
||||
assert( 0 && "ImmediateCopy called on a property wrapping getter/setter functions" );
|
||||
assert( 0 && "ImmediateCopy called on a property wrapping getter/setter functions (something's gone wrong with the inheritance for this object)" );
|
||||
}
|
||||
};
|
||||
|
||||
@ -419,7 +455,9 @@ public:
|
||||
if( prop )
|
||||
{
|
||||
// Already exists
|
||||
prop->Set( cx, *vp );
|
||||
prop->Set( cx, this, *vp );
|
||||
|
||||
prop->m_Inherited = false;
|
||||
|
||||
// If it's a C++ property, reflect this change in objects that inherit this.
|
||||
if( prop->m_AllowsInheritance && prop->m_Intrinsic )
|
||||
@ -430,11 +468,11 @@ public:
|
||||
{
|
||||
IJSObject* UpdateObj = UpdateSet.back();
|
||||
UpdateSet.pop_back();
|
||||
IJSProperty* UpdateProp = UpdateObj->m_Properties[PropertyName];
|
||||
IJSProperty* UpdateProp = UpdateObj->HasProperty( PropertyName );
|
||||
// Property must exist, also be a C++ property, and not have its value specified.
|
||||
if( UpdateProp && UpdateProp->m_Intrinsic && UpdateProp->m_Inherited )
|
||||
{
|
||||
UpdateProp->Set( cx, *vp );
|
||||
UpdateProp->Set( cx, this, *vp );
|
||||
InheritorsList::iterator it2;
|
||||
for( it2 = UpdateObj->m_Inheritors.begin(); it2 != UpdateObj->m_Inheritors.end(); it2++ )
|
||||
UpdateSet.push_back( *it2 );
|
||||
@ -491,7 +529,12 @@ public:
|
||||
|
||||
delete[]( JSI_methods );
|
||||
}
|
||||
|
||||
static void ScriptingShutdown()
|
||||
{
|
||||
PropertyTable::iterator it;
|
||||
for( it = m_SharedProperties.begin(); it != m_SharedProperties.end(); it++ )
|
||||
delete( it->second );
|
||||
}
|
||||
static void DefaultFinalize( JSContext *cx, JSObject *obj )
|
||||
{
|
||||
T* Instance = ToNative<T>( cx, obj );
|
||||
@ -541,6 +584,8 @@ public:
|
||||
private:
|
||||
static JSPropertySpec JSI_props[];
|
||||
static std::vector<JSFunctionSpec> m_Methods;
|
||||
static PropertyTable m_IntrinsicProperties;
|
||||
|
||||
|
||||
public:
|
||||
CJSObject()
|
||||
@ -627,7 +672,21 @@ public:
|
||||
if( cp && cp->m_AllowsInheritance )
|
||||
{
|
||||
assert( cp->m_Intrinsic );
|
||||
it->second->ImmediateCopy( cp );
|
||||
it->second->ImmediateCopy( this, m_Parent, cp );
|
||||
}
|
||||
}
|
||||
// Do the same for the shared properties table, too
|
||||
for( it = m_IntrinsicProperties.begin(); it != m_IntrinsicProperties.end(); it++ )
|
||||
{
|
||||
if( !it->second->m_Inherited )
|
||||
continue;
|
||||
|
||||
IJSProperty* cp = m_Parent->HasProperty( it->first );
|
||||
|
||||
if( cp && cp->m_AllowsInheritance )
|
||||
{
|
||||
assert( cp->m_Intrinsic );
|
||||
it->second->ImmediateCopy( this, m_Parent, cp );
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,10 +699,15 @@ public:
|
||||
IJSProperty* HasProperty( CStrW PropertyName )
|
||||
{
|
||||
PropertyTable::iterator it;
|
||||
it = m_Properties.find( PropertyName );
|
||||
if( it == m_Properties.end() )
|
||||
return( NULL );
|
||||
it = T::m_IntrinsicProperties.find( PropertyName );
|
||||
if( it != T::m_IntrinsicProperties.end() )
|
||||
return( it->second );
|
||||
|
||||
it = m_Properties.find( PropertyName );
|
||||
if( it != m_Properties.end() )
|
||||
return( it->second );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
void AddProperty( CStrW PropertyName, jsval Value )
|
||||
@ -669,9 +733,9 @@ public:
|
||||
{
|
||||
AddProperty( PropertyName, JSParseString( Value ) );
|
||||
}
|
||||
void AddProperty( CStrW PropertyName, GetFn Getter, SetFn Setter = NULL )
|
||||
static void AddClassProperty( CStrW PropertyName, GetFn Getter, SetFn Setter = NULL )
|
||||
{
|
||||
m_Properties[PropertyName] = new CJSFunctionProperty( this, Getter, Setter );
|
||||
T::m_IntrinsicProperties[PropertyName] = new CJSFunctionProperty( Getter, Setter );
|
||||
}
|
||||
template<typename ReturnType, ReturnType (T::*NativeFunction)( JSContext* cx, uintN argc, jsval* argv )>
|
||||
static void AddMethod( const char* Name, uintN MinArgs )
|
||||
@ -679,13 +743,21 @@ public:
|
||||
JSFunctionSpec FnInfo = { Name, CNativeFunction<T, ReadOnly, ReturnType, NativeFunction>::JSFunction, MinArgs, 0, 0 };
|
||||
T::m_Methods.push_back( FnInfo );
|
||||
}
|
||||
template<typename PropType> static void AddClassProperty( CStrW PropertyName, PropType T::*Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
|
||||
{
|
||||
T::m_IntrinsicProperties[PropertyName] = new CJSSharedProperty<PropType, ReadOnly>( (PropType IJSObject::*)Native, PropAllowInheritance, Update, Refresh );
|
||||
}
|
||||
template<typename PropType> static void AddReadOnlyClassProperty( CStrW PropertyName, PropType T::*Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
|
||||
{
|
||||
T::m_IntrinsicProperties[PropertyName] = new CJSSharedProperty<PropType, true>( (PropType IJSObject::*)Native, PropAllowInheritance, Update, Refresh );
|
||||
}
|
||||
template<typename PropType> void AddProperty( CStrW PropertyName, PropType* Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
|
||||
{
|
||||
m_Properties[PropertyName] = new CJSProperty<PropType, ReadOnly>( Native, this, PropAllowInheritance, Update, Refresh );
|
||||
m_Properties[PropertyName] = new CJSProperty<PropType, ReadOnly>( Native, PropAllowInheritance, Update, Refresh );
|
||||
}
|
||||
template<typename PropType> void AddReadOnlyProperty( CStrW PropertyName, PropType* Native, bool PropAllowInheritance = true, NotifyFn Update = NULL, NotifyFn Refresh = NULL )
|
||||
{
|
||||
m_Properties[PropertyName] = new CJSProperty<PropType, true>( Native, this, PropAllowInheritance, Update, Refresh );
|
||||
m_Properties[PropertyName] = new CJSProperty<PropType, true>( Native, PropAllowInheritance, Update, Refresh );
|
||||
}
|
||||
};
|
||||
|
||||
@ -703,13 +775,14 @@ template<typename T, bool ReadOnly> JSPropertySpec CJSObject<T, ReadOnly>::JSI_p
|
||||
};
|
||||
|
||||
template<typename T, bool ReadOnly> std::vector<JSFunctionSpec> CJSObject<T, ReadOnly>::m_Methods;
|
||||
template<typename T, bool ReadOnly> typename CJSObject<typename T, ReadOnly>::PropertyTable CJSObject<T, ReadOnly>::m_IntrinsicProperties;
|
||||
|
||||
template<typename T, bool ReadOnly> void CJSObject<T, ReadOnly>::GetProperty( JSContext* cx, CStrW PropertyName, jsval* vp )
|
||||
{
|
||||
IJSProperty* Property = HasProperty( PropertyName );
|
||||
if( Property && Property->m_Intrinsic )
|
||||
{
|
||||
*vp = Property->Get( cx );
|
||||
*vp = Property->Get( cx, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "ScriptingHost.h"
|
||||
#include "ScriptGlue.h"
|
||||
#include "CConsole.h"
|
||||
#include "Profile.h"
|
||||
#include <sstream>
|
||||
|
||||
#include "res/res.h"
|
||||
@ -53,6 +54,13 @@ ScriptingHost::ScriptingHost() : m_RunTime(NULL), m_Context(NULL), m_GlobalObjec
|
||||
|
||||
m_GlobalObject = JS_NewObject(m_Context, &GlobalClass, NULL, NULL);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Register our script and function handlers - note: docs say they don't like
|
||||
// nulls passed as closures, nor should they return nulls.
|
||||
JS_SetExecuteHook( m_RunTime, jshook_script, this );
|
||||
JS_SetCallHook( m_RunTime, jshook_function, this );
|
||||
#endif
|
||||
|
||||
if (m_GlobalObject == NULL)
|
||||
throw PSERROR_Scripting_GlobalObjectCreationFailed();
|
||||
|
||||
@ -379,3 +387,37 @@ void ScriptingHost::_CollectGarbage()
|
||||
{
|
||||
JS_GC(m_Context);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void* ScriptingHost::jshook_script( JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* ok, void* closure )
|
||||
{
|
||||
if( before )
|
||||
{
|
||||
g_Profiler.StartScript( "script invocation" );
|
||||
}
|
||||
else
|
||||
g_Profiler.Stop();
|
||||
|
||||
return( closure );
|
||||
}
|
||||
|
||||
void* ScriptingHost::jshook_function( JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* ok, void* closure )
|
||||
{
|
||||
JSFunction* fn = JS_GetFrameFunction( cx, fp );
|
||||
if( before )
|
||||
{
|
||||
if( fn )
|
||||
{
|
||||
g_Profiler.StartScript( JS_GetFunctionName( fn ) );
|
||||
}
|
||||
else
|
||||
g_Profiler.StartScript( "function invokation" );
|
||||
}
|
||||
else
|
||||
g_Profiler.Stop();
|
||||
|
||||
return( closure );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,10 @@ ERROR_TYPE(Scripting_DefineType, CreationFailed);
|
||||
|
||||
#include <jsapi.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <jsdbgapi.h>
|
||||
#endif
|
||||
|
||||
// Make JS debugging a little easier by automatically naming GC roots
|
||||
#ifndef NDEBUG
|
||||
// Don't simply #define NAME_ALL_GC_ROOTS, because jsapi.h is horridly broken
|
||||
@ -78,7 +82,12 @@ private:
|
||||
std::map < std::string, CustomType > m_CustomObjectTypes;
|
||||
|
||||
void _CollectGarbage();
|
||||
|
||||
#ifndef NDEBUG
|
||||
// A hook to capture script calls
|
||||
static void* jshook_script( JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* ok, void* closure );
|
||||
// A hook to capture function calls
|
||||
static void* jshook_function( JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* ok, void* closure );
|
||||
#endif
|
||||
public:
|
||||
|
||||
ScriptingHost();
|
||||
|
@ -73,7 +73,7 @@ struct CSynchedJSObjectBase
|
||||
CSynchedJSObjectBase *m_Owner;
|
||||
UpdateFn m_Update;
|
||||
|
||||
virtual void Set(JSContext *cx, jsval value)
|
||||
virtual void Set(JSContext *cx, IJSObject* owner, jsval value)
|
||||
{
|
||||
if (!ReadOnly)
|
||||
{
|
||||
@ -85,12 +85,12 @@ struct CSynchedJSObjectBase
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual jsval Get(JSContext *cx)
|
||||
virtual jsval Get(JSContext *cx, IJSObject* owner)
|
||||
{
|
||||
return ToJSVal(*m_Data);
|
||||
}
|
||||
|
||||
virtual void ImmediateCopy(IJSProperty *other)
|
||||
virtual void ImmediateCopy(IJSObject* CopyFrom, IJSObject* CopyTo, IJSProperty *other)
|
||||
{
|
||||
*m_Data = *( ((CSynchedJSProperty<PropType, ReadOnly>*)other)->m_Data );
|
||||
}
|
||||
|
@ -11,8 +11,10 @@
|
||||
|
||||
CBaseEntity::CBaseEntity()
|
||||
{
|
||||
m_base = NULL;
|
||||
|
||||
AddProperty( L"tag", &m_Tag, false );
|
||||
AddProperty( L"parent", (CBaseEntity**)&m_base, false );
|
||||
AddProperty( L"parent", &m_base, false );
|
||||
AddProperty( L"actions.move.speed", &m_speed );
|
||||
AddProperty( L"actions.move.turningradius", &m_turningRadius );
|
||||
AddProperty( L"actions.attack.range", &m_meleeRange );
|
||||
@ -24,8 +26,6 @@ CBaseEntity::CBaseEntity()
|
||||
for( int t = 0; t < EVENT_LAST; t++ )
|
||||
AddProperty( EventNames[t], &m_EventHandlers[t] );
|
||||
|
||||
m_base = NULL;
|
||||
|
||||
// Initialize, make life a little easier on the scriptors
|
||||
m_speed = m_turningRadius = m_meleeRange = m_meleeRangeMin = 0.0f;
|
||||
m_extant = true; m_corpse = CStrW();
|
||||
@ -193,7 +193,7 @@ void CBaseEntity::XMLLoadProperty( const CXeromyces& XeroFile, const XMBElement&
|
||||
{
|
||||
if( !Existing->m_Intrinsic )
|
||||
LOG( WARNING, LOG_CATEGORY, "CBaseEntity::XMLAddProperty: %s already defined for %s. Property trees will be merged.", PropertyName.c_str(), m_Tag.c_str() );
|
||||
Existing->Set( JSParseString( Source.getText() ) );
|
||||
Existing->Set( this, JSParseString( Source.getText() ) );
|
||||
Existing->m_Inherited = false;
|
||||
}
|
||||
else
|
||||
@ -221,7 +221,7 @@ void CBaseEntity::XMLLoadProperty( const CXeromyces& XeroFile, const XMBElement&
|
||||
|
||||
if( Existing )
|
||||
{
|
||||
Existing->Set( JSParseString( Attribute.Value ) );
|
||||
Existing->Set( this, JSParseString( Attribute.Value ) );
|
||||
Existing->m_Inherited = false;
|
||||
}
|
||||
else
|
||||
@ -247,6 +247,7 @@ void CBaseEntity::XMLLoadProperty( const CXeromyces& XeroFile, const XMBElement&
|
||||
void CBaseEntity::ScriptingInit()
|
||||
{
|
||||
AddMethod<jsval, &CBaseEntity::ToString>( "toString", 0 );
|
||||
|
||||
CJSObject<CBaseEntity>::ScriptingInit( "EntityTemplate" );
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "Profile.h"
|
||||
|
||||
#include "Entity.h"
|
||||
#include "EntityManager.h"
|
||||
#include "BaseEntityCollection.h"
|
||||
@ -26,7 +28,6 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
|
||||
m_ahead.x = sin( m_orientation );
|
||||
m_ahead.y = cos( m_orientation );
|
||||
|
||||
AddProperty( L"template", (CBaseEntity**)&m_base, false, (NotifyFn)&CEntity::loadBase );
|
||||
AddProperty( L"actions.move.speed", &m_speed );
|
||||
AddProperty( L"selected", &m_selected, false, (NotifyFn)&CEntity::checkSelection );
|
||||
AddProperty( L"group", &m_grouped, false, (NotifyFn)&CEntity::checkGroup );
|
||||
@ -172,6 +173,8 @@ void CEntity::update( size_t timestep )
|
||||
// still needs to be (re-)evaluated; else 'false' to terminate the processing of
|
||||
// this entity in this timestep.
|
||||
|
||||
PROFILE_START( "state processing" );
|
||||
|
||||
while( !m_orderQueue.empty() )
|
||||
{
|
||||
CEntityOrder* current = &m_orderQueue.front();
|
||||
@ -180,6 +183,8 @@ void CEntity::update( size_t timestep )
|
||||
|
||||
if( m_transition )
|
||||
{
|
||||
PROFILE( "state transition / order" );
|
||||
|
||||
CEntity* target = NULL;
|
||||
if( current->m_data[0].entity )
|
||||
target = &( *( current->m_data[0].entity ) );
|
||||
@ -229,8 +234,11 @@ void CEntity::update( size_t timestep )
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_END( "state processing" );
|
||||
|
||||
if( m_actor )
|
||||
{
|
||||
PROFILE( "animation updates" );
|
||||
if( m_extant )
|
||||
{
|
||||
if( ( m_lastState != -1 ) || !m_actor->GetModel()->GetAnimation() )
|
||||
@ -242,6 +250,7 @@ void CEntity::update( size_t timestep )
|
||||
|
||||
if( m_lastState != -1 )
|
||||
{
|
||||
PROFILE( "state transition event" );
|
||||
CEntity* d0;
|
||||
CVector3D d1;
|
||||
CEventOrderTransition evt( m_lastState, -1, d0, d1 );
|
||||
@ -313,7 +322,29 @@ void CEntity::dispatch( const CMessage* msg )
|
||||
|
||||
bool CEntity::DispatchEvent( CScriptEvent* evt )
|
||||
{
|
||||
return( m_EventHandlers[evt->m_TypeCode].DispatchEvent( GetScript(), evt ) );
|
||||
// MT: HACK. And it leaks.
|
||||
static std::map<CStrW, char*> evMap;
|
||||
char* data;
|
||||
std::map<CStrW, char*>::iterator it = evMap.find( evt->m_Type );
|
||||
if( it != evMap.end() )
|
||||
{
|
||||
data = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
CStr8 short_string( evt->m_Type );
|
||||
int length = short_string.length();
|
||||
data = new char[length + 9];
|
||||
strcpy( data, "script: " );
|
||||
strcpy( data + 8, short_string.c_str() );
|
||||
data[length + 8] = 0;
|
||||
evMap.insert( std::pair<CStrW, char*>( evt->m_Type, data ) );
|
||||
}
|
||||
|
||||
g_Profiler.StartScript( data );
|
||||
bool rval = m_EventHandlers[evt->m_TypeCode].DispatchEvent( GetScript(), evt );
|
||||
g_Profiler.Stop();
|
||||
return( rval );
|
||||
}
|
||||
|
||||
void CEntity::clearOrders()
|
||||
@ -613,6 +644,10 @@ void CEntity::ScriptingInit()
|
||||
AddMethod<bool, &CEntity::Kill>( "kill", 0 );
|
||||
AddMethod<bool, &CEntity::Damage>( "damage", 1 );
|
||||
AddMethod<bool, &CEntity::IsIdle>( "isIdle", 0 );
|
||||
|
||||
|
||||
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
|
||||
|
||||
CJSObject<CEntity>::ScriptingInit( "Entity", Construct, 2 );
|
||||
}
|
||||
|
||||
|
@ -54,17 +54,7 @@ HEntity* CEntityManager::getByHandle( u16 index )
|
||||
return( new HEntity( index ) );
|
||||
}
|
||||
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate )
|
||||
{
|
||||
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
||||
for( int i = 0; i < MAX_HANDLES; i++ )
|
||||
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
||||
if( predicate( m_entities[i].m_entity ) )
|
||||
matchlist->push_back( HEntity( i ) );
|
||||
return( matchlist );
|
||||
}
|
||||
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicateUD predicate, void* userdata )
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate, void* userdata )
|
||||
{
|
||||
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
||||
for( int i = 0; i < MAX_HANDLES; i++ )
|
||||
@ -74,26 +64,6 @@ std::vector<HEntity>* CEntityManager::matches( EntityPredicateUD predicate, void
|
||||
return( matchlist );
|
||||
}
|
||||
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate1, EntityPredicate predicate2 )
|
||||
{
|
||||
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
||||
for( int i = 0; i < MAX_HANDLES; i++ )
|
||||
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
||||
if( predicate1( m_entities[i].m_entity ) && predicate2( m_entities[i].m_entity ) )
|
||||
matchlist->push_back( HEntity( i ) );
|
||||
return( matchlist );
|
||||
}
|
||||
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicateUD predicate1, EntityPredicateUD predicate2, void* userdata )
|
||||
{
|
||||
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
||||
for( int i = 0; i < MAX_HANDLES; i++ )
|
||||
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
||||
if( predicate1( m_entities[i].m_entity, userdata ) && predicate2( m_entities[i].m_entity, userdata ) )
|
||||
matchlist->push_back( HEntity( i ) );
|
||||
return( matchlist );
|
||||
}
|
||||
|
||||
std::vector<HEntity>* CEntityManager::getExtant()
|
||||
{
|
||||
std::vector<HEntity>* activelist = new std::vector<HEntity>;
|
||||
|
@ -79,7 +79,9 @@ void CScheduler::update(size_t simElapsed)
|
||||
timeFunction.pop();
|
||||
jsval rval;
|
||||
m_abortInterval = false;
|
||||
|
||||
JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval );
|
||||
|
||||
if( top.isRecurrent && !m_abortInterval )
|
||||
pushInterval( top.delay, top.delay, top.function, top.operateOn );
|
||||
}
|
||||
@ -90,6 +92,8 @@ void CScheduler::update(size_t simElapsed)
|
||||
break;
|
||||
frameFunction.pop();
|
||||
jsval rval;
|
||||
|
||||
JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <timer.h>
|
||||
#include "Profile.h"
|
||||
|
||||
#include "Simulation.h"
|
||||
#include "TurnManager.h"
|
||||
@ -53,6 +54,7 @@ void CSimulation::Update(double frameTime)
|
||||
|
||||
if( m_DeltaTime >= 0.0 )
|
||||
{
|
||||
PROFILE( "simulation turn" );
|
||||
// A new simulation frame is required.
|
||||
MICROLOG( L"calculate simulation" );
|
||||
Simulate();
|
||||
@ -65,7 +67,9 @@ void CSimulation::Update(double frameTime)
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_START( "simulation interpolation" );
|
||||
Interpolate(frameTime, ((1000.0*m_DeltaTime) / (float)m_pTurnManager->GetTurnLength()) + 1.0);
|
||||
PROFILE_END( "simulation interpolation" );
|
||||
}
|
||||
|
||||
void CSimulation::Interpolate(double frameTime, double offset)
|
||||
@ -79,11 +83,18 @@ void CSimulation::Interpolate(double frameTime, double offset)
|
||||
|
||||
void CSimulation::Simulate()
|
||||
{
|
||||
PROFILE_START( "scheduler tick" );
|
||||
g_Scheduler.update(m_pTurnManager->GetTurnLength());
|
||||
g_EntityManager.updateAll( m_pTurnManager->GetTurnLength() );
|
||||
PROFILE_END( "scheduler tick" );
|
||||
|
||||
PROFILE_START( "entity updates" );
|
||||
g_EntityManager.updateAll( m_pTurnManager->GetTurnLength() );
|
||||
PROFILE_END( "entity updates" );
|
||||
|
||||
PROFILE_START( "turn manager update" );
|
||||
m_pTurnManager->NewTurn();
|
||||
m_pTurnManager->IterateBatch(0, TranslateMessage, this);
|
||||
PROFILE_END( "turn manager update" );
|
||||
}
|
||||
|
||||
uint CSimulation::TranslateMessage(CNetMessage *pMsg, uint clientMask, void *userdata)
|
||||
|
Loading…
Reference in New Issue
Block a user