//----------------------------------------------------------------------------------- SceneImport* FbxLoadSceneFromFile(const char* fbxFilename, const Matrix4x4& engineBasis, bool isEngineBasisRightHanded, const Matrix4x4& transform) { FbxScene* scene = nullptr; FbxManager* fbxManager = FbxManager::Create(); if (nullptr == fbxManager) { Console::instance->PrintLine("Could not create fbx manager."); DebuggerPrintf("Could not create fbx manager."); return nullptr; } FbxIOSettings* ioSettings = FbxIOSettings::Create(fbxManager, IOSROOT); //Name of object is blank, we don't care fbxManager->SetIOSettings(ioSettings); //Create an importer FbxImporter* importer = FbxImporter::Create(fbxManager, ""); bool loadSuccessful = importer->Initialize(fbxFilename, -1, fbxManager->GetIOSettings()); if (loadSuccessful) { //We have imported the FBX scene = FbxScene::Create(fbxManager, ""); bool importSuccessful = importer->Import(scene); ASSERT_OR_DIE(importSuccessful, "Scene import failed!"); } else { Console::instance->PrintLine(Stringf("Could not import scene: %s", fbxFilename)); DebuggerPrintf("Could not import scene: %s", fbxFilename); } SceneImport* import = new SceneImport(); MatrixStack4x4 matrixStack; matrixStack.Push(transform); //Set up our initial transforms Matrix4x4 sceneBasis = GetSceneBasis(scene); Matrix4x4::MatrixTranspose(&sceneBasis); if (!isEngineBasisRightHanded) { Vector3 forward = Matrix4x4::MatrixGetForward(&sceneBasis); Matrix4x4::MatrixSetForward(&sceneBasis, -forward); //3rd row or column } matrixStack.Push(sceneBasis); ImportScene(import, scene, matrixStack); FBX_SAFE_DESTROY(importer); FBX_SAFE_DESTROY(ioSettings); FBX_SAFE_DESTROY(scene); FBX_SAFE_DESTROY(fbxManager); return import; }
//----------------------------------------------------------------------------------------------- __declspec( noreturn ) void FatalError( const char* filePath, const char* functionName, int lineNum, const std::string& reasonForError, const char* conditionText ) { std::string errorMessage = reasonForError; if( reasonForError.empty() ) { if( conditionText ) errorMessage = Stringf( "ERROR: \"%s\" is false!", conditionText ); else errorMessage = "Unspecified fatal error"; } const char* fileName = FindStartOfFileNameWithinFilePath( filePath ); // std::string appName = theApplication ? theApplication->GetApplicationName() : "Unnamed Application"; std::string appName = "Unnamed Application"; std::string fullMessageTitle = appName + " :: Error"; std::string fullMessageText = errorMessage; fullMessageText += "\n\nThe application will now close.\n"; bool isDebuggerPresent = (IsDebuggerPresent() == TRUE); if( isDebuggerPresent ) { fullMessageText += "\nDEBUGGER DETECTED!\nWould you like to break and debug?\n (Yes=debug, No=quit)\n"; } fullMessageText += "\n---------- Debugging Details Follow ----------\n"; if( conditionText ) { fullMessageText += Stringf( "\nThis error was triggered by a run-time condition check:\n %s\n from %s(), line %i in %s\n", conditionText, functionName, lineNum, fileName ); } else { fullMessageText += Stringf( "\nThis was an unconditional error triggered by reaching\n line %i of %s, in %s()\n", lineNum, fileName, functionName ); } DebuggerPrintf( "\n==============================================================================\n" ); DebuggerPrintf( "RUN-TIME FATAL ERROR on line %i of %s, in %s()\n", lineNum, fileName, functionName ); DebuggerPrintf( "%s(%d): %s\n", filePath, lineNum, errorMessage.c_str() ); // Use this specific format so Visual Studio users can double-click to jump to file-and-line of error DebuggerPrintf( "==============================================================================\n\n" ); if( isDebuggerPresent ) { bool isAnswerYes = SystemDialogue_YesNo( fullMessageTitle, fullMessageText, SEVERITY_FATAL ); ShowCursor( TRUE ); if( isAnswerYes ) { __debugbreak(); } } else { SystemDialogue_Okay( fullMessageTitle, fullMessageText, SEVERITY_FATAL ); ShowCursor( TRUE ); } exit( 0 ); }
//----------------------------------------------------------------------------------- void MemoryAnalytics::Free(const void* ptr) { size_t *sizedPtr = (size_t *)ptr; --sizedPtr; MemoryMetadata* metadata = (MemoryMetadata*)*sizedPtr; ::free(sizedPtr); #if (TRACK_MEMORY == 2) DebuggerPrintf("Delete called for %p.\n", ptr); #endif // TRACK_MEMORY == 2 //THIS IS THE PART THAT NEEDS TO BE THREAD-SAFE AttemptLock(); { --m_numberOfAllocations; m_numberOfBytes -= metadata->sizeOfAllocInBytes; #if (TRACK_MEMORY > 0) MemoryMetadata::RemoveMemoryMetadataFromList(metadata); UntrackedDelete<MemoryMetadata>(metadata); #endif // TRACK_MEMORY > 0 } AttemptLeave(); }
//----------------------------------------------------------------------------------- void MemoryAnalytics::Startup() { m_isInitialized = true; CallstackSystemInit(); DebuggerPrintf("Number of allocations before startup: %i. Total size: %luB\n", m_numberOfAllocations, m_numberOfBytes); m_startupNumberOfAllocations = m_numberOfAllocations; }
IntVector2 Map::FindRandomValidLocationToSpawn() { IntVector2 position; bool foundALocation = false; int indicesToConsider = m_tiles.size(); int numTimesRan = 0; while (!foundALocation) { int ind = RandInt(0, indicesToConsider - 1); Tile* currTile = GetTileAtIndex(ind); if (nullptr != currTile && currTile->IsValid() && currTile->GetCurrentTileType() != TILE_WATER && currTile->GetCurrentTileType() != TILE_LAVA) { position = currTile->GetLocation(); foundALocation = true; } if (numTimesRan > 10000) { DebuggerPrintf("ERROR: Find Random Valid Location running too long."); return IntVector2(0, 0); } numTimesRan++; } return position; }
//--------------------------------------------------------------------------- ZipFile::ZipFile( const char* zipFilePath ) { memset( &m_zipArchive, 0, sizeof( mz_zip_archive ) ); mz_bool success = mz_zip_reader_init_file( &m_zipArchive, zipFilePath, 0 ); if ( !success ) { DebuggerPrintf( "Zip file creation failed!\n" ); } }
STATIC ItemFactory* ItemFactory::GetFactoryByName(const String& name) { std::map<String, ItemFactory*>::iterator factory = s_itemFactories.find(name); if (factory == s_itemFactories.end()) { DebuggerPrintf("%s%s", "Couldn't find Item blueprint ", name); return nullptr; } else { return factory->second; } }
void MemoryAllocatePool::ScanMemory() { MemorySpaceHeader* currentNode = m_headOfFreeSpace; while (currentNode) { if (!currentNode->available) { DebuggerPrintf("%s(%d) : memory leak , size-> %d bytes , memory address -> %d \r\n", currentNode->filename, currentNode->line, currentNode->sizeInBytes, currentNode); } currentNode = currentNode->next; } }
//----------------------------------------------------------------------------------------------- void ScenarioStartFunction_Responsibility( Scenario& scenario ) { DebuggerPrintf( "Starting scenario '%s'...\n", scenario.m_name.c_str() ); //1024x576 Actor *player=new Actor(); player->m_position = Vector2(352+144, 320+128); player->m_isPlayer = true; player->m_baseColor = Rgba::BLUE; scenario.m_actors.push_back( player ); RelationshipToOtherActor followPlayer; followPlayer.m_attractionRepulsionAtOuterDistance = Vector2(0.75f, 0.75f); followPlayer.m_attractionRepulsionAtInnerDistance = Vector2(-0.25f, -0.25f); followPlayer.m_outerDistance = 128; followPlayer.m_innerDistance = 16; followPlayer.m_otherActor = player; for(int i = 0; i < 5; i++) { for(int j = 0; j < 5; j++) { if(i == 2 && j == 2) { continue; } AC(a, player->m_position.x-(i-2)*30, player->m_position.y-(j-2)*30); } } for(int i = 0; i < scenario.m_actors.size(); i++) { Actor *a = scenario.m_actors[i]; RelationshipToOtherActor dontBumpA; dontBumpA.m_innerDistance = 0; dontBumpA.m_outerDistance = 64; dontBumpA.m_attractionRepulsionAtOuterDistance = Vector2(0,0); dontBumpA.m_attractionRepulsionAtInnerDistance = Vector2(-3,-3); dontBumpA.m_otherActor = a; for(int j = 0; j < scenario.m_actors.size(); j++) { if(i == j) { continue; } Actor *b = scenario.m_actors[j]; b->m_relationships.push_back(dontBumpA); } } AR(ar1, 352, 320, 288, 256); AR(ar2, 96, 256, 288, 256); AR(ar3, 224, 32, 288, 256); AR(ar4, 352, 320, 288, 256); AR(ar5, 512, 128, 288, 256); AR(ar6, 800, 32, 288, 256); Area *pGoal=new Area(); pGoal->m_bounds.SetFromMinXYMaxXY( 928, 32, 1500, 32+256 ); pGoal->m_color = Rgba::WHITE; pGoal->m_alpha = 1.0f; scenario.m_areas.push_back( pGoal ); }
//----------------------------------------------------------------------------------- void FbxListScene(const char* filename) { FbxManager* fbxManager = FbxManager::Create(); if (nullptr == fbxManager) { Console::instance->PrintLine("Could not create fbx manager."); DebuggerPrintf("Could not create fbx manager."); return; } FbxIOSettings* ioSettings = FbxIOSettings::Create(fbxManager, IOSROOT); //Name of object is blank, we don't care fbxManager->SetIOSettings(ioSettings); //Create an importer FbxImporter* importer = FbxImporter::Create(fbxManager, ""); bool loadSuccessful = importer->Initialize(filename, -1, fbxManager->GetIOSettings()); if (loadSuccessful) { //We have imported the FBX FbxScene* scene = FbxScene::Create(fbxManager, ""); bool importSuccessful = importer->Import(scene); if (importSuccessful) { FbxNode* root = scene->GetRootNode(); PrintNode(root, 0); } FBX_SAFE_DESTROY(scene); } else { Console::instance->PrintLine(Stringf("Could not import scene: %s", filename)); DebuggerPrintf("Could not import scene: %s", filename); } FBX_SAFE_DESTROY(importer); FBX_SAFE_DESTROY(ioSettings); FBX_SAFE_DESTROY(fbxManager); }
//----------------------------------------------------------------------------------- static void PrintNode(FbxNode* node, int depth) { Console::instance->PrintLine(Stringf("%*sNode [%s]\n", depth, " ", node->GetName())); DebuggerPrintf("%*sNode [%s]\n", depth, " ", node->GetName()); for (int i = 0; i < node->GetNodeAttributeCount(); ++i) { PrintAttribute(node->GetNodeAttributeByIndex(i), depth); } for (int i = 0; i < node->GetChildCount(); ++i) { PrintNode(node->GetChild(i), depth + 1); } }
bool SetGameState(GameState newState) { if (m_state != newState) { DebuggerPrintf("Changed State from %s to %s", GetStateString(m_state), GetStateString(newState)); m_state = newState; return true; } else { ERROR_RECOVERABLE("State machine was set to the same state."); return false; } }
//----------------------------------------------------------------------------------- static void PrintAttribute(FbxNodeAttribute* attribute, int depth) { if (attribute == nullptr) { return; } FbxNodeAttribute::EType type = attribute->GetAttributeType(); const char* typeName = GetAttributeTypeName(type); const char* attribName = attribute->GetName(); Console::instance->PrintLine(Stringf("%*s- type='%s', name='%s'\n", depth, " ", typeName, attribName)); DebuggerPrintf("%*s- type='%s', name='%s'\n", depth, " ", typeName, attribName); }
//----------------------------------------------------------------------------------- void MemoryMetadata::PrintAllMetadataInList() { if (!g_memoryMetadataList) { DebuggerPrintf("Metadata list was null, nothing to print. (Are you not running in verbose mode?)\n"); return; } MemoryMetadata* currentNode = g_memoryMetadataList; int callstackListIndex = -1; do { Callstack* callstack = currentNode->callstack; CallstackLine* callstackLines = CallstackGetLines(callstack); DebuggerPrintf("---===Allocation #%i===---\n>>>Size: %i bytes\n", ++callstackListIndex, currentNode->sizeOfAllocInBytes); DebuggerPrintf(">>>Callstack:\n//-----------------------------------------------------------------------------------\n"); for (unsigned int i = 0; i < callstack->frameCount; ++i) { DebuggerPrintf("%s(%i): %s\n", callstackLines[i].filename, callstackLines[i].line, callstackLines[i].functionName); } currentNode = currentNode->next; DebuggerPrintf("//-----------------------------------------------------------------------------------\n\n", callstackListIndex); } while (currentNode != g_memoryMetadataList); }
IntVector2 Map::GetLocationWithOpeningOnEitherSide() { std::vector<Tile*> allStoneTilesOnMap; for (int x = 0; x < m_size.x; x++) { for (int y = 0; y < m_size.y; y++) { IntVector2 loc = IntVector2(x, y); Tile* currTile = GetTileAtLocation(loc); if (currTile->GetCurrentTileType() == TILE_STONE) { allStoneTilesOnMap.push_back(currTile); } } } int numTimesRan = 0; bool b = true; while (b) { int which = RandIntZeroToSize(allStoneTilesOnMap.size()); Tile*& currTile = allStoneTilesOnMap[which]; IntVector2 loc = currTile->GetLocation(); Tile* tileToLeft = GetTileAtLocation(loc + WEST); Tile* tileToRight = GetTileAtLocation(loc + EAST); Tile* tileToUp = GetTileAtLocation(loc + NORTH); Tile* tileToDown = GetTileAtLocation(loc + SOUTH); if (tileToLeft && tileToRight && tileToLeft->IsValid() && tileToRight->IsValid()) { return loc; } else if (tileToUp && tileToDown && tileToUp->IsValid() && tileToDown->IsValid()) { return loc; } if (numTimesRan > 10000) { DebuggerPrintf("ERROR: Find Random Valid Location running too long."); return IntVector2(0, 0); } numTimesRan++; } return IntVector2(0, 0); }
//----------------------------------------------------------------------------------- void* MemoryAnalytics::Allocate(const size_t numBytes) { MemoryMetadata* metadata = UntrackedNew<MemoryMetadata>(); const size_t real_size = sizeof(size_t) + numBytes; size_t* ptr = (size_t*) ::malloc(real_size); metadata->sizeOfAllocInBytes = numBytes; #if (TRACK_MEMORY > 0) { Callstack* callstackPtr = AllocateCallstack(); metadata->callstack = callstackPtr; } #endif #if (TRACK_MEMORY == 2) { DebuggerPrintf("New called for %lu bytes. Pointer: %p\n", numBytes, ptr); } #endif //Save off the metadata so that we know how much memory to free later *ptr = (size_t)metadata; ++ptr; //THIS IS THE PART THAT NEEDS TO BE THREAD-SAFE AttemptLock(); { ++m_numberOfAllocations; m_numberOfBytes += numBytes; if (m_numberOfBytes > m_highwaterInBytes) { m_highwaterInBytes = m_numberOfBytes; } #if (TRACK_MEMORY > 0) //Add to map MemoryMetadata::AddMemoryMetadataToList(metadata); #endif // TRACK_MEMORY > 0 } AttemptLeave(); return ptr; // BONUS MATERIAL // Track average allocations and size per second as well }
//--------------------------------------------------------------------------------------------------------------------------- //USING //--------------------------------------------------------------------------------------------------------------------------- void Feature::Toggle() { switch (m_featureType) { case FEATURE_TYPE_DOOR: if (m_featureState == FEATURE_STATE_ACTIVATED) { m_featureState = FEATURE_STATE_DEACTIVATED; LogActivation(); } else if (m_featureState == FEATURE_STATE_DEACTIVATED) { m_featureState = FEATURE_STATE_ACTIVATED; LogDeactivation(); } else { DebuggerPrintf("WARNING: Door is in a state not activated or deactivated"); } break; default: break; } }
void AudioSystem::ValidateResult(FMOD_RESULT result) { if (result != FMOD_OK) { DebuggerPrintf("AUDIO SYSTEM ERROR: Got error result code %d.\n", result); __debugbreak(); } }
//--------------------------------------------------------------------------- // FMOD startup code based on "GETTING STARTED With FMOD Ex Programmer’s API for Windows" document // from the FMOD programming API at http://www.fmod.org/download/ // void AudioSystem::InitializeFMOD() { const int MAX_AUDIO_DEVICE_NAME_LEN = 256; FMOD_RESULT result; unsigned int fmodVersion; int numDrivers; FMOD_SPEAKERMODE speakerMode; FMOD_CAPS deviceCapabilities; char audioDeviceName[MAX_AUDIO_DEVICE_NAME_LEN]; // Create a System object and initialize. result = FMOD::System_Create(&m_fmodSystem); ValidateResult(result); result = m_fmodSystem->getVersion(&fmodVersion); ValidateResult(result); if (fmodVersion < FMOD_VERSION) DebuggerPrintf("AUDIO SYSTEM ERROR! Your FMOD .dll is of an older version (0x%08x == %d) than that the .lib used to compile this code (0x%08x == %d).\n", fmodVersion, fmodVersion, FMOD_VERSION, FMOD_VERSION); result = m_fmodSystem->getNumDrivers(&numDrivers); ValidateResult(result); if (numDrivers == 0) { result = m_fmodSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND); ValidateResult(result); } else { result = m_fmodSystem->getDriverCaps(0, &deviceCapabilities, 0, &speakerMode); ValidateResult(result); // Set the user selected speaker mode. result = m_fmodSystem->setSpeakerMode(speakerMode); ValidateResult(result); if (deviceCapabilities & FMOD_CAPS_HARDWARE_EMULATED) { // The user has the 'Acceleration' slider set to off! This is really bad // for latency! You might want to warn the user about this. result = m_fmodSystem->setDSPBufferSize(1024, 10); ValidateResult(result); } result = m_fmodSystem->getDriverInfo(0, audioDeviceName, MAX_AUDIO_DEVICE_NAME_LEN, 0); ValidateResult(result); if (strstr(audioDeviceName, "SigmaTel")) { // Sigmatel sound devices crackle for some reason if the format is PCM 16bit. // PCM floating point output seems to solve it. result = m_fmodSystem->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); ValidateResult(result); } } result = m_fmodSystem->init(100, FMOD_INIT_NORMAL, 0); if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) { // Ok, the speaker mode selected isn't supported by this sound card. Switch it // back to stereo... result = m_fmodSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); ValidateResult(result); // ... and re-init. result = m_fmodSystem->init(100, FMOD_INIT_NORMAL, 0); ValidateResult(result); } }
//----------------------------------------------------------------------------------------------- void RecoverableWarning( const char* filePath, const char* functionName, int lineNum, const std::string& reasonForWarning, const char* conditionText ) { std::string errorMessage = reasonForWarning; if( reasonForWarning.empty() ) { if( conditionText ) errorMessage = Stringf( "WARNING: \"%s\" is false!", conditionText ); else errorMessage = "Unspecified warning"; } const char* fileName = FindStartOfFileNameWithinFilePath( filePath ); // std::string appName = theApplication ? theApplication->GetApplicationName() : "Unnamed Application"; std::string appName = "Unnamed Application"; std::string fullMessageTitle = appName + " :: Warning"; std::string fullMessageText = errorMessage; bool isDebuggerPresent = (IsDebuggerPresent() == TRUE); if( isDebuggerPresent ) { fullMessageText += "\n\nDEBUGGER DETECTED!\nWould you like to continue running?\n (Yes=continue, No=quit, Cancel=debug)\n"; } else { fullMessageText += "\n\nWould you like to continue running?\n (Yes=continue, No=quit)\n"; } fullMessageText += "\n---------- Debugging Details Follow ----------\n"; if( conditionText ) { fullMessageText += Stringf( "\nThis warning was triggered by a run-time condition check:\n %s\n from %s(), line %i in %s\n", conditionText, functionName, lineNum, fileName ); } else { fullMessageText += Stringf( "\nThis was an unconditional warning triggered by reaching\n line %i of %s, in %s()\n", lineNum, fileName, functionName ); } DebuggerPrintf( "\n------------------------------------------------------------------------------\n" ); DebuggerPrintf( "RUN-TIME RECOVERABLE WARNING on line %i of %s, in %s()\n", lineNum, fileName, functionName ); DebuggerPrintf( "%s(%d): %s\n", filePath, lineNum, errorMessage.c_str() ); // Use this specific format so Visual Studio users can double-click to jump to file-and-line of error DebuggerPrintf( "------------------------------------------------------------------------------\n\n" ); if( isDebuggerPresent ) { int answerCode = SystemDialogue_YesNoCancel( fullMessageTitle, fullMessageText, SEVERITY_WARNING ); ShowCursor( TRUE ); if( answerCode == 0 ) // "NO" { exit( 0 ); } else if( answerCode == -1 ) // "CANCEL" { __debugbreak(); } } else { bool isAnswerYes = SystemDialogue_YesNo( fullMessageTitle, fullMessageText, SEVERITY_WARNING ); ShowCursor( TRUE ); if( !isAnswerYes ) { exit( 0 ); } } }
//----------------------------------------------------------------------------------------------- void ScenarioStartFunction_Claustrophobia( Scenario& scenario ) { DebuggerPrintf( "Starting scenario '%s'...\n", scenario.m_name.c_str() ); //1024x576 Actor *player=new Actor(); player->m_position = Vector2(100, 576/2); player->m_isPlayer = true; player->m_baseColor = Rgba::BLUE; scenario.m_actors.push_back( player ); for(int i = 0; i < 11; i++) { for(int j = 0; j < 9; j++) { AC(a, (1024/2)-(i-5)*50, (576/2)+(j-4)*30+(i%2*16)); } } for(int i = 0; i < scenario.m_actors.size(); i++) { Actor *a = scenario.m_actors[i]; RelationshipToOtherActor dontBumpA; dontBumpA.m_innerDistance = 0; dontBumpA.m_outerDistance = 20; dontBumpA.m_attractionRepulsionAtOuterDistance = Vector2(0,0); dontBumpA.m_attractionRepulsionAtInnerDistance = Vector2(-5,-5); dontBumpA.m_otherActor = a; for(int j = 0; j < scenario.m_actors.size(); j++) { if(i == j) { continue; } Actor *b = scenario.m_actors[j]; b->m_relationships.push_back(dontBumpA); } } AR(ar1, 0, 100, 1024, 376); Area* lWall = new Area; lWall->m_bounds.SetFromMinXYMaxXY( 0, 100, 10, 576-100); lWall->m_color = Rgba::DARKGREY; lWall->m_alpha = 1.f; lWall->m_impassableToNPC = true; lWall->m_impassableToPlayer = true; lWall->m_deepShadow = false; scenario.m_areas.push_back( lWall ); Area* rWall = new Area; rWall->m_bounds.SetFromMinXYMaxXY( 1014, 10, 1024, 576-100 ); rWall->m_color = Rgba::DARKGREY; rWall->m_alpha = 1.f; rWall->m_impassableToNPC = true; rWall->m_impassableToPlayer = true; rWall->m_deepShadow = false; scenario.m_areas.push_back( rWall ); Area* tWall = new Area; tWall->m_bounds.SetFromMinXYMaxXY( 0, 100, 1024, 100 ); tWall->m_color = Rgba::DARKGREY; tWall->m_alpha = 1.f; tWall->m_impassableToNPC = true; tWall->m_impassableToPlayer = true; tWall->m_deepShadow = false; scenario.m_areas.push_back( tWall ); Area* bWall = new Area; bWall->m_bounds.SetFromMinXYMaxXY( 0, 576-100, 1024, 576-100 ); bWall->m_color = Rgba::DARKGREY; bWall->m_alpha = 1.f; bWall->m_impassableToNPC = true; bWall->m_impassableToPlayer = true; bWall->m_deepShadow = false; scenario.m_areas.push_back( bWall ); Area *pGoal=new Area(); pGoal->m_bounds.SetFromMinXYMaxXY( 928, 576/2-64, 1024, 576/2+64 ); pGoal->m_color = Rgba::WHITE; pGoal->m_alpha = 1.0f; scenario.m_areas.push_back( pGoal ); }
//----------------------------------------------------------------------------------- void MemoryAnalytics::Shutdown() { m_isInitialized = false; CallstackSystemDeinit(); DebuggerPrintf("Number of allocations at shutdown: %i. Total size: %luB\n", m_numberOfAllocations, m_numberOfBytes); }