/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts 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 .
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/console.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 3/14/02 4:07p $*
* *
* $Revision:: 138 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "console.h"
#include "consolefunction.h"
#include "textdisplay.h"
#include "assets.h"
#include "font3d.h"
#include "debug.h"
#include "timemgr.h"
#include "input.h"
#include "miscutil.h"
#include "cnetwork.h"
#include "teammanager.h"
#include "scene.h"
#include "ww3d.h"
#include
#include "wwaudio.h"
#include "audiblesound.H"
//#include "gamesettings.h"
#include "gamedata.h"
#include "overlay.h"
#include "combat.h"
#include "camera.h"
#include "ccamera.h"
#include "gameobjmanager.h"
#include "smartgameobj.h"
#include "playermanager.h"
#include "_globals.h"
#include "registry.h"
#include "phys3.h"
#include "wolgmode.h"
#include "devoptions.h"
#include "playertype.h"
#include "pscene.h"
#include "translatedb.h"
#include "string_ids.h"
#include "vehicle.h"
#include "wheelvehicle.h"
#include "wwprofile.h"
#include "wwmemlog.h"
#include "wheel.h"
#include "statistics.h"
#include "meshmdl.h"
#include "w3d_file.h" // for SURFACE_TYPE_STRINGS
#include "colors.h"
#include "chatshre.h"
#include "dx8renderer.h"
#include "dx8wrapper.h"
#include "umbrasupport.h"
#include "render2d.h"
#include "sortingrenderer.h"
#include "sctextobj.h"
#include "textdisplay.h"
#include "trackedvehicle.h"
#include "dx8rendererdebugger.h"
#include "fastallocator.h"
#include
#include "consolemode.h"
//#include "dlgmpingamechat.h"
#if (_MSC_VER >= 1200)
#pragma warning(push,1)
#endif
#include
#if (_MSC_VER >= 1200)
#pragma warning(pop)
#endif
static bool profile_log_active;
static StringClass* profile_log_names;
//
// ConsoleGameModeClass statics
//
ConsoleGameModeClass * ConsoleGameModeClass::Instance = NULL;
const float ConsoleGameModeClass::LeftMargin = 0.02f;
/*
** called each time through the main loop
*/
void ConsoleGameModeClass::Init()
{
ConsoleFunctionManager::Init();
WWASSERT( ConsoleGameModeClass::Instance == NULL );
ConsoleGameModeClass::Instance = this;
InputActive = false;
InputLine[0] = 0;
Clear_Suggestion();
// FPSActive = false;
FPSFrames = 0;
FPSTime = 0.0f;
FPSLastTime = 0.0f;
FPS = 0.0f;
// ShowPlayerPosition = false;
PerformanceSamplingActive = false;
Load_Registry_Keys();
ProfileIterator = NULL;
}
/*
** called each time through the main loop
*/
void ConsoleGameModeClass::Shutdown()
{
Save_Registry_Keys();
WWASSERT( ConsoleGameModeClass::Instance == this );
ConsoleGameModeClass::Instance = NULL;
ConsoleFunctionManager::Shutdown();
}
void ConsoleGameModeClass::Load_Registry_Keys(void)
{
// Debug_Say(( "CombatGameModeClass::Load_Registry_Keys...\n" ));
RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_OPTIONS );
WWASSERT( registry );
if ( registry->Is_Valid() ) {
WW3D::Set_Screen_UV_Bias( registry->Get_Int( "ScreenUVBias", 1 ) != 0 );
Get_Console()->Set_FPS_Active( registry->Get_Int( "FPS", 1 ) != 0 );
}
delete registry;
}
void ConsoleGameModeClass::Save_Registry_Keys(void)
{
// Debug_Say(( "CombatGameModeClass::Save_Registry_Keys...\n"));
RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_OPTIONS );
WWASSERT( registry );
if ( registry->Is_Valid() ) {
registry->Set_Int( "ScreenUVBias", WW3D::Is_Screen_UV_Biased() );
// registry->Set_Int( "TextureReduction", WW3D::Get_Texture_Reduction() );
// registry->Set_Int( "TextureThumbnail", WW3D::Get_Texture_Thumbnail_Mode() );
// registry->Set_Int( "TextureCompression", WW3D::Get_Texture_Compression_Mode() );
// registry->Set_Int( "NPatchesLevel", WW3D::Get_NPatches_Level() );
registry->Set_Int( "FPS", Get_Console()->Is_FPS_Active() );
}
delete registry;
}
#define BACKSPACE_KEY 8
#define ESC_KEY 27
#define ENTER_KEY 13
#define TAB_KEY 0x09
#define SPACE_KEY 0x20
/*
** called each time through the main loop
*/
void ConsoleGameModeClass::Think()
{
WWPROFILE( "Console Think" );
/*
//
// TSS092501 - disabling this because it is fatal.
// If you want it, you'll have to fix it!
//
if (Input::Get_State(INPUT_FUNCTION_VERBOSE_HELP)) {
ConsoleFunctionManager::Next_Verbose_Help_Screen();
}
*/
//cNetwork::Watch_Wol_Location(Drawer, Font);
if ( !InputActive ) {
bool enable_console = false;
#pragma message("TODO: relocate and provide UI for player communication.")
// HACK: Disable console in ATI demo
//#ifndef ATI_DEMO_HACK
if (Input::Get_State(INPUT_FUNCTION_BEGIN_CONSOLE)) {
enable_console = true;
ConsoleInputType = INPUT_FUNCTION_BEGIN_CONSOLE;
strcpy(InputLine, "Command >");
}
//#endif
if (enable_console) {
InputActive = true;
PromptLength = strlen(InputLine);
Input::Console_Enable();
Clear_Suggestion();
}
}
/*
** Handle Console Input
*/
if ( InputActive ) {
WWPROFILE( "Input Active" );
int key = Input::Console_Get_Key();
while ( key ) {
int len = strlen( InputLine ) ;
switch( key ) {
case ENTER_KEY:
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
Accept_Suggestion(InputLine + PromptLength);
len = strlen(InputLine);
Clear_Suggestion();
}
//Parse_Input( InputLine );
Parse_Input( InputLine + PromptLength );
case ESC_KEY:
InputActive = false;
Input::Console_Disable();
break;
case BACKSPACE_KEY:
//if ( len > 0 ) {
if ( len > PromptLength ) {
InputLine[ --len ] = 0;
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
Update_Suggestion(InputLine + PromptLength,true);
}
} else {
//DebugManager::Display();
}
break;
case TAB_KEY:
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
Update_Suggestion(InputLine + PromptLength,true);
}
break;
case SPACE_KEY:
// Accept any suggested command line completion and fall through to default
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
Accept_Suggestion(InputLine + PromptLength);
len = strlen(InputLine);
}
default:
if ( len + 1 < MAX_INPUT_LINE_LENGTH) {
InputLine[ len++ ] = key;
InputLine[ len ] = 0;
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
Update_Suggestion(InputLine + PromptLength,false);
}
} else {
//DebugManager::Display();
}
break;
}
key = Input::Console_Get_Key();
}
/*
** Console Input Output
*/
char mess[MAX_INPUT_LINE_LENGTH+2];
strcpy( mess, InputLine );
static int flash = 0;
if ( (int)(TimeManager::Get_Seconds()*4) & 1 ) {
strcat( mess, "|" );
}
strcat( mess, "\n" );
Vector3 color(1.0f,1.0f,1.0f);
switch (ConsoleInputType) {
/*
case INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE :
color = COLOR_PUBLIC_TEXT;
break;
case INPUT_FUNCTION_BEGIN_TEAM_MESSAGE :
color = cNetwork::Get_My_Color();
break;
case INPUT_FUNCTION_BEGIN_PRIVATE_MESSAGE :
color = COLOR_PRIVATE_TEXT;
break;
*/
case INPUT_FUNCTION_BEGIN_CONSOLE :
color = COLOR_CONSOLE_TEXT;
break;
default :
DIE;
break;
}
if (Get_Text_Display()) {
WWASSERT( Get_Text_Display() );
Get_Text_Display()->Set_Input_Text( mess );
Get_Text_Display()->Set_Help_Text( HelpLine );
}
} else {
if (Get_Text_Display()) {
WWASSERT( Get_Text_Display() );
Vector3 color(1,1,1);
Get_Text_Display()->Set_Input_Text( "" );
Get_Text_Display()->Set_Help_Text( "" );
}
}
/****************************************************************************************
**
** Vis Warning, In debug and profile mode, always display a warning if vis is missing
**
****************************************************************************************/
#ifdef WWDEBUG
{ WWPROFILE( "Vis Check" );
if (Get_Text_Display()) {
PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance();
Get_Text_Display()->Display_Vis_Warning( scene && scene->Is_Vis_Sector_Missing() );
}
}
#endif
// Note: As you add more stats, also add to the stats help command.
/****************************************************************************************
**
** Frame-Rate Stats. Activate with 'stats fps'
**
****************************************************************************************/
if (Get_Text_Display()) {
// Update text if it's visible
if (StatisticsDisplayManager::Is_Current_Display("histogram")) {
StringClass working_string(true);
StringClass message(true);
float cur_time = TimeManager::Get_Seconds();
FPSTime += cur_time - FPSLastTime;
FPSLastTime = cur_time;
FPSFrames++;
if ( FPSTime >= 1.0f ) {
FPS = (float)FPSFrames/FPSTime;
FPSTime = 0.0f;
FPSFrames = 0;
}
working_string.Format("%2.0f fps\n\n",FPS);
message += working_string;
unsigned slot_count=TimeManager::Peek_Frame_Time_Histogram().Get_Slot_Count();
if (slot_count) {
unsigned char* slots=new unsigned char[slot_count];
TimeManager::Peek_Frame_Time_Histogram().Get_Packed_Report(slots);
unsigned i;
for (i=0;i= 1.0f ) {
FPS = (float)FPSFrames/FPSTime;
FPSTime = 0.0f;
FPSFrames = 0;
}
working_string.Format("%2.0f fps\n",FPS);
message += working_string;
#ifdef ATI_DEMO_HACK
if (WW3D::Get_NPatches_Level()>1) {
working_string.Format(
"\nNPATCH level: %d\n",
WW3D::Get_NPatches_Level());
}
else {
working_string.Format("\nNPATCH OFF\n");
}
message += working_string;
#endif
working_string.Format(
"\npolys/frame: %7d\npolys/second %4dk\n",
WW3D::Get_Last_Frame_Poly_Count(),
int(WW3D::Get_Last_Frame_Poly_Count()*FPS/1000));
message += working_string;
unsigned ffheap=FastAllocatorGeneral::Get_Allocator()->Get_Total_Heap_Size();
unsigned ffuse=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocated_Size();
unsigned actualuse=FastAllocatorGeneral::Get_Allocator()->Get_Total_Actual_Memory_Usage();
unsigned count=FastAllocatorGeneral::Get_Allocator()->Get_Total_Allocation_Count();
working_string.Format(
"\nMalloc count: %d\n"
"Free count: %d\n"
"FF Heap: %d.%3.3d.%3.3d (%d Mb)\n"
"FF Use: %d.%3.3d.%3.3d (%d Mb)\n"
"Actual Use: %d.%3.3d.%3.3d (%d Mb)\n"
"FF Count: %d\n"
,
WW3D::Get_Last_Frame_Memory_Allocation_Count(),
WW3D::Get_Last_Frame_Memory_Free_Count(),
ffheap/(1000*1000),(ffheap/1000)%1000,ffheap%1000, ffheap/(1024*1024),
ffuse/(1000*1000),(ffuse/10000)%1000,ffuse%1000, ffuse/(1024*1024),
actualuse/(1000*1000),(actualuse/1000)%1000,actualuse%1000, actualuse/(1024*1024),
count);
message += working_string;
#ifndef ATI_DEMO_HACK
working_string.Format("verts/frame: %7d v/p ratio: %2.2f\n",
WW3D::Get_Last_Frame_Vertex_Count(),
float(WW3D::Get_Last_Frame_Vertex_Count())/float(WW3D::Get_Last_Frame_Poly_Count()));
message += working_string;
#endif
int texture_reduction = WW3D::Get_Texture_Reduction();
if (texture_reduction > 0) {
working_string.Format("Tex. Red. %d\n\n", texture_reduction);
message += working_string;
}
// Only display texture and vertex processor statistics if texture statistics recording is enabled
if (Debug_Statistics::Get_Record_Texture_Mode()!=Debug_Statistics::RECORD_TEXTURE_NONE) {
// Texture usage
int red_size=Debug_Statistics::Get_Record_Texture_Size();
int lightmap_size=Debug_Statistics::Get_Record_Lightmap_Texture_Size();
int procedural_size=Debug_Statistics::Get_Record_Procedural_Texture_Size();
working_string.Format(
"\n"
"textures/frame: %5d\n"
"tex memory used: %d.%dMb\n"
"texture changes: %d\n"
,
Debug_Statistics::Get_Record_Texture_Count(),
red_size>>20,
(10*(red_size>>10)>>10)%10,
Debug_Statistics::Get_Record_Texture_Change_Count());
message += working_string;
// Lightmap info
working_string.Format(
"\n"
"lightmaps/frame: %5d\n"
"lightmap memory used: %d.%dMb\n"
,
Debug_Statistics::Get_Record_Lightmap_Texture_Count(),
lightmap_size>>20,
(10*(lightmap_size>>10)>>10)%10);
message += working_string;
// Procedural texture info
working_string.Format(
"\n"
"procedural textures/frame: %5d\n"
"procedural memory used: %d.%dMb\n\n"
,
Debug_Statistics::Get_Record_Procedural_Texture_Count(),
procedural_size>>20,
(10*(procedural_size>>10)>>10)%10);
message += working_string;
// Texture info
red_size=TextureClass::_Get_Total_Texture_Size();
lightmap_size=TextureClass::_Get_Total_Lightmap_Texture_Size();
procedural_size=TextureClass::_Get_Total_Procedural_Texture_Size();
working_string.Format(
"\n"
"total tex loaded: %5d\n"
"total size of textures: %d.%dMb\n"
"\n"
"total lightmaps: %5d\n"
"total size of lightmaps: %dMb\n"
"\n"
"total procedural textures: %5d\n"
"total size of procedural textures: %dMb\n"
,
TextureClass::_Get_Total_Texture_Count(),
red_size>>20,
(10*(red_size>>10)>>10)%10,
TextureClass::_Get_Total_Lightmap_Texture_Count(),
lightmap_size>>20,
(10*(lightmap_size>>10)>>10)%10,
TextureClass::_Get_Total_Procedural_Texture_Count(),
procedural_size>>20,
(10*(procedural_size>>10)>>10)%10);
message += working_string;
// Thumbnail info
red_size=TextureClass::_Get_Total_Locked_Surface_Size();
working_string.Format(
"total thumbnails: %5d\n"
"total size of thumbnails: %d.%dMb\n"
,
TextureClass::_Get_Total_Locked_Surface_Count(),
red_size>>20,
(10*(red_size>>10)>>10)%10);
message += working_string;
if (Debug_Statistics::Get_Record_Texture_Mode()==Debug_Statistics::RECORD_TEXTURE_DETAILS) {
message+="\n"
" Scroll up\n"
" Scroll down\n"
"\n";
message+=Debug_Statistics::Get_Record_Texture_String();
}
}
if (Debug_Statistics::Get_Record_Texture_Mode()==Debug_Statistics::RECORD_TEXTURE_DETAILS) {
StatisticsDisplayManager::Set_Stat( "fps", message, 0xffffffcf );
}
else {
StatisticsDisplayManager::Set_Stat( "fps", message );
}
}
/****************************************************************************************
**
** Meshmodel Stats. Activate with 'stats dx8'
**
****************************************************************************************/
// Update text if it's visible
if (StatisticsDisplayManager::Is_Current_Display("dx8")) {
StringClass working_string(true);
StringClass message(true);
float cur_time = TimeManager::Get_Seconds();
FPSTime += cur_time - FPSLastTime;
FPSLastTime = cur_time;
FPSFrames++;
if ( FPSTime >= 1.0f ) {
FPS = (float)FPSFrames/FPSTime;
FPSTime = 0.0f;
FPSFrames = 0;
}
message.Format("%2.0f fps\n",FPS);
working_string.Format(
"Total DX8 calls: %d\n"
"Total Polys: %d\n"
"Total Verts: %d\n"
"Skins rendered: %d\n"
"(Total Polys in skins: %d)\n"
"(Total Verts in skins: %d)\n"
"Matrix changes: %d\n"
"Texture changes: %d\n"
"Material changes: %d\n"
"VB changes: %d\n"
"IB changes: %d\n"
"Light changes: %d\n\n"
"Sorted polys: %d\n"
"Sorted verts: %d\n",
DX8Wrapper::Get_Last_Frame_DX8_Calls(),
Debug_Statistics::Get_DX8_Polygons(),
Debug_Statistics::Get_DX8_Vertices(),
Debug_Statistics::Get_DX8_Skin_Renders(),
Debug_Statistics::Get_DX8_Skin_Polygons(),
Debug_Statistics::Get_DX8_Skin_Vertices(),
DX8Wrapper::Get_Last_Frame_Matrix_Changes(),
Debug_Statistics::Get_Record_Texture_Count(),
DX8Wrapper::Get_Last_Frame_Material_Changes(),
DX8Wrapper::Get_Last_Frame_Vertex_Buffer_Changes(),
DX8Wrapper::Get_Last_Frame_Index_Buffer_Changes(),
DX8Wrapper::Get_Last_Frame_Light_Changes(),
Debug_Statistics::Get_Sorting_Polygons(),
Debug_Statistics::Get_Sorting_Vertices());
message+=working_string;
// DX8MeshRendererContainerClass* n=DX8MeshRendererContainerClass::Head();
// int cont=0;
// while (n) {
// First check if container it empty
/* bool empty=true;
for (int a=0;arender_class_types[a].Get_Renderer_Head();
if (renderer) {
empty=false;
break;
}
}
// Log stats only if container is not empty
if (empty) {
working_string.Format("Container: %d EMPTY\n",cont);
message+=working_string;
}
else {
working_string.Format("Container: %d\n",cont);
message+=working_string;
for (int a=0;arender_class_types[a].Get_Renderer_Head();
if (!renderer) {
message+=" No registered renderers!\n";
}
else {
message+="\n";
}
while (renderer) {
if (renderer->stats_last_frame_add_calls || renderer->stats_last_frame_count) {
working_string.Format("%24s Add: %3d Render: %3d Polys: %3d\n",
renderer->name,
renderer->stats_last_frame_add_calls,
renderer->stats_last_frame_count,
renderer->stats_last_frame_polys);
message+=working_string;
}
renderer=renderer->Succ();
}
}
}
*/
// n=n->Succ();
// cont++;
// }
/* working_string.Format("Total add renders: %d\n",DX8MeshRendererClass::Get_Last_Frame_Render_Stats());
message+=working_string;
for (int ridx=0;ridxGet_2D_Sample_Count ();
int count_3d = WWAudioClass::Get_Instance ()->Get_3D_Sample_Count ();
message = "2D or Pseudo-3D Sounds:\n";
//
// Add all the 2D sounds to the message
//
for (int sample_index = 0; sample_index < count_2d; sample_index ++) {
temp_string.Format (" %d.", sample_index + 1);
message += temp_string;
AudibleSoundClass *sound_obj = WWAudioClass::Get_Instance ()->Peek_2D_Sample (sample_index);
if (sound_obj != NULL) {
if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_MUSIC) {
message += "(M)";
} else if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_SOUND_EFFECT) {
message += "(S)";
} else if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_DIALOG) {
message += "(D)";
}
StringClass filename = sound_obj->Get_Filename ();
message += filename;
message += "\n";
Vector3 curr_pos = sound_obj->Get_Position ();
PhysicsSceneClass::Get_Instance ()->Add_Debug_AABox (AABoxClass (curr_pos, Vector3 (0.25F,0.25F,0.25F)), Vector3 (1, 0, 0));
} else {
message += " --\n";
}
}
message += "\n3D Sounds:\n";
//
// Add all the 2D sounds to the message
//
for (sample_index = 0; sample_index < count_3d; sample_index ++) {
temp_string.Format (" %d.", sample_index + 1);
message += temp_string;
AudibleSoundClass *sound_obj = WWAudioClass::Get_Instance ()->Peek_3D_Sample (sample_index);
if (sound_obj != NULL) {
if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_MUSIC) {
message += "(M)";
} else if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_SOUND_EFFECT) {
message += "(S)";
} else if (sound_obj->Get_Type () == AudibleSoundClass::TYPE_DIALOG) {
message += "(D)";
}
StringClass filename = sound_obj->Get_Filename ();
message += filename;
message += "\n";
Vector3 curr_pos = sound_obj->Get_Position ();
PhysicsSceneClass::Get_Instance ()->Add_Debug_AABox (AABoxClass (curr_pos, Vector3 (0.25F,0.25F,0.25F)), Vector3 (0, 0, 1));
} else {
message += " --\n";
}
}
StatisticsDisplayManager::Set_Stat( "audio", message, 0xffffffff );
}
/****************************************************************************************
**
** Mesh rendering debug display page. Activate with 'stats mesh'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("mesh")) {
StringClass message;
DX8RendererDebugger::Enable(true); // The first frame will not have any information...
DX8RendererDebugger::Get_String(message);
StatisticsDisplayManager::Set_Stat( "star", message );
Vector2 pos = Render2DClass::Get_Screen_Resolution().Upper_Left();
StatisticsDisplayManager::Set_Stat( "mesh", message, 0xffffffff, pos );
}
/****************************************************************************************
**
** Star Stats Page. Activate with 'stats star'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("star")) {
StringClass working_string(true);
StringClass message(true);
working_string.Format("Star (%1.1f, %1.1f, %1.1f) %1.1f\n",
PlayerPosition.X, PlayerPosition.Y, PlayerPosition.Z, RAD_TO_DEGF(PlayerFacing) );
message = working_string;
if (COMBAT_STAR) {
Phys3Class * pobj = COMBAT_STAR->Peek_Physical_Object()->As_Phys3Class();
if (pobj) {
Vector3 vel;
pobj->Get_Velocity(&vel);
working_string.Format("Vel (%1.1f, %1.1f, %1.1f)\n",vel.X,vel.Y,vel.Z);
message += working_string;
}
}
if ( COMBAT_CAMERA ) {
working_string.Format("Range %1.1f\n", COMBAT_CAMERA->Get_Sniper_Distance() );
message += working_string;
}
StatisticsDisplayManager::Set_Stat( "star", message );
}
/****************************************************************************************
**
** Collision Detection Stats Page. Activate with 'stats collision'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("collision")) {
StringClass working_string(true);
StringClass message(true);
const CollisionMath::ColmathStatsStruct & stats = CollisionMath::Get_Current_Stats();
working_string.Format("Collision Stats\n");
message = working_string;
working_string.Format("Tests: %d\n",stats.TotalCollisionCount);
message += working_string;
working_string.Format("Hits: %d\n",stats.TotalCollisionHitCount);
message += working_string;
working_string.Format("Ray-Tri Tests: %d\n",stats.CollisionRayTriCount);
message += working_string;
working_string.Format("Ray-Tri Hits: %d\n",stats.CollisionRayTriHitCount);
message += working_string;
working_string.Format("AAB-Tri Tests: %d\n",stats.CollisionAABoxTriCount);
message += working_string;
working_string.Format("AAB-Tri Hits: %d\n",stats.CollisionAABoxTriHitCount);
message += working_string;
working_string.Format("OBB-Tri Tests: %d\n",stats.CollisionOBBoxTriCount);
message += working_string;
working_string.Format("OBB-Tri Hits: %d\n",stats.CollisionOBBoxTriHitCount);
message += working_string;
StatisticsDisplayManager::Set_Stat( "collision", message );
}
CollisionMath::Reset_Stats();
/****************************************************************************************
**
** Culling Stats Page. Activate with 'stats culling'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("culling")) {
StringClass working_string(true);
StringClass message(true);
PhysicsSceneClass * the_scene = PhysicsSceneClass::Get_Instance();
working_string.Format("Culling Stats\n");
message = working_string;
if (the_scene != NULL) {
const PhysicsSceneClass::StatsStruct & stats = the_scene->Get_Statistics();
if (stats.FrameCount > 0) {
working_string.Format("Frames: %d\n",stats.FrameCount);
message += working_string;
working_string.Format("Node Count: %d\n",stats.CullNodeCount);
message += working_string;
working_string.Format("Accepted: %d %10.3f pf\n",stats.CullNodesAccepted,(float)stats.CullNodesAccepted / (float)stats.FrameCount);
message += working_string;
working_string.Format("Triv Accepted: %d %10.3f pf\n",stats.CullNodesTriviallyAccepted,(float)stats.CullNodesTriviallyAccepted / (float)stats.FrameCount);
message += working_string;
working_string.Format("Rejected: %d %10.3f pf\n",stats.CullNodesRejected,(float)stats.CullNodesRejected / (float)stats.FrameCount);
message += working_string;
}
}
StatisticsDisplayManager::Set_Stat( "culling", message );
}
/****************************************************************************************
**
** Physics Stats Page. Activate with 'stats physics'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("physics")) {
StringClass working_string(true);
StringClass message(true);
PhysicsSceneClass * the_scene = PhysicsSceneClass::Get_Instance();
working_string.Format("Physics Stats\n");
message = working_string;
if (the_scene != NULL) {
int phys3_count = 0;
int phys3_active_count = 0;
int human_count = 0;
int rbody_count = 0;
int rbody_active_count = 0;
int wheeled_count = 0;
int tracked_count = 0;
int vtol_count = 0;
int projectile_count = 0;
int decoration_count = 0;
int light_count = 0;
int rendobj_count = 0;
int other_count = 0;
RefPhysListIterator iterator = the_scene->Get_Dynamic_Object_Iterator();
for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
PhysClass * obj = iterator.Peek_Obj();
WWASSERT(obj != NULL);
if (obj->As_Phys3Class()) {
phys3_count++;
if (!obj->Is_Asleep()) {
phys3_active_count++;
}
if (obj->As_HumanPhysClass()) {
human_count++;
}
} else if (obj->As_RigidBodyClass()) {
rbody_count++;
bool is_active = true;
if (obj->Is_Asleep()) {
is_active = false;
}
if ((obj->As_VehiclePhysClass()) && (obj->As_VehiclePhysClass()->Get_VehiclePhysDef()->Is_Fake() == true)) {
is_active = false;
}
if (is_active) {
rbody_active_count++;
}
if (obj->As_WheeledVehicleClass()) {
wheeled_count++;
} else if (obj->As_TrackedVehicleClass()) {
tracked_count++;
} else if (obj->As_VTOLVehicleClass()) {
vtol_count++;
}
} else if (obj->As_LightPhysClass()) {
light_count++;
} else if (obj->As_DecorationPhysClass()) {
decoration_count++;
} else if (obj->As_ProjectileClass()) {
projectile_count++;
} else if (obj->As_RenderObjPhysClass()) {
rendobj_count++;
} else {
other_count++;
}
}
working_string.Format("Phys3 Objects: %d (active: %d)\n",phys3_count,phys3_active_count);
message += working_string;
working_string.Format(" Human Objects: %d\n\n",human_count);
message += working_string;
working_string.Format("RBody Objects: %d (active: %d)\n",rbody_count,rbody_active_count);
message += working_string;
working_string.Format(" WheeledVehicle Objects: %d\n",wheeled_count);
message += working_string;
working_string.Format(" TrackedVehicle Objects: %d\n",tracked_count);
message += working_string;
working_string.Format(" VTOLVehicle Objects: %d\n\n",vtol_count);
message += working_string;
working_string.Format("Static Lights: %d\n",light_count);
message += working_string;
working_string.Format("Decoration Objects: %d\n",decoration_count);
message += working_string;
working_string.Format("Projectile Objects: %d\n",projectile_count);
message += working_string;
working_string.Format("Render Object Wrappers: %d\n",rendobj_count);
message += working_string;
working_string.Format("Other Objects: %d\n",other_count);
message += working_string;
int static_obj_count = 0;
int static_anim_count = 0;
iterator = the_scene->Get_Static_Object_Iterator();
for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
PhysClass * obj = iterator.Peek_Obj();
WWASSERT(obj != NULL);
if (obj->As_StaticPhysClass()) static_obj_count++;
if (obj->As_StaticAnimPhysClass()) static_anim_count++;
}
working_string.Format("Static objects: %d\n",static_obj_count);
message += working_string;
working_string.Format(" Static Anim Objects: %d\n",static_anim_count);
message += working_string;
StatisticsDisplayManager::Set_Stat("physics", message);
}
}
/****************************************************************************************
**
** Vehicle Debug Stats Page. Activate with 'stats vehicle'
** This will dump stats about any vehicle the player is currently controlling.
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("vehicle")) {
StringClass working_string(true);
StringClass message(true);
working_string.Format("Vehicle Debug Stats\n");
message = working_string;
if ((COMBAT_STAR != NULL) && (((PhysicalGameObj *) COMBAT_STAR)->As_SoldierGameObj() != NULL)) {
VehicleGameObj * vehicle_game_obj = ((PhysicalGameObj *)COMBAT_STAR)->As_SoldierGameObj()->Get_Vehicle();
if ((vehicle_game_obj != NULL) && (vehicle_game_obj->Peek_Physical_Object() != NULL)) {
VehiclePhysClass * vehicle = vehicle_game_obj->Peek_Physical_Object()->As_VehiclePhysClass();
if (vehicle != NULL) {
Vector3 vel;
vehicle->Get_Velocity(&vel);
float meters_per_sec = vel.Length();
float miles_per_hour = meters_per_sec * 60.0f * 60.0f * (1/1609.0f);
working_string.Format("Current Velocity: %10.2f m/s (%10.2f mph)\r\n",meters_per_sec,miles_per_hour);
message += working_string;
WheeledVehicleClass * wv = vehicle->As_WheeledVehicleClass();
if (wv != NULL) {
working_string.Format("Current Gear: %d\n", wv->Get_Current_Gear());
message += working_string;
working_string.Format("Engine avel: %10.3f\n", wv->Get_Engine_Angular_Velocity());
message += working_string;
working_string.Format("Engine rpm: %10.3f\n", RADS_TO_RPM(wv->Get_Engine_Angular_Velocity()));
message += working_string;
working_string.Format("Axle rpm: %10.3f\n", RADS_TO_RPM(wv->Get_Axle_Angular_Velocity()));
message += working_string;
working_string.Format("Engine torque: %10.3f\n", wv->Get_Engine_Torque());
message += working_string;
working_string.Format("Axle torque: %10.3f\n", wv->Get_Axle_Torque());
message += working_string;
working_string.Format("Max Engine torque: %10.3f\n", wv->Get_Max_Engine_Torque());
message += working_string;
}
TrackedVehicleClass * tv = vehicle->As_TrackedVehicleClass();
if (tv != NULL) {
const TrackedVehicleDefClass * def = tv->Get_TrackedVehicleDef();
if (def != NULL) {
working_string.Format("Max Engine Torque: %10.3f\n", def->Get_Max_Engine_Torque());
message += working_string;
working_string.Format("Turn Torque Scale Factor: %10.3f\n", def->Get_Turn_Torque_Scale_Factor());
message += working_string;
}
}
}
}
}
StatisticsDisplayManager::Set_Stat("vehicle", message, 0xffffffff );
}
/****************************************************************************************
**
** Collision Detection Stats Page. Activate with 'stats collision'
**
****************************************************************************************/
if (StatisticsDisplayManager::Is_Current_Display("ai")) {
StringClass working_string(true);
StringClass message(true);
working_string.Format("AI Stats\n");
message = working_string;
extern int _ActionActCalls;
working_string.Format("%d Action Act Calls\n",_ActionActCalls);
message += working_string;
_ActionActCalls = 0;
extern int _ActionCodeChanges;
working_string.Format("%d Action Code Changes\n", _ActionCodeChanges);
message += working_string;
_ActionCodeChanges = 0;
extern int _AwakeSoldiers;
working_string.Format("%d Awake Soldiers\n", _AwakeSoldiers);
message += working_string;
_AwakeSoldiers = 0;
extern int _HibernatingSoldiers;
working_string.Format("%d Hibernating Soldiers\n", _HibernatingSoldiers);
message += working_string;
_HibernatingSoldiers = 0;
SLNode *objnode;
for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
if ( !objnode->Data()->Is_Hibernating() ) {
if ( objnode->Data()->As_SmartGameObj() ) {
if ( objnode->Data()->As_SmartGameObj()->As_SoldierGameObj() ) {
Vector3 pos;
objnode->Data()->As_SmartGameObj()->Get_Position( &pos );
pos -= COMBAT_CAMERA->Get_Transform().Get_Translation();
float distance = pos.Length();
working_string.Format("ID %d awake (%1.1fm)\n", objnode->Data()->Get_ID(), distance );
message += working_string;
}
}
}
}
StatisticsDisplayManager::Set_Stat( "ai", message );
}
#ifdef WWDEBUG
/*
** WOL location diagnostic
*/
#if(0) // obsolete
if (StatisticsDisplayManager::Is_Current_Display("wol")) {
char string[200];
if (GameModeManager::Find("WOL")->Is_Active()) {
WWASSERT(PWC != NULL);
//sprintf(string, "WOL location: %s", PWC->Translate_Location());
sprintf(string, "WOL location: %s", Translate_Location(PWC->Get_Current_Location()));
} else {
sprintf(string, "WOL is not active.");
}
StatisticsDisplayManager::Set_Stat( "wol", string );
}
#endif // obsolete
#endif // WWDEBUG
}
if ( Input::Get_State( INPUT_FUNCTION_CNC )) {
ConsoleFunctionManager::Parse_Input( "CNC" );
}
// Note: As you add more stats, also add to the stats help command.
Update_Profile();
Update_Memory_Log();
}
/*
**
*/
void ConsoleGameModeClass::Parse_Input( char * string )
{
WWASSERT(Get_Console() != NULL);
if ( ConsoleInputType == INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE ||
ConsoleInputType == INPUT_FUNCTION_BEGIN_TEAM_MESSAGE ||
ConsoleInputType == INPUT_FUNCTION_BEGIN_PRIVATE_MESSAGE ) {
if (GameModeManager::Find("Combat")->Is_Active()) {
/*
if (cNetwork::I_Am_Client()) {
cNetwork::Send_Client_Text_Message(string, ConsoleInputType);
} else {
WWASSERT(ConsoleInputType == INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE);
WideStringClass text;
text.Convert_From(string);
if (!text.Is_Empty()) {
cScTextObj * p_test_obj = new cScTextObj;
p_test_obj->Init(text, TEXT_MESSAGE_PUBLIC, HOST_TEXT_SENDER);
}
}
*/
} else if (GameModeManager::Find("WOL")->Is_Active()) {
RefPtr wolSession = WWOnline::Session::GetInstance(false);
if (wolSession.IsValid()) {
wolSession->SendPublicMessage(string);
}
}
} else {
ConsoleFunctionManager::Parse_Input( string );
}
}
void ConsoleGameModeClass::Clear_Suggestion(void)
{
memset(Suggestion,0,sizeof(Suggestion));
memset(HelpLine,0,sizeof(HelpLine));
}
void ConsoleGameModeClass::Accept_Suggestion(char * cmd)
{
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
// If a space has already been entered or there is no suggestion, do nothing
if ((strchr(cmd,' ') == NULL) && (strlen(Suggestion) > 0)) {
strcpy(cmd,Suggestion);
}
}
}
void ConsoleGameModeClass::Update_Suggestion(char * cmd,bool go_to_next)
{
if (ConsoleInputType == INPUT_FUNCTION_BEGIN_CONSOLE) {
// If a space has already been entered don't update so that the help stays up
if ((strlen(cmd) > 0) && (strchr(cmd,' ') == NULL)) {
char * cur_suggestion = NULL;
if ((go_to_next) && (strlen(Suggestion) > 0)) {
cur_suggestion = &(Suggestion[0]);
}
bool gotone = ConsoleFunctionManager::Get_Command_Suggestion(cmd,cur_suggestion,Suggestion,HelpLine,sizeof(Suggestion));
if (!gotone) {
Clear_Suggestion();
}
}
}
}
void ConsoleGameModeClass::Profile_Command( const char * command )
{
if ( ProfileIterator != NULL ) {
if ( stricmp( command, "log" ) == 0 ) {
if (profile_log_active) End_Profile_Log();
else Begin_Profile_Log();
} else if ( stricmp( command, "off" ) == 0 ) {
WWProfileManager::Release_Iterator( ProfileIterator );
ProfileIterator = NULL;
} else if ( stricmp( command, "reset" ) == 0 ) {
WWProfileManager::Reset();
} else if ( stricmp( command, "up" ) == 0 ) {
ProfileIterator->Enter_Parent();
} else {
int index = atoi( command );
if ( index > -1 ) {
ProfileIterator->Enter_Child( index );
}
}
}
if ( ProfileIterator == NULL ) {
if ( stricmp( command, "on" ) == 0 ) {
ProfileIterator = WWProfileManager::Get_Iterator();
}
}
}
StringClass profile_string;
StringClass working_string;
void ConsoleGameModeClass::Update_Profile( void )
{
WWPROFILE( "Update Profile" );
#ifdef ATI_DEMO_HACK
// HACK
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD0)) WW3D::Set_NPatches_Level(0);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD1)) WW3D::Set_NPatches_Level(1);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD2)) WW3D::Set_NPatches_Level(2);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD3)) WW3D::Set_NPatches_Level(3);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD4)) WW3D::Set_NPatches_Level(4);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD5)) WW3D::Set_NPatches_Level(5);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD6)) WW3D::Set_NPatches_Level(6);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD7)) WW3D::Set_NPatches_Level(7);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD8)) WW3D::Set_NPatches_Level(8);
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_PARENT)) {
if (COMBAT_SCENE->Get_Polygon_Mode()==SceneClass::LINE) {
COMBAT_SCENE->Set_Polygon_Mode(SceneClass::FILL);
}
else {
COMBAT_SCENE->Set_Polygon_Mode(SceneClass::LINE);
}
}
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD9)) {
unsigned i=(unsigned)WW3D::Get_NPatches_Gap_Filling_Mode();
i&=1;
i^=1;
WW3D::Set_NPatches_Gap_Filling_Mode( (WW3D::NPatchesGapFillingModeEnum) i);
}
#endif
if (!StatisticsDisplayManager::Is_Current_Display("profile")) return;
if (profile_log_active) {
Process_Profile_Log();
Vector2 pos = (Render2DClass::Get_Screen_Resolution().Upper_Left() + Render2DClass::Get_Screen_Resolution().Lower_Left()) * 0.5f;
StatisticsDisplayManager::Set_Stat( "profile", "LOG IN PROGRESS", 0xffffffff, pos );
return;
}
// It costs to allocate these, lets just skip strings that grow.
// StringClass profile_string( 2000, true );
// StringClass working_string( 200, true );
if ( ProfileIterator ) {
/*
** Handle user input. When the profiler is active, the numeric keypad can be used to
** traverse the profile tree.
** '1'-'9' enter profile node 1-9
** '.' go to parent node
** '*' reset the profile data
*/
#ifndef ATI_DEMO_HACK
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD0)) { Profile_Command("0"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD1)) { Profile_Command("1"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD2)) { Profile_Command("2"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD3)) { Profile_Command("3"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD4)) { Profile_Command("4"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD5)) { Profile_Command("5"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD6)) { Profile_Command("6"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD7)) { Profile_Command("7"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD8)) { Profile_Command("8"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_CHILD9)) { Profile_Command("9"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_ENTER_PARENT)) { Profile_Command("up"); }
if (Input::Get_State(INPUT_FUNCTION_PROFILE_RESET)) { Profile_Command("reset"); }
#endif
// Only update every 1/4 second
static float timer = 0;
timer += TimeManager::Get_Frame_Seconds();
if ( timer < 0.25f ) {
return;
}
timer = 0;
profile_string = "";
working_string = "";
/*
** Update the profile display
*/
const char * parent_name = ProfileIterator->Get_Current_Parent_Name();
float parent_time = ProfileIterator->Get_Current_Parent_Total_Time();
profile_string.Format( "PROFILE DATA for %s\n\n", parent_name );
working_string.Format(
" Name %%parent %%total ms/f ms/call calls/f\n\n");
profile_string += working_string;
int index = 0;
float total_time = WWProfileManager::Get_Time_Since_Reset();
int total_frames = WWProfileManager::Get_Frame_Count_Since_Reset();
float missing_parent_time = parent_time;
if ((total_frames > 0) && (total_time > 0.0f)) {
float percent_of_parent;
float percent_of_total;
float ms_per_frame;
float ms_per_call;
int calls_per_frame;
/*
** Display stats for each child node
*/
for ( ProfileIterator->First(); !ProfileIterator->Is_Done(); ProfileIterator->Next() ) {
int calls = ProfileIterator->Get_Current_Total_Calls();
float time = ProfileIterator->Get_Current_Total_Time();
const char * name = ProfileIterator->Get_Current_Name();
missing_parent_time -= time;
/*
** First print the index and name of the profile entry
*/
working_string.Format("%-2d %-25s",index,name);
profile_string += working_string;
/*
** Print the percent of the parent and percent of total time.
** If there is no parent time, we are at the wrapper of everything and
** we simply print that it is 100% of the time and
*/
percent_of_total = 100.0f * time / total_time;
if (parent_time != 0.0f) {
percent_of_parent = 100.0f * time / parent_time;
working_string.Format(" %-6.2f %-6.2f",percent_of_parent,percent_of_total);
} else {
percent_of_parent = 100.0f;
working_string.Format(" -- %-6.2f",percent_of_total);
}
profile_string += working_string;
/*
** Print the ms_per_frame
*/
ms_per_frame = 1000.0f * time / total_frames;
working_string.Format(" %-6.2f",ms_per_frame);
profile_string += working_string;
/*
** Print the ms_per_call and number of calls or '--' if not available
*/
if (calls > 0) {
ms_per_call = 1000.0f * time / (float)calls;
calls_per_frame = calls / total_frames;
working_string.Format(" %-6.2f %-4d (%4d)\n",ms_per_call, calls_per_frame, calls);
} else {
working_string.Format(" -- -- \n");
}
profile_string += working_string;
/*
** Increment the index
*/
index++;
}
/*
** Display stats for the un-accounted time. Note that there will only be
** "missing_parent_time" if there also was "parent_time"...
*/
if (parent_time > 0.0f) {
percent_of_parent = 100.0f * missing_parent_time / parent_time;
percent_of_total = 100.0f * missing_parent_time / total_time;
ms_per_frame = 1000.0f * missing_parent_time / total_frames;
working_string.Format(
" %-25s %-6.2f %-6.2f %-6.2f\n",
"MISSING TIME",
percent_of_parent,
percent_of_total,
ms_per_frame );
profile_string += working_string;
}
}
if (ConsoleBox.Is_Exclusive()) {
ConsoleBox.Update_Profile(profile_string);
} else {
Vector2 pos = (Render2DClass::Get_Screen_Resolution().Upper_Left() + Render2DClass::Get_Screen_Resolution().Lower_Left()) * 0.5f;
StatisticsDisplayManager::Set_Stat( "profile", profile_string, 0xffffffff, pos );
}
}
}
class ProfileLogNodeClass
{
StringClass string;
ProfileLogNodeClass* succ;
float* percentages;
unsigned count;
public:
ProfileLogNodeClass(unsigned count);
~ProfileLogNodeClass();
void Set(unsigned index,float value) { WWASSERT(indexsucc=this;
profile_log_tail=this;
}
percentages=new float[count];
}
ProfileLogNodeClass::~ProfileLogNodeClass()
{
delete[] percentages;
if (profile_log_head==this) profile_log_head=succ;
if (profile_log_tail==this) profile_log_tail=NULL;
}
void ConsoleGameModeClass::Begin_Profile_Log()
{
if (profile_log_active) return;
profile_log_active=true;
}
void ConsoleGameModeClass::End_Profile_Log()
{
if (!profile_log_active) return;
profile_log_active=false;
ProfileLogNodeClass* node=profile_log_head;
if (node && profile_log_names) {
for (unsigned index=0;indexGet_Count();++index) {
char tmp[8];
strncpy(tmp,profile_log_names[index],sizeof(tmp));
tmp[7]='\0';
WWDEBUG_SAY(("%7s ",tmp));
}
WWDEBUG_SAY(("\n"));
}
while (node) {
for (unsigned index=0;indexGet_Count();++index) {
WWDEBUG_SAY(("%2.2f ",node->Get(index)));
}
WWDEBUG_SAY(("\n"));
node=node->Succ();
}
WWDEBUG_SAY(("\n\n"));
node=profile_log_head;
while (node) {
WWDEBUG_SAY(("%s\n",node->Get_String()));
node=node->Succ();
}
while (profile_log_head) {
delete profile_log_head;
}
delete[] profile_log_names;
profile_log_names=NULL;
}
void ConsoleGameModeClass::Process_Profile_Log()
{
if ( ProfileIterator ) {
// Only update every 1/4 second
static float timer = 0;
timer += TimeManager::Get_Frame_Seconds();
if ( timer < 0.25f ) {
return;
}
timer = 0;
profile_string = "";
working_string = "";
/*
** Update the profile display
*/
// const char * parent_name = ProfileIterator->Get_Current_Parent_Name();
// float parent_time = ProfileIterator->Get_Current_Parent_Total_Time();
//
float total_time = WWProfileManager::Get_Time_Since_Reset();
int total_frames = WWProfileManager::Get_Frame_Count_Since_Reset();
//
// float missing_parent_time = parent_time;
if ((total_frames > 0) && (total_time > 0.0f)) {
// float percent_of_parent;
float percent_of_total;
// float ms_per_frame;
// float ms_per_call;
// int calls_per_frame;
unsigned index=0;
for ( ProfileIterator->First(); !ProfileIterator->Is_Done(); ProfileIterator->Next(),index++ ) {
}
delete[] profile_log_names;
profile_log_names=NULL;
if (index) {
profile_log_names=new StringClass[index];
}
ProfileLogNodeClass* node=new ProfileLogNodeClass(index);
/*
** Display stats for each child node
*/
index=0;
for ( ProfileIterator->First(); !ProfileIterator->Is_Done(); ProfileIterator->Next() ) {
// int calls = ProfileIterator->Get_Current_Total_Calls();
float time = ProfileIterator->Get_Current_Total_Time();
const char * name = ProfileIterator->Get_Current_Name();
profile_log_names[index]=name;
// missing_parent_time -= time;
/*
** First print the index and name of the profile entry
*/
// working_string.Format("%-2d %-25s",index,name);
// profile_string += working_string;
/*
** Print the percent of the parent and percent of total time.
** If there is no parent time, we are at the wrapper of everything and
** we simply print that it is 100% of the time and
*/
percent_of_total = 100.0f * time / total_time;
// if (parent_time != 0.0f) {
// percent_of_parent = 100.0f * time / parent_time;
// working_string.Format(" %-6.2f %-6.2f",percent_of_parent,percent_of_total);
// } else {
// percent_of_parent = 100.0f;
// working_string.Format(" -- %-6.2f",percent_of_total);
// }
// profile_string += working_string;
node->Set(index,percent_of_total);
/*
** Print the ms_per_frame
*/
// ms_per_frame = 1000.0f * time / total_frames;
// working_string.Format(" %-6.2f",ms_per_frame);
// profile_string += working_string;
/*
** Print the ms_per_call and number of calls or '--' if not available
*/
// if (calls > 0) {
// ms_per_call = 1000.0f * time / (float)calls;
// calls_per_frame = calls / total_frames;
// working_string.Format(" %-6.2f %-4d (%4d)\n",ms_per_call, calls_per_frame, calls);
// } else {
// working_string.Format(" -- -- \n");
// }
// profile_string += working_string;
/*
** Increment the index
*/
index++;
}
/*
** Display stats for the un-accounted time. Note that there will only be
** "missing_parent_time" if there also was "parent_time"...
*/
/* if (parent_time > 0.0f) {
percent_of_parent = 100.0f * missing_parent_time / parent_time;
percent_of_total = 100.0f * missing_parent_time / total_time;
ms_per_frame = 1000.0f * missing_parent_time / total_frames;
working_string.Format(
" %-25s %-6.2f %-6.2f %-6.2f\n",
"MISSING TIME",
percent_of_parent,
percent_of_total,
ms_per_frame );
profile_string += working_string;
}
*/
node->Set_String(profile_string);
// Vector2 pos = (Render2DClass::Get_Screen_Resolution().Upper_Left() + Render2DClass::Get_Screen_Resolution().Lower_Left()) * 0.5f;
// StatisticsDisplayManager::Set_Stat( "profile", profile_string, 0xffffffff, pos );
}
}
}
void ConsoleGameModeClass::Update_Memory_Log( void )
{
if (!StatisticsDisplayManager::Is_Current_Display("memory")) return;
const float MEGABYTE = 1048576.0f;
const float OOMEGABYTE = 1.0f / MEGABYTE;
StringClass memory_string(2048);
StringClass working_string(true);
memory_string.Format("Memory Category Current(Mb) Peak(Mb)\n");
int total = 0;
for (int i=0; i