mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
CWE Directory Reorganization
Rearrange directory structure of CWE to be loosely equivalent to the H'uru Plasma repository. Part 1: Movement of directories and files.
This commit is contained in:
399
Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp
Normal file
399
Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp
Normal file
@ -0,0 +1,399 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plAutoProfile.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "../plNetClient/plNetClientMgr.h"
|
||||
#include "../plNetClient/plNetLinkingMgr.h"
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "hsTimer.h"
|
||||
#include "../plMessage/plAgeLoadedMsg.h"
|
||||
#include "../pnTimer/plTimerCallbackManager.h"
|
||||
#include "../plMessage/plTimerCallbackMsg.h"
|
||||
#include "../plAvatar/plAvatarMgr.h"
|
||||
#include "../plAvatar/plArmatureMod.h"
|
||||
#include "../plModifier/plSpawnModifier.h"
|
||||
#include "../plMessage/plConsoleMsg.h"
|
||||
#include "../pnMessage/plClientMsg.h"
|
||||
#include "../plAgeLoader/plAgeLoader.h"
|
||||
#include "plProfileManagerFull.h"
|
||||
#include "../plFile/plFileUtils.h"
|
||||
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
#include "../plVault/plVault.h"
|
||||
|
||||
#include "../plContainer/plConfigInfo.h" // for plStringList
|
||||
|
||||
// For taking screenshots
|
||||
#include "../plGImage/plMipmap.h"
|
||||
#include "../Apps/plClient/plClient.h"
|
||||
#include "../plJPEG/plJPEG.h"
|
||||
#include "plPipeline.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
class plAutoProfileImp : public plAutoProfile
|
||||
{
|
||||
protected:
|
||||
plStringList fAges;
|
||||
int fNextAge;
|
||||
int fNextSpawnPoint;
|
||||
const char* fLastSpawnPointName;
|
||||
// For profiling a single age
|
||||
std::string fAgeName;
|
||||
bool fLinkedToSingleAge;
|
||||
bool fJustLinkToAges;
|
||||
|
||||
UInt64 fLinkTime;
|
||||
|
||||
std::string fStatusMessage;
|
||||
|
||||
void INextProfile();
|
||||
bool INextAge();
|
||||
bool INextSpawnPoint();
|
||||
|
||||
void IInit();
|
||||
void IShutdown();
|
||||
|
||||
public:
|
||||
plAutoProfileImp();
|
||||
|
||||
virtual void StartProfile(const char* ageName);
|
||||
virtual void LinkToAllAges();
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
};
|
||||
|
||||
plAutoProfile* plAutoProfile::Instance()
|
||||
{
|
||||
static plAutoProfileImp theInstance;
|
||||
return &theInstance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plAutoProfileImp::plAutoProfileImp() : fNextAge(0), fNextSpawnPoint(0), fLastSpawnPointName(nil), fLinkedToSingleAge(false), fJustLinkToAges(false)
|
||||
{
|
||||
}
|
||||
|
||||
void plAutoProfileImp::StartProfile(const char* ageName)
|
||||
{
|
||||
if (ageName)
|
||||
fAgeName = ageName;
|
||||
else
|
||||
fAgeName = "";
|
||||
|
||||
IInit();
|
||||
|
||||
plProfileManagerFull::Instance().ActivateAllStats();
|
||||
}
|
||||
|
||||
void plAutoProfileImp::LinkToAllAges()
|
||||
{
|
||||
fJustLinkToAges = true;
|
||||
IInit();
|
||||
}
|
||||
|
||||
void plAutoProfileImp::IInit()
|
||||
{
|
||||
// TODO: Find a better way to grab a list of age names, since the old data server
|
||||
// no longer exists
|
||||
/*plIDataServer* dataServer = plNetClientMgr::GetInstance()->GetDataServer();
|
||||
if (!dataServer)
|
||||
return;
|
||||
|
||||
dataServer->GetDatasetAges(fAges);*/
|
||||
|
||||
// The first age we link into is AvatarCustomization, since we have a new avatar.
|
||||
// Coincidentally, the first age in our list is AvatarCustomization. However,
|
||||
// sometimes linking from ACA to ACA causes a crash. To get around that, we just
|
||||
// reverse the list, so it's last.
|
||||
std::reverse(fAges.begin(), fAges.end());
|
||||
|
||||
fNextAge = 0;
|
||||
|
||||
RegisterAs(kAutoProfile_KEY);
|
||||
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plAgeBeginLoadingMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
|
||||
plConsoleMsg* consoleMsg = TRACKED_NEW plConsoleMsg(plConsoleMsg::kExecuteLine, "Camera.AlwaysCut true");
|
||||
consoleMsg->Send();
|
||||
}
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
#include "hsWindows.h"
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
void plAutoProfileImp::IShutdown()
|
||||
{
|
||||
// KLUDGE - Copy the load timing log, in case we used it
|
||||
#define kTimingLog L"readtimings.0.log"
|
||||
#define kAgeTimingLog L"agetimings.0.log"
|
||||
wchar destPath[MAX_PATH];
|
||||
wchar sourcePath[MAX_PATH];
|
||||
|
||||
PathAddFilename(destPath, plProfileManagerFull::Instance().GetProfilePath(), kTimingLog, arrsize(destPath));
|
||||
PathGetLogDirectory(sourcePath, arrsize(sourcePath));
|
||||
PathAddFilename(sourcePath, sourcePath, kTimingLog, arrsize(sourcePath));
|
||||
plFileUtils::FileCopy(sourcePath, destPath);
|
||||
|
||||
PathAddFilename(destPath, plProfileManagerFull::Instance().GetProfilePath(), kAgeTimingLog, arrsize(destPath));
|
||||
PathGetLogDirectory(sourcePath, arrsize(sourcePath));
|
||||
PathAddFilename(sourcePath, sourcePath, kAgeTimingLog, arrsize(sourcePath));
|
||||
plFileUtils::FileCopy(sourcePath, destPath);
|
||||
|
||||
#ifdef HS_BUILD_FOR_WIN32
|
||||
ShellExecute(nil, nil, "PostRun.bat", nil, nil, SW_SHOWNORMAL);
|
||||
#endif
|
||||
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
|
||||
|
||||
UnRegisterAs(kAutoProfile_KEY);
|
||||
// Pump the queue so we get fully unregistered
|
||||
plgDispatch::Dispatch()->MsgQueueProcess();
|
||||
|
||||
plClientMsg* clientMsg = TRACKED_NEW plClientMsg(plClientMsg::kQuit);
|
||||
clientMsg->Send(hsgResMgr::ResMgr()->FindKey(kClient_KEY));
|
||||
}
|
||||
|
||||
void plAutoProfileImp::INextProfile()
|
||||
{
|
||||
// Haven't linked to our first age yet, do that before we start profiling
|
||||
if (fNextAge == 0)
|
||||
{
|
||||
if (!INextAge())
|
||||
IShutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log the stats for this spawn point
|
||||
if (fLastSpawnPointName)
|
||||
{
|
||||
const char * ageName = NetCommGetAge()->ageDatasetName;
|
||||
plProfileManagerFull::Instance().LogStats(ageName, fLastSpawnPointName);
|
||||
|
||||
plMipmap mipmap;
|
||||
if (plClient::GetInstance()->GetPipeline()->CaptureScreen(&mipmap))
|
||||
{
|
||||
char fileName[256];
|
||||
sprintf(fileName, "%s%s_%s.jpg",
|
||||
plProfileManagerFull::Instance().GetProfilePath(),
|
||||
ageName, fLastSpawnPointName);
|
||||
|
||||
plJPEG::Instance().SetWriteQuality(100);
|
||||
plJPEG::Instance().WriteToFile(fileName, &mipmap);
|
||||
}
|
||||
|
||||
fLastSpawnPointName = nil;
|
||||
}
|
||||
|
||||
// Try to go to the next spawn point
|
||||
if (!INextSpawnPoint())
|
||||
{
|
||||
// Link to the next age
|
||||
if (!INextAge())
|
||||
{
|
||||
// We've done all the ages, shut down
|
||||
IShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool plAutoProfileImp::INextAge()
|
||||
{
|
||||
const char* ageName = nil;
|
||||
|
||||
if (fAgeName.length() > 0)
|
||||
{
|
||||
if (fLinkedToSingleAge)
|
||||
return false;
|
||||
|
||||
fLinkedToSingleAge = true;
|
||||
ageName = fAgeName.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fNextAge >= fAges.size())
|
||||
return false;
|
||||
|
||||
ageName = fAges[fNextAge].c_str();
|
||||
}
|
||||
|
||||
fNextAge++;
|
||||
fNextSpawnPoint = 0;
|
||||
|
||||
plAgeLinkStruct link;
|
||||
link.GetAgeInfo()->SetAgeFilename(ageName);
|
||||
link.SetLinkingRules(plNetCommon::LinkingRules::kBasicLink);
|
||||
plNetLinkingMgr::GetInstance()->LinkToAge(&link);
|
||||
|
||||
fStatusMessage = "Linking to age ";
|
||||
fStatusMessage += ageName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plAutoProfileImp::INextSpawnPoint()
|
||||
{
|
||||
if (fJustLinkToAges)
|
||||
return false;
|
||||
|
||||
const char* kPerfSpawnPrefix = "cPerf-";
|
||||
int kPerfSpawnLen = strlen(kPerfSpawnPrefix);
|
||||
|
||||
// Find the next perf spawn point
|
||||
bool foundGood = false;
|
||||
while (fNextSpawnPoint < plAvatarMgr::GetInstance()->NumSpawnPoints())
|
||||
{
|
||||
const plSpawnModifier* spawnMod = plAvatarMgr::GetInstance()->GetSpawnPoint(fNextSpawnPoint);
|
||||
fLastSpawnPointName = spawnMod->GetKeyName();
|
||||
|
||||
if (strncmp(fLastSpawnPointName, kPerfSpawnPrefix, kPerfSpawnLen) == 0)
|
||||
{
|
||||
fStatusMessage = "Profiling spawn point ";
|
||||
fStatusMessage += fLastSpawnPointName;
|
||||
|
||||
foundGood = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
fNextSpawnPoint++;
|
||||
}
|
||||
|
||||
if (!foundGood)
|
||||
{
|
||||
fLastSpawnPointName = nil;
|
||||
fStatusMessage = "No profile spawn point found";
|
||||
return false;
|
||||
}
|
||||
|
||||
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
||||
if (avatar)
|
||||
{
|
||||
double fakeTime = 0.0f;
|
||||
avatar->SpawnAt(fNextSpawnPoint, fakeTime);
|
||||
}
|
||||
|
||||
fNextSpawnPoint++;
|
||||
|
||||
plTimerCallbackMsg* timerMsg = TRACKED_NEW plTimerCallbackMsg(GetKey());
|
||||
plgTimerCallbackMgr::NewTimer(30, timerMsg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plAutoProfileImp::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg);
|
||||
if (evalMsg)
|
||||
{
|
||||
if (fStatusMessage.length() > 0)
|
||||
plDebugText::Instance().DrawString(10, 10, fStatusMessage.c_str());
|
||||
}
|
||||
|
||||
plAgeLoadedMsg* ageLoaded = plAgeLoadedMsg::ConvertNoRef(msg);
|
||||
if (ageLoaded)
|
||||
{
|
||||
if (!ageLoaded->fLoaded)
|
||||
{
|
||||
fLinkTime = hsTimer::GetFullTickCount();
|
||||
hsStatusMessage("Age unloaded");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
plInitialAgeStateLoadedMsg* ageStateLoaded = plInitialAgeStateLoadedMsg::ConvertNoRef(msg);
|
||||
if (ageStateLoaded)
|
||||
{
|
||||
if (fNextAge > 0)
|
||||
{
|
||||
fLinkTime = hsTimer::GetFullTickCount() - fLinkTime;
|
||||
float ms = hsTimer::FullTicksToMs(fLinkTime);
|
||||
|
||||
hsStatusMessageF("Age %s finished load, took %.1f ms",
|
||||
fAges[fNextAge-1].c_str(),
|
||||
ms);
|
||||
|
||||
plStatusLog::AddLineS("agetimings.log", "Age %s took %.1f ms",
|
||||
fAges[fNextAge-1].c_str(),
|
||||
ms);
|
||||
}
|
||||
|
||||
fStatusMessage = "Age loaded. Preparing to profile.";
|
||||
|
||||
// Age is loaded, start profiling in 5 seconds (to make sure the avatar is linked in all the way)
|
||||
plTimerCallbackMsg* timerMsg = TRACKED_NEW plTimerCallbackMsg(GetKey());
|
||||
plgTimerCallbackMgr::NewTimer(5, timerMsg);
|
||||
return true;
|
||||
}
|
||||
|
||||
plTimerCallbackMsg* timerMsg = plTimerCallbackMsg::ConvertNoRef(msg);
|
||||
if (timerMsg)
|
||||
{
|
||||
INextProfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
// When the first age starts to load, register the stupid avatar customization variable
|
||||
// so the calibration screen won't pop up and ruin everything. I'm sure I could try
|
||||
// and do this earlier, but I'm not sure when that player folder is set so screw it, it works here.
|
||||
plAgeBeginLoadingMsg* ageBeginLoadingMsg = plAgeBeginLoadingMsg::ConvertNoRef(msg);
|
||||
if (ageBeginLoadingMsg)
|
||||
{
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plAgeBeginLoadingMsg::Index(), GetKey());
|
||||
VaultAddChronicleEntryAndWait(L"InitialAvCursomizationsDone", 0, L"1");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
62
Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.h
Normal file
62
Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef plAutoProfile_h_inc
|
||||
#define plAutoProfile_h_inc
|
||||
|
||||
#include "../pnKeyedObject/hsKeyedObject.h"
|
||||
|
||||
class plAutoProfile : public hsKeyedObject
|
||||
{
|
||||
public:
|
||||
CLASSNAME_REGISTER(plAutoProfile);
|
||||
GETINTERFACE_ANY(plAutoProfile, hsKeyedObject);
|
||||
|
||||
static plAutoProfile* Instance();
|
||||
|
||||
// If ageName is nil, do all ages
|
||||
virtual void StartProfile(const char* ageName = nil)=0;
|
||||
|
||||
// For when we just want to link to each age, for other reasons (profiling load times)
|
||||
virtual void LinkToAllAges()=0;
|
||||
};
|
||||
|
||||
#endif // plAutoProfile_h_inc
|
320
Sources/Plasma/PubUtilLib/plStatGather/plCalculatedProfiles.cpp
Normal file
320
Sources/Plasma/PubUtilLib/plStatGather/plCalculatedProfiles.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plProfile.h"
|
||||
#include "plProfileManager.h"
|
||||
#include "../plNetClient/plNetClientMgr.h"
|
||||
#include "hsTimer.h"
|
||||
|
||||
plProfile_CreateCounter("Age Upload BitsPerSec", "Network", UploadAgeBitsPerSec);
|
||||
plProfile_CreateMemCounter("Upload Bytes", "Network", UploadBW);
|
||||
plProfile_CreateMemCounter("Upload Avg Packet Size", "Network", UploadAPS);
|
||||
plProfile_CreateCounter("Upload Num Packets", "Network", UploadPPS);
|
||||
plProfile_CreateCounter("Upload Avg Packets Queued", "Network", UploadPQ);
|
||||
plProfile_CreateCounter("Recvd Multiple Acks", "Network", RMultAcksPQ);
|
||||
|
||||
plProfile_CreateCounter("Age Download BitsPerSec", "Network", DownloadAgeBitsPerSec);
|
||||
plProfile_CreateMemCounter("Download Bytes", "Network", DownloadBW);
|
||||
plProfile_CreateMemCounter("Download Avg Packet Size", "Network", DownloadAPS);
|
||||
plProfile_CreateCounter("Download Num Packets", "Network", DownloadPPS);
|
||||
plProfile_CreateCounter("Download Avg Packets Queued", "Network", DownloadPQ);
|
||||
plProfile_CreateCounter("Download Dropped Pkts", "Network", DownloadDP);
|
||||
|
||||
plProfile_CreateCounter("Remote Players", "Network", RemotePlayers);
|
||||
plProfile_CreateCounter("Peers", "Network", Peers);
|
||||
plProfile_CreateCounter("Player ID", "Network", PlayerID);
|
||||
plProfile_CreateCounter("Account ID", "Network", AccountID);
|
||||
|
||||
plProfile_CreateTimer("Avg Receipt Time", "Network", AvgReceiptTime);
|
||||
plProfile_CreateTimer("Peak Receipt Time", "Network", PeakReceiptTime);
|
||||
|
||||
#ifdef HS_FIND_MEM_LEAKS
|
||||
plProfile_CreateMemCounter("Allocated", "Memory", MemAllocated);
|
||||
plProfile_CreateMemCounter("Peak Alloc", "Memory", MemPeakAlloc);
|
||||
#endif
|
||||
|
||||
static plProfileVar gVarRFPS("RFPS", "General", plProfileVar::kDisplayTime | plProfileVar::kDisplayFPS);
|
||||
|
||||
plProfile_Extern(DrawTriangles);
|
||||
plProfile_Extern(MatChange);
|
||||
plProfile_CreateCounter("Polys Per Material", "General", PolysPerMat);
|
||||
|
||||
#ifdef PL_PROFILE_ENABLED
|
||||
#define plProfile_GetValue(varName) gProfileVar##varName.GetValue()
|
||||
#else
|
||||
#define plProfile_GetValue(varName) 0
|
||||
#endif
|
||||
|
||||
void CalculateProfiles()
|
||||
{
|
||||
// KLUDGE - do timing that overlaps the beginframe / endframe (where timing is normally reset)
|
||||
static UInt32 lastTicks = plProfileManager::GetTime();
|
||||
UInt32 curTicks = plProfileManager::GetTime();
|
||||
gVarRFPS.Set(curTicks - lastTicks);
|
||||
lastTicks = curTicks;
|
||||
|
||||
// KLUDGE - calulate the polys per material
|
||||
if (plProfile_GetValue(MatChange) == 0)
|
||||
plProfile_Set(PolysPerMat, 0);
|
||||
else
|
||||
plProfile_Set(PolysPerMat, plProfile_GetValue(DrawTriangles) / plProfile_GetValue(MatChange));
|
||||
|
||||
#ifdef HS_FIND_MEM_LEAKS
|
||||
// plProfile_Set(MemAllocated, MemGetAllocated());
|
||||
// plProfile_Set(MemPeakAlloc, MemGetPeakAllocated());
|
||||
#endif
|
||||
|
||||
// Network stats
|
||||
plNetClientMgr* nc = plNetClientMgr::GetInstance();
|
||||
if (!nc->GetFlagsBit(plNetClientMgr::kDisabled))
|
||||
{
|
||||
#if 0
|
||||
hsAssert(nc->GetNetCore(), "nil net core in stats?");
|
||||
plNetCoreStats* ns = nc->GetNetCore()->GetStats();
|
||||
|
||||
plProfile_Set(UploadAgeBitsPerSec, (UInt32)nc->GetNetClientStats().GetAgeStatsULBitsPerSec());
|
||||
plProfile_Set(UploadBW, ns->GetULBits()/8);
|
||||
plProfile_Set(UploadPPS, ns->GetULPackets());
|
||||
plProfile_Set(UploadAPS, (UInt32)ns->GetULAvgPacketBytes());
|
||||
plProfile_Set(UploadPQ, (UInt32)ns->GetULAvgNumPacketsQueued());
|
||||
plProfile_Set(RMultAcksPQ, nc->GetNetClientStats().GetRecvdMultipleAcks());
|
||||
|
||||
plProfile_Set(DownloadAgeBitsPerSec, (UInt32)nc->GetNetClientStats().GetAgeStatsDLBitsPerSec());
|
||||
plProfile_Set(DownloadBW, ns->GetDLBits()/8);
|
||||
plProfile_Set(DownloadPPS, ns->GetDLPackets());
|
||||
plProfile_Set(DownloadAPS, (UInt32)ns->GetDLAvgPacketBytes());
|
||||
plProfile_Set(DownloadPQ, (UInt32)ns->GetDLAvgNumPacketsQueued());
|
||||
plProfile_Set(DownloadDP, ns->GetDLDroppedPackets());
|
||||
|
||||
plProfile_Set(RemotePlayers, nc->RemotePlayerKeys().size());
|
||||
plProfile_Set(Peers, ns->GetNumPeers());
|
||||
plProfile_Set(PlayerID, nc->GetPlayerID());
|
||||
plProfile_Set(AccountID, nc->GetAccountID());
|
||||
|
||||
plProfile_Set(AvgReceiptTime, hsTimer::PrecSecsToTicks(ns->GetAvgReceiptTime()));
|
||||
plProfile_Set(PeakReceiptTime, hsTimer::PrecSecsToTicks(ns->GetPeakReceiptTime()));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#include "../plPipeline/plPlates.h"
|
||||
|
||||
static plGraphPlate* fFPSPlate = nil;
|
||||
static plGraphPlate* fNetBWPlate = nil;
|
||||
static plGraphPlate* fNetPPSPlate = nil;
|
||||
static plGraphPlate* fNetQueuesPlate = nil;
|
||||
static plGraphPlate* fNetAvgBWPlate = nil;
|
||||
static plGraphPlate* fNetAvgPPSPlate = nil;
|
||||
static plGraphPlate* fNetAvgQueuesPlate = nil;
|
||||
|
||||
static int ICreateStdPlate(plGraphPlate** graph)
|
||||
{
|
||||
if (plPlateManager::InstanceValid())
|
||||
{
|
||||
plPlateManager::Instance().CreateGraphPlate(graph);
|
||||
(*graph)->SetSize(0.25, 0.25);
|
||||
(*graph)->SetDataRange(0, 100, 100);
|
||||
return hsOK;
|
||||
}
|
||||
return hsFail;
|
||||
}
|
||||
|
||||
void CreateStandardGraphs(const char* groupName, bool create)
|
||||
{
|
||||
if (strcmp(groupName, "General") == 0)
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
if (ICreateStdPlate(&fFPSPlate) == hsOK)
|
||||
{
|
||||
fFPSPlate->SetTitle("mSecs");
|
||||
fFPSPlate->SetLabelText("Tot", "Draw", "Upd");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plPlateManager::Instance().DestroyPlate(fFPSPlate);
|
||||
fFPSPlate = nil;
|
||||
}
|
||||
}
|
||||
else if (strcmp(groupName, "Network") == 0)
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
if (ICreateStdPlate(&fNetBWPlate) == hsOK)
|
||||
{
|
||||
fNetBWPlate->SetDataLabels(0, 2000);
|
||||
fNetBWPlate->SetTitle("Bytes");
|
||||
fNetBWPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetPPSPlate);
|
||||
fNetPPSPlate->SetDataLabels(0, 20);
|
||||
fNetPPSPlate->SetTitle("Packets");
|
||||
fNetPPSPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetQueuesPlate);
|
||||
fNetQueuesPlate->SetDataLabels(0, 20);
|
||||
fNetQueuesPlate->SetTitle("Queue Counts");
|
||||
fNetQueuesPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetQueuesPlate);
|
||||
fNetQueuesPlate->SetDataLabels(0, 20);
|
||||
fNetQueuesPlate->SetTitle("Queue Counts");
|
||||
fNetQueuesPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetQueuesPlate);
|
||||
fNetQueuesPlate->SetDataLabels(0, 20);
|
||||
fNetQueuesPlate->SetTitle("Queue Counts");
|
||||
fNetQueuesPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetAvgBWPlate);
|
||||
fNetAvgBWPlate->SetDataLabels(0, 5000);
|
||||
fNetAvgBWPlate->SetTitle("Avg BytesPS");
|
||||
fNetAvgBWPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetAvgPPSPlate);
|
||||
fNetAvgPPSPlate->SetDataLabels(0, 40);
|
||||
fNetAvgPPSPlate->SetTitle("Avg PacketsPS");
|
||||
fNetAvgPPSPlate->SetLabelText("UL", "DL");
|
||||
|
||||
ICreateStdPlate(&fNetAvgQueuesPlate);
|
||||
fNetAvgQueuesPlate->SetDataLabels(0, 40);
|
||||
fNetAvgQueuesPlate->SetTitle("Avg Queue CountsPS");
|
||||
fNetAvgQueuesPlate->SetLabelText("UL", "DL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plPlateManager::Instance().DestroyPlate(fNetBWPlate);
|
||||
plPlateManager::Instance().DestroyPlate(fNetPPSPlate);
|
||||
plPlateManager::Instance().DestroyPlate(fNetQueuesPlate);
|
||||
plPlateManager::Instance().DestroyPlate(fNetAvgBWPlate);
|
||||
plPlateManager::Instance().DestroyPlate(fNetAvgPPSPlate);
|
||||
plPlateManager::Instance().DestroyPlate(fNetAvgQueuesPlate);
|
||||
fNetBWPlate = nil;
|
||||
fNetPPSPlate = nil;
|
||||
fNetQueuesPlate = nil;
|
||||
fNetAvgBWPlate = nil;
|
||||
fNetAvgPPSPlate = nil;
|
||||
fNetAvgQueuesPlate = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plProfile_CreateTimer("Draw", "General", DrawTime);
|
||||
plProfile_CreateTimer("Update", "General", UpdateTime);
|
||||
|
||||
void UpdateStandardGraphs(float xPos, float yPos)
|
||||
{
|
||||
#define PositionPlate(plate) \
|
||||
plate->SetPosition(xPos, yPos); \
|
||||
yPos += 0.25; \
|
||||
plate->SetVisible(true);
|
||||
|
||||
if (fFPSPlate)
|
||||
{
|
||||
fFPSPlate->AddData(
|
||||
gVarRFPS.GetValue(),
|
||||
plProfile_GetValue(DrawTime),
|
||||
plProfile_GetValue(UpdateTime));
|
||||
PositionPlate(fFPSPlate);
|
||||
}
|
||||
|
||||
plNetClientMgr* nc = plNetClientMgr::GetInstance();
|
||||
|
||||
|
||||
#if 0
|
||||
plNetCoreStats* ns = nc ? nc->GetNetCore()->GetStats() : nil;
|
||||
|
||||
if (!nc || !ns)
|
||||
return;
|
||||
|
||||
if (fNetBWPlate)
|
||||
{
|
||||
fNetBWPlate->AddData(
|
||||
(UInt32)(ns->GetULBits()/8.f),
|
||||
(UInt32)(ns->GetDLBits()/8.f));
|
||||
PositionPlate(fNetBWPlate);
|
||||
}
|
||||
|
||||
if (fNetPPSPlate)
|
||||
{
|
||||
fNetPPSPlate->AddData(
|
||||
ns->GetULPackets(),
|
||||
ns->GetDLPackets());
|
||||
PositionPlate(fNetPPSPlate);
|
||||
}
|
||||
|
||||
if (fNetQueuesPlate)
|
||||
{
|
||||
unsigned int ul, dl;
|
||||
nc->GetNetCore()->GetOutQueueMsgCount(plNetCore::kPeerAll,ul);
|
||||
nc->GetNetCore()->GetInQueueMsgCount(plNetCore::kPeerAll,dl);
|
||||
fNetQueuesPlate->AddData(ul,dl);
|
||||
PositionPlate(fNetQueuesPlate);
|
||||
}
|
||||
|
||||
if (fNetAvgBWPlate)
|
||||
{
|
||||
fNetAvgBWPlate->AddData(
|
||||
(UInt32)(ns->GetULBitsPS()/8.f),
|
||||
(UInt32)(ns->GetDLBitsPS()/8.f));
|
||||
PositionPlate(fNetAvgBWPlate);
|
||||
}
|
||||
|
||||
if (fNetAvgPPSPlate)
|
||||
{
|
||||
fNetAvgPPSPlate->AddData(
|
||||
(Int32)ns->GetULNumPacketsPS(),
|
||||
(Int32)ns->GetDLNumPacketsPS());
|
||||
PositionPlate(fNetAvgPPSPlate);
|
||||
}
|
||||
|
||||
if (fNetAvgQueuesPlate)
|
||||
{
|
||||
fNetAvgQueuesPlate->AddData(
|
||||
(Int32)ns->GetULAvgNumPacketsQueued(),
|
||||
(Int32)ns->GetDLAvgNumPacketsQueued());
|
||||
PositionPlate(fNetAvgQueuesPlate);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
void CalculateProfiles();
|
||||
void CreateStandardGraphs(const char* groupName, bool create);
|
||||
void UpdateStandardGraphs(float xPos, float yPos);
|
692
Sources/Plasma/PubUtilLib/plStatGather/plProfileManagerFull.cpp
Normal file
692
Sources/Plasma/PubUtilLib/plStatGather/plProfileManagerFull.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plProfileManagerFull.h"
|
||||
#include "plProfileManager.h"
|
||||
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
#include "../plPipeline/plPlates.h"
|
||||
|
||||
#include "plCalculatedProfiles.h"
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "../pnUtils/pnUtils.h"
|
||||
#include "../plUnifiedTime/plUnifiedTime.h"
|
||||
#include "../plFile/plFileUtils.h"
|
||||
|
||||
plProfileManagerFull::plProfileManagerFull() :
|
||||
fVars(plProfileManager::Instance().fVars),
|
||||
fLogStats(false),
|
||||
fShowLaps(nil),
|
||||
fMinLap(0),
|
||||
fDetailGraph(nil)
|
||||
{
|
||||
}
|
||||
|
||||
plProfileManagerFull& plProfileManagerFull::Instance()
|
||||
{
|
||||
static plProfileManagerFull theInstance;
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
void plProfileManagerFull::GetGroups(GroupSet& groups)
|
||||
{
|
||||
groups.clear();
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
groups.insert(fVars[i]->GetGroup());
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ShowGroup(const char* groupName)
|
||||
{
|
||||
if (!groupName)
|
||||
groupName = "General";
|
||||
|
||||
// If we're already showing this group, stop
|
||||
if (fShowGroups.find(groupName) != fShowGroups.end())
|
||||
{
|
||||
CreateStandardGraphs(groupName, false);
|
||||
fShowGroups.erase(groupName);
|
||||
ISetActive(groupName, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* shareGroupName = nil;
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
if (stricmp(fVars[i]->GetGroup(), groupName) == 0)
|
||||
{
|
||||
shareGroupName = fVars[i]->GetGroup();
|
||||
}
|
||||
}
|
||||
|
||||
// We do have a group with this name, so insert one of the variable's
|
||||
// pointers to the name into our list (we can hang on to those pointers)
|
||||
if (shareGroupName)
|
||||
{
|
||||
ISetActive(shareGroupName, true);
|
||||
CreateStandardGraphs(shareGroupName, true);
|
||||
fShowGroups.insert(shareGroupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ShowNextGroup()
|
||||
{
|
||||
const char* curGroup = nil;
|
||||
if (fShowGroups.begin() != fShowGroups.end())
|
||||
curGroup = *(fShowGroups.begin());
|
||||
|
||||
GroupSet groups;
|
||||
GetGroups(groups);
|
||||
|
||||
const char* nextGroup = nil;
|
||||
if (curGroup)
|
||||
{
|
||||
CreateStandardGraphs(curGroup, false);
|
||||
|
||||
GroupSet::iterator it = groups.find(curGroup);
|
||||
it++;
|
||||
if (it != groups.end())
|
||||
{
|
||||
nextGroup = *it;
|
||||
}
|
||||
ISetActive(curGroup,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextGroup = *(groups.begin());
|
||||
}
|
||||
|
||||
fShowGroups.clear();
|
||||
if (nextGroup)
|
||||
{
|
||||
ISetActive(nextGroup, true);
|
||||
CreateStandardGraphs(nextGroup, true);
|
||||
fShowGroups.insert(nextGroup);
|
||||
}
|
||||
}
|
||||
|
||||
plProfileVar* plProfileManagerFull::IFindTimer(const char *name)
|
||||
{
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
if (stricmp(fVars[i]->GetName(), name) == 0)
|
||||
return fVars[i];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plProfileManagerFull::GetLaps(LapNames& lapNames)
|
||||
{
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
plProfileVar* var = fVars[i];
|
||||
if (var->GetLaps())
|
||||
{
|
||||
LapPair lapPair;
|
||||
lapPair.group = var->GetGroup();
|
||||
lapPair.varName = var->GetName();
|
||||
lapNames.push_back(lapPair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
kColName,
|
||||
kColValue,
|
||||
kColAvg,
|
||||
kColMax,
|
||||
kColIndex,
|
||||
};
|
||||
|
||||
typedef std::vector<plProfileBase*> ProfileGroup;
|
||||
|
||||
static void PrintColumn(ProfileGroup& group, const char* groupName, int column, int x, int y, int& width, int& height, int off =0)
|
||||
{
|
||||
plDebugText& txt = plDebugText::Instance();
|
||||
int yInc = txt.GetFontHeight() + 2;
|
||||
|
||||
height = 0;
|
||||
width = 0;
|
||||
|
||||
width = hsMaximum(width, txt.CalcStringWidth(groupName) + 1);
|
||||
txt.DrawString(x, y+height, groupName, 255, 255, 255, 255, plDebugText::kStyleBold);
|
||||
height += yInc;
|
||||
|
||||
UInt32 samplesWidth = txt.CalcStringWidth("[000]");
|
||||
|
||||
for (int i = 0; i < group.size(); i++)
|
||||
{
|
||||
char str[1024];
|
||||
|
||||
switch (column)
|
||||
{
|
||||
case kColName:
|
||||
strcpy(str, group[i]->GetName());
|
||||
|
||||
// Since we don't draw the samples text for stats that only have 1 sample,
|
||||
// if the stat with the longest name is fluctuating between 1 and more than
|
||||
// 1 sample the width of the column will jump around. So we calculate the
|
||||
// width based on the stat name plus the width of the widest sample we should
|
||||
// get
|
||||
width = hsMaximum(width, txt.CalcStringWidth(str) + samplesWidth + 1);
|
||||
|
||||
// Now add on the samples text, if we have any
|
||||
if (group[i]->GetTimerSamples())
|
||||
{
|
||||
char cnt[20];
|
||||
sprintf(cnt, "[%d]", group[i]->GetTimerSamples());
|
||||
strcat(str, cnt);
|
||||
}
|
||||
break;
|
||||
case kColValue:
|
||||
group[i]->PrintValue(str);
|
||||
break;
|
||||
case kColAvg:
|
||||
group[i]->PrintAvg(str);
|
||||
break;
|
||||
case kColMax:
|
||||
group[i]->PrintMax(str);
|
||||
break;
|
||||
case kColIndex:
|
||||
sprintf(str,"[%3d]",i+off);
|
||||
break;
|
||||
}
|
||||
|
||||
txt.DrawString(x, y+height, str);
|
||||
if (column != kColName)
|
||||
width = hsMaximum(width, txt.CalcStringWidth(str) + 1);
|
||||
height += yInc;
|
||||
}
|
||||
|
||||
// So the columns don't jump around as much as values change, pad them out to a certain width
|
||||
width = hsMaximum(width, txt.CalcStringWidth("000.0 ms") + 1);
|
||||
}
|
||||
|
||||
static void PrintGroup(ProfileGroup& group, const char* groupName, int& x, int& y)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
PrintColumn(group, groupName, kColName, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
PrintColumn(group, "Avg", kColAvg, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
PrintColumn(group, "Cur", kColValue, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
PrintColumn(group, "Max", kColMax, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
y += height;
|
||||
}
|
||||
|
||||
|
||||
static void PrintLapGroup(ProfileGroup& group, const char* groupName, int& x, int& y, int min)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
if(min > 0)
|
||||
{
|
||||
PrintColumn(group, "Index", kColIndex, x, y, width, height, min);
|
||||
x += width + 10;
|
||||
}
|
||||
|
||||
PrintColumn(group, "Avg", kColAvg, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
PrintColumn(group, groupName, kColName, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
PrintColumn(group, "Cur", kColValue, x, y, width, height);
|
||||
x += width + 10;
|
||||
|
||||
y += height;
|
||||
}
|
||||
|
||||
void plProfileManagerFull::EndFrame()
|
||||
{
|
||||
CalculateProfiles();
|
||||
}
|
||||
|
||||
void plProfileManagerFull::Update()
|
||||
{
|
||||
if (fLogStats)
|
||||
ILogStats();
|
||||
|
||||
//
|
||||
// Print the groups we're showing
|
||||
//
|
||||
int maxX = 0;
|
||||
|
||||
int y = 10;
|
||||
GroupSet::iterator it;
|
||||
for (it = fShowGroups.begin(); it != fShowGroups.end(); it++)
|
||||
{
|
||||
const char* groupName = *it;
|
||||
|
||||
std::vector<plProfileBase*> group;
|
||||
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
if (hsStrEQ(fVars[i]->GetGroup(), groupName))
|
||||
group.push_back(fVars[i]);
|
||||
|
||||
int x = 10;
|
||||
PrintGroup(group, groupName, x, y);
|
||||
|
||||
maxX = hsMaximum(maxX, x);
|
||||
y += 10;
|
||||
}
|
||||
|
||||
//
|
||||
// Print the laps we're showing
|
||||
//
|
||||
if (fShowLaps && fShowLaps->GetLaps())
|
||||
{
|
||||
plProfileLaps* laps = fShowLaps->GetLaps();
|
||||
|
||||
std::vector<plProfileBase*> group;
|
||||
int numLaps = laps->GetNumLaps();
|
||||
|
||||
if(numLaps < fMinLap)
|
||||
fMinLap = 0;
|
||||
for (int i = 0; i < numLaps; i++)
|
||||
{
|
||||
if(i >= fMinLap && i < (fMinLap + 40))
|
||||
group.push_back(laps->GetLap(i));
|
||||
}
|
||||
y = 10;
|
||||
char buf[256];
|
||||
sprintf(buf, "%s - %s", fShowLaps->GetGroup(), fShowLaps->GetName());
|
||||
PrintLapGroup(group, buf, maxX, y, fMinLap);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the graphs
|
||||
//
|
||||
float size = 0.25;
|
||||
float xPos = 1 - size / 2;
|
||||
float yPos = -1 + size / 2;
|
||||
|
||||
for (int i = 0; i < fGraphs.size(); i++)
|
||||
{
|
||||
plGraphPlate* graph = fGraphs[i];
|
||||
plProfileVar* var = IFindTimer(graph->GetTitle());
|
||||
|
||||
if (var)
|
||||
{
|
||||
graph->SetPosition(xPos, yPos);
|
||||
graph->AddData(var->GetValue());
|
||||
graph->SetVisible(true);
|
||||
|
||||
yPos += size;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateStandardGraphs(xPos, yPos);
|
||||
|
||||
float detailSize = 0.9;
|
||||
float detailX = 1 - detailSize / 2;
|
||||
float detailY = 1 - detailSize / 2;
|
||||
if (fDetailGraph)
|
||||
{
|
||||
fDetailGraph->SetPosition(detailX,detailY);
|
||||
double value;
|
||||
double scale;
|
||||
int i;
|
||||
std::vector<Int32> values;
|
||||
for (i=0; i<fDetailVars.size(); i++)
|
||||
{
|
||||
value = (double)fDetailVars[i].var->GetValue();
|
||||
scale = 100.0/((double)(fDetailVars[i].max-fDetailVars[i].min));
|
||||
value = scale*value-fDetailVars[i].min;
|
||||
values.push_back((Int32)value);
|
||||
}
|
||||
fDetailGraph->AddData(values);
|
||||
fDetailGraph->SetVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ActivateAllStats()
|
||||
{
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
fVars[i]->SetActive(true);
|
||||
fVars[i]->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::IPrintGroup(hsStream* s, const char* groupName, bool printTitle)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
plProfileVar* var = fVars[i];
|
||||
if (hsStrEQ(var->GetGroup(), groupName))
|
||||
{
|
||||
if (printTitle)
|
||||
sprintf(buf, "%s:%s", var->GetGroup(), var->GetName());
|
||||
else
|
||||
var->PrintAvg(buf, false);
|
||||
|
||||
s->Write(strlen(buf), buf);
|
||||
s->WriteByte(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::LogStats(const char* ageName, const char* spawnName)
|
||||
{
|
||||
fLogStats = true;
|
||||
wchar* temp = hsStringToWString(ageName);
|
||||
fLogAgeName = temp;
|
||||
delete [] temp;
|
||||
fLogSpawnName = spawnName;
|
||||
}
|
||||
|
||||
const wchar* plProfileManagerFull::GetProfilePath()
|
||||
{
|
||||
static wchar profilePath[MAX_PATH];
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
|
||||
plUnifiedTime curTime = plUnifiedTime::GetCurrentTime(plUnifiedTime::kLocal);
|
||||
|
||||
PathGetUserDirectory(profilePath, arrsize(profilePath));
|
||||
PathAddFilename(profilePath, profilePath, L"Profile", arrsize(profilePath));
|
||||
plFileUtils::CreateDir(profilePath);
|
||||
|
||||
wchar buff[256];
|
||||
swprintf(buff, L"%02d-%02d-%04d_%02d-%02d//",
|
||||
curTime.GetMonth(),
|
||||
curTime.GetDay(),
|
||||
curTime.GetYear(),
|
||||
curTime.GetHour(),
|
||||
curTime.GetMinute());
|
||||
|
||||
PathAddFilename(profilePath, profilePath, buff, arrsize(profilePath));
|
||||
plFileUtils::CreateDir(profilePath);
|
||||
}
|
||||
|
||||
return profilePath;
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ILogStats()
|
||||
{
|
||||
wchar statFilename[256];
|
||||
swprintf(statFilename, L"%s%s.csv", GetProfilePath(), fLogAgeName.c_str());
|
||||
|
||||
bool exists = plFileUtils::FileExists(statFilename);
|
||||
|
||||
hsUNIXStream s;
|
||||
if (s.Open(statFilename, L"ab"))
|
||||
{
|
||||
GroupSet groups;
|
||||
GetGroups(groups);
|
||||
|
||||
GroupSet::iterator it;
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
const char* kSpawn = "Spawn";
|
||||
s.Write(strlen(kSpawn), kSpawn);
|
||||
s.WriteByte(',');
|
||||
|
||||
for (it = groups.begin(); it != groups.end(); it++)
|
||||
{
|
||||
const char* groupName = *it;
|
||||
IPrintGroup(&s, groupName, true);
|
||||
}
|
||||
s.WriteByte('\r');
|
||||
s.WriteByte('\n');
|
||||
}
|
||||
|
||||
s.Write(fLogSpawnName.length(), fLogSpawnName.c_str());
|
||||
s.WriteByte(',');
|
||||
|
||||
for (it = groups.begin(); it != groups.end(); it++)
|
||||
{
|
||||
const char* groupName = *it;
|
||||
IPrintGroup(&s, groupName);
|
||||
}
|
||||
s.WriteByte('\r');
|
||||
s.WriteByte('\n');
|
||||
|
||||
s.Close();
|
||||
}
|
||||
|
||||
fLogStats = false;
|
||||
fLogAgeName = L"";
|
||||
fLogSpawnName = "";
|
||||
}
|
||||
|
||||
|
||||
void plProfileManagerFull::ShowLaps(const char* groupName, const char* varName)
|
||||
{
|
||||
plProfileVar* var = nil;
|
||||
|
||||
|
||||
if(fShowLaps)
|
||||
fShowLaps->SetLapsActive(false);
|
||||
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
int j = 0;
|
||||
while(fVars[i]->GetName()[j++] == ' ') {}
|
||||
if (stricmp(&(fVars[i]->GetName()[j-1]), varName) == 0 &&
|
||||
stricmp(fVars[i]->GetGroup(), groupName) == 0)
|
||||
{
|
||||
var = fVars[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (var)
|
||||
{
|
||||
if (var == fShowLaps)
|
||||
{
|
||||
|
||||
fShowLaps = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
fShowLaps = var;
|
||||
}
|
||||
}
|
||||
if(fShowLaps)
|
||||
fShowLaps->SetLapsActive(true);
|
||||
}
|
||||
|
||||
void plProfileManagerFull::CreateGraph(const char* varName, UInt32 min, UInt32 max)
|
||||
{
|
||||
// If the graph is already created, destroy it
|
||||
for (int i = 0; i < fGraphs.size(); i++)
|
||||
{
|
||||
if (strcmp(fGraphs[i]->GetTitle(), varName) == 0)
|
||||
{
|
||||
plPlateManager::Instance().DestroyPlate(fGraphs[i]);
|
||||
fGraphs.erase(fGraphs.begin()+i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
plProfileVar* var = IFindTimer(varName);
|
||||
if (var)
|
||||
{
|
||||
plGraphPlate* graph = nil;
|
||||
plPlateManager::Instance().CreateGraphPlate(&graph);
|
||||
graph->SetSize(0.25, 0.25);
|
||||
graph->SetDataRange(min, max, 100);
|
||||
graph->SetTitle(var->GetName());
|
||||
|
||||
fGraphs.push_back(graph);
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ResetDefaultDetailVars()
|
||||
{
|
||||
fDetailVars.clear();
|
||||
AddDetailVar("ApplyAnimation",0,50);
|
||||
AddDetailVar("AnimatingPhysicals",0,50);
|
||||
AddDetailVar("StoppedAnimPhysicals",0,50);
|
||||
AddDetailVar("DrawableTime",0,50);
|
||||
AddDetailVar("Polys",0,150000);
|
||||
AddDetailVar("Step",0,50);
|
||||
AddDetailVar("LineOfSight",0,50);
|
||||
AddDetailVar(" PhysicsUpdates",0,50);
|
||||
AddDetailVar("Stream Shove Time",0,50);
|
||||
AddDetailVar("RenderSetup",0,50);
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ShowDetailGraph()
|
||||
{
|
||||
// if graph is already created, kill it
|
||||
if (fDetailGraph)
|
||||
HideDetailGraph();
|
||||
if (fDetailVars.size() == 0)
|
||||
ResetDefaultDetailVars();
|
||||
|
||||
plPlateManager::Instance().CreateGraphPlate(&fDetailGraph);
|
||||
fDetailGraph->SetSize(0.9,0.9);
|
||||
fDetailGraph->SetDataRange(0,500,500);
|
||||
fDetailGraph->SetDataLabels(0,100); // should be relatively simple to cast everything to a 0-100 range
|
||||
fDetailGraph->SetTitle("Detail");
|
||||
UpdateDetailLabels();
|
||||
}
|
||||
|
||||
void plProfileManagerFull::HideDetailGraph()
|
||||
{
|
||||
if (fDetailGraph)
|
||||
{
|
||||
plPlateManager::Instance().DestroyPlate(fDetailGraph);
|
||||
fDetailGraph = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::AddDetailVar(const char* varName, UInt32 min, UInt32 max)
|
||||
{
|
||||
int i=0;
|
||||
for (i=0; i<fDetailVars.size(); i++)
|
||||
{
|
||||
if (stricmp(fDetailVars[i].var->GetName(), varName) == 0)
|
||||
return; // don't add it again
|
||||
}
|
||||
|
||||
plProfileVar* var = IFindTimer(varName);
|
||||
if (!var)
|
||||
return;
|
||||
var->SetActive(true);
|
||||
|
||||
if (fDetailVars.size() == 10)
|
||||
fDetailVars.erase(fDetailVars.begin()); // we don't want any more then 10 at this point, so drop the oldest one
|
||||
detailVar temp;
|
||||
temp.var = var;
|
||||
temp.min = min;
|
||||
temp.max = max;
|
||||
fDetailVars.push_back(temp);
|
||||
UpdateDetailLabels();
|
||||
}
|
||||
|
||||
void plProfileManagerFull::RemoveDetailVar(const char* varName)
|
||||
{
|
||||
int i=0;
|
||||
for (i=0; i<fDetailVars.size(); i++)
|
||||
{
|
||||
if (stricmp(fDetailVars[i].var->GetName(), varName) == 0)
|
||||
{
|
||||
fDetailVars.erase(fDetailVars.begin()+i);
|
||||
}
|
||||
}
|
||||
UpdateDetailLabels();
|
||||
}
|
||||
|
||||
void plProfileManagerFull::UpdateDetailLabels()
|
||||
{
|
||||
if (fDetailGraph)
|
||||
{
|
||||
int i;
|
||||
std::vector<std::string> labels;
|
||||
for (i=0; i<fDetailVars.size(); i++)
|
||||
labels.push_back(fDetailVars[i].var->GetName());
|
||||
|
||||
fDetailGraph->SetLabelText(labels);
|
||||
|
||||
// update the colors as well, just in case
|
||||
std::vector<UInt32> colors;
|
||||
colors.push_back(0xff00ff00); // green
|
||||
colors.push_back(0xff0000ff); // blue
|
||||
colors.push_back(0xffffff00); // yellow
|
||||
colors.push_back(0xffff00ff); // pink
|
||||
colors.push_back(0xffffffff); // white
|
||||
colors.push_back(0xff00ffff); // cyan
|
||||
colors.push_back(0xffff8000); // orange
|
||||
colors.push_back(0xff8000ff); // purple
|
||||
colors.push_back(0xffff0080); // fuscha
|
||||
colors.push_back(0xff808080); // grey
|
||||
|
||||
fDetailGraph->SetDataColors(colors);
|
||||
}
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ResetMax()
|
||||
{
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
fVars[i]->ResetMax();
|
||||
}
|
||||
|
||||
void plProfileManagerFull::ISetActive(const char* groupName, bool active)
|
||||
{
|
||||
for (int i = 0; i < fVars.size(); i++)
|
||||
{
|
||||
if (stricmp(fVars[i]->GetGroup(), groupName) == 0)
|
||||
{
|
||||
fVars[i]->SetActive(active);
|
||||
}
|
||||
}
|
||||
}
|
131
Sources/Plasma/PubUtilLib/plStatGather/plProfileManagerFull.h
Normal file
131
Sources/Plasma/PubUtilLib/plStatGather/plProfileManagerFull.h
Normal file
@ -0,0 +1,131 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef plProfileManagerFull_h_inc
|
||||
#define plProfileManagerFull_h_inc
|
||||
|
||||
#include "plProfileManager.h"
|
||||
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
#include "hsStlSortUtils.h"
|
||||
|
||||
class plProfileManager;
|
||||
class plGraphPlate;
|
||||
class plStatusLog;
|
||||
class hsStream;
|
||||
class plProfileVar;
|
||||
|
||||
class plProfileManagerFull
|
||||
{
|
||||
public:
|
||||
typedef std::set<const char*, stringISorter> GroupSet;
|
||||
|
||||
protected:
|
||||
plProfileManager::VarVec& fVars;
|
||||
|
||||
bool fLogStats; // If true, log the stats at the end of the frame
|
||||
std::wstring fLogAgeName;
|
||||
std::string fLogSpawnName;
|
||||
|
||||
std::vector<plGraphPlate*> fGraphs;
|
||||
plGraphPlate* fDetailGraph;
|
||||
|
||||
struct detailVar
|
||||
{
|
||||
plProfileVar* var;
|
||||
Int32 min;
|
||||
Int32 max;
|
||||
};
|
||||
|
||||
std::vector<detailVar> fDetailVars; // the vars we want to show on the detail graph
|
||||
|
||||
GroupSet fShowGroups;
|
||||
plProfileVar* fShowLaps;
|
||||
UInt32 fMinLap; // For Display
|
||||
|
||||
void IPrintGroup(hsStream* s, const char* groupName, bool printTitle=false);
|
||||
void ILogStats();
|
||||
|
||||
plProfileVar* IFindTimer(const char* name);
|
||||
|
||||
void ISetActive(const char* groupName, bool active);
|
||||
|
||||
plProfileManagerFull();
|
||||
|
||||
public:
|
||||
static plProfileManagerFull& Instance();
|
||||
|
||||
void EndFrame(); // Call end frame on our special timers
|
||||
void Update();
|
||||
|
||||
void GetGroups(GroupSet& groups);
|
||||
void ShowGroup(const char* groupName);
|
||||
void ShowNextGroup();
|
||||
|
||||
struct LapPair { const char* group; const char* varName; };
|
||||
typedef std::vector<LapPair> LapNames;
|
||||
void GetLaps(LapNames& lapNames);
|
||||
void ShowLaps(const char* groupName, const char* varName);
|
||||
void SetMinLap(int m) { fMinLap = m; };
|
||||
void PageDownLaps() { fMinLap += 40; }
|
||||
void PageUpLaps() { fMinLap = (fMinLap < 40) ? 0 : fMinLap - 40;}
|
||||
|
||||
void CreateGraph(const char* varName, UInt32 min, UInt32 max);
|
||||
|
||||
void ResetDefaultDetailVars();
|
||||
void ShowDetailGraph();
|
||||
void HideDetailGraph();
|
||||
void AddDetailVar(const char* varName, UInt32 min, UInt32 max);
|
||||
void RemoveDetailVar(const char* varName);
|
||||
void UpdateDetailLabels();
|
||||
|
||||
void ResetMax();
|
||||
|
||||
void LogStats(const char* ageName, const char* spawnName);
|
||||
const wchar* GetProfilePath();
|
||||
|
||||
// If you're going to call LogStats, make sure to call this first so all stats will be evaluated before logging
|
||||
void ActivateAllStats();
|
||||
|
||||
};
|
||||
|
||||
#endif // plProfileManagerFull_h_inc
|
@ -0,0 +1,50 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef plStatGatherCreatable_h_inc
|
||||
#define plStatGatherCreatable_h_inc
|
||||
|
||||
#include "../pnFactory/plCreator.h"
|
||||
|
||||
#include "plAutoProfile.h"
|
||||
REGISTER_NONCREATABLE(plAutoProfile);
|
||||
|
||||
#endif // plStatGatherCreatable_h_inc
|
Reference in New Issue
Block a user