1782 lines
55 KiB
C++
1782 lines
55 KiB
C++
|
/*
|
||
|
** 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** 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 <stdio.h>
|
||
|
#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 <WWOnline\WOLSession.h>
|
||
|
#include "consolemode.h"
|
||
|
|
||
|
//#include "dlgmpingamechat.h"
|
||
|
|
||
|
|
||
|
#if (_MSC_VER >= 1200)
|
||
|
#pragma warning(push,1)
|
||
|
#endif
|
||
|
|
||
|
#include <sstream>
|
||
|
|
||
|
#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<slot_count;++i) {
|
||
|
working_string.Format("%d: %d\n",
|
||
|
unsigned(TimeManager::Peek_Frame_Time_Histogram().Get_Step()*float(i)),
|
||
|
slots[i]);
|
||
|
message+=working_string;
|
||
|
}
|
||
|
delete[] slots;
|
||
|
}
|
||
|
StatisticsDisplayManager::Set_Stat( "histogram", message );
|
||
|
}
|
||
|
|
||
|
// Update text if it's visible
|
||
|
if (StatisticsDisplayManager::Is_Current_Display("fps")) {
|
||
|
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",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"
|
||
|
"<F9 + F5> Scroll up\n"
|
||
|
"<F9 + F6> 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;a<DX8MeshRendererContainerClass::RENDER_CLASS_MAX;++a) {
|
||
|
DX8MeshRendererClass* renderer=n->render_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;a<DX8MeshRendererContainerClass::RENDER_CLASS_MAX;++a) {
|
||
|
working_string.Format("Class: %s",
|
||
|
DX8MeshRendererContainerClass::Get_Render_Class_Name(a));
|
||
|
message+=working_string;
|
||
|
|
||
|
DX8MeshRendererClass* renderer=n->render_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;ridx<DX8MeshRendererContainerClass::RENDER_CLASS_MAX;++ridx) {
|
||
|
working_string.Format("Class: %s\nObjects: %d\nPolys: %d\n\n",
|
||
|
DX8MeshRendererContainerClass::Get_Render_Class_Name(ridx),
|
||
|
DX8MeshRendererClass::Get_Last_Frame_Render_Stats(ridx).count,
|
||
|
DX8MeshRendererClass::Get_Last_Frame_Render_Stats(ridx).polys);
|
||
|
message+=working_string;
|
||
|
}
|
||
|
*/ StatisticsDisplayManager::Set_Stat( "dx8", message, 0xffffffff );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/****************************************************************************************
|
||
|
**
|
||
|
** Audio Stats. Activate with 'stats audio'
|
||
|
**
|
||
|
****************************************************************************************/
|
||
|
|
||
|
// Update text if it's visible
|
||
|
if (StatisticsDisplayManager::Is_Current_Display("audio")) {
|
||
|
|
||
|
StringClass message (true);
|
||
|
StringClass temp_string (true);
|
||
|
int count_2d = WWAudioClass::Get_Instance ()->Get_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<BaseGameObj> *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<WWOnline::Session> 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(index<count); percentages[index]=value; }
|
||
|
float Get(unsigned index) const { WWASSERT(index<count); return percentages[index]; }
|
||
|
void Set_String(const StringClass& string_) { string=string_; }
|
||
|
const StringClass& Get_String() const { return string; }
|
||
|
unsigned Get_Count() const { return count; }
|
||
|
|
||
|
ProfileLogNodeClass* Succ() { return succ; }
|
||
|
};
|
||
|
|
||
|
static ProfileLogNodeClass* profile_log_head;
|
||
|
static ProfileLogNodeClass* profile_log_tail;
|
||
|
|
||
|
ProfileLogNodeClass::ProfileLogNodeClass(unsigned count_)
|
||
|
:
|
||
|
count(count_),
|
||
|
succ(NULL)
|
||
|
{
|
||
|
if (!profile_log_head) {
|
||
|
profile_log_head=this;
|
||
|
profile_log_tail=this;
|
||
|
}
|
||
|
else {
|
||
|
profile_log_tail->succ=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;index<node->Get_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;index<node->Get_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<WWMemoryLogClass::Get_Category_Count(); i++) {
|
||
|
|
||
|
// (gth) to compute Mb should I divide by the nearest power of two to a million?
|
||
|
working_string.Format("%-18s %-10.2f %-10.2f\r\n",
|
||
|
WWMemoryLogClass::Get_Category_Name(i),
|
||
|
(float)WWMemoryLogClass::Get_Current_Allocated_Memory(i) * OOMEGABYTE,
|
||
|
(float)WWMemoryLogClass::Get_Peak_Allocated_Memory(i) * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
total += WWMemoryLogClass::Get_Current_Allocated_Memory(i);
|
||
|
}
|
||
|
|
||
|
#if (UMBRASUPPORT)
|
||
|
float umbra_mem = UmbraSupport::Get_Umbra_Memory_Consumption();
|
||
|
total += umbra_mem;
|
||
|
working_string.Format("Umbra: %-10.2f\r\n",umbra_mem * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
#endif
|
||
|
|
||
|
working_string.Format("SUB TOTAL: %-10.2f\r\n\r\n",(float)total * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
|
||
|
// display the estimated space used by textures residing in system ram
|
||
|
int tex_size=TextureClass::_Get_Total_Texture_Size();
|
||
|
working_string.Format("%-18s %-10.2f\r\n","Textures(est)",(float)tex_size * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
total+=tex_size;
|
||
|
|
||
|
// display estimated vertex buffer space
|
||
|
unsigned vb_size=VertexBufferClass::Get_Total_Allocated_Memory();
|
||
|
working_string.Format("%-18s %-10.2f\r\n","Vertex Buffers(est)",(float)vb_size * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
total+=vb_size;
|
||
|
|
||
|
// display estimated index buffer space
|
||
|
unsigned ib_size=IndexBufferClass::Get_Total_Allocated_Memory();
|
||
|
working_string.Format("%-18s %-10.2f\r\n","Index Buffers(est)",(float)ib_size * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
total+=ib_size;
|
||
|
|
||
|
// total!
|
||
|
working_string.Format("TOTAL: %-10.2f\r\n\r\n",(float)total * OOMEGABYTE);
|
||
|
memory_string += working_string;
|
||
|
|
||
|
StatisticsDisplayManager::Set_Stat( "memory", memory_string, 0xffffffff );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|