/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "CryLegacy_precompiled.h" #include "ActionController.h" #include "MannequinDebug.h" #include "IAIObject.h" ////////////////////////////////////////////////////////////////////////// static void MN_ReloadAll(IConsoleCmdArgs* pArgs) { CCryAction::GetCryAction()->GetMannequinInterface().ReloadAll(); } struct SAnimAssetContext { XmlNodeRef xmlRoot; const IAnimationDatabase* pDatabase; }; void AssetCallback(const SAnimAssetReport& assetReport, void* _context) { SAnimAssetContext* pContext = (SAnimAssetContext*)_context; XmlNodeRef xmlAnim = GetISystem()->CreateXmlNode("Anim"); if (assetReport.pAnimName != NULL) { xmlAnim->setAttr("AnimID", assetReport.pAnimName); } if (assetReport.pAnimPath != NULL) { xmlAnim->setAttr("AnimPath", assetReport.pAnimPath); } pContext->xmlRoot->addChild(xmlAnim); } ////////////////////////////////////////////////////////////////////////// static void MN_ListAssets(IConsoleCmdArgs* pArgs) { const char* filename = "@LOG@/mannequinAnimationAssetUsage.xml"; if (pArgs->GetArgCount() >= 2) { filename = pArgs->GetArg(1); } SAnimAssetContext context; context.xmlRoot = GetISystem()->CreateXmlNode("UsedAnims"); IAnimationDatabaseManager& dbManager = CCryAction::GetCryAction()->GetMannequinInterface().GetAnimationDatabaseManager(); const int numDBAs = dbManager.GetTotalDatabases(); for (int i = 0; i < numDBAs; i++) { const IAnimationDatabase* pDatabase = dbManager.GetDatabase(i); context.pDatabase = pDatabase; pDatabase->EnumerateAnimAssets(NULL, AssetCallback, &context); } context.xmlRoot->saveToFile(filename); } ////////////////////////////////////////////////////////////////////////// static void MN_DebugAI(IConsoleCmdArgs* pArgs) { const IEntity* pDebugEntity = NULL; if (2 <= pArgs->GetArgCount()) { const char* const entityName = pArgs->GetArg(1); pDebugEntity = gEnv->pEntitySystem->FindEntityByName(entityName); } else { const CCamera& viewCamera = gEnv->pSystem->GetViewCamera(); const Matrix34& viewCameraMatrix = viewCamera.GetMatrix(); const Vec3 cameraWorldPosition = viewCameraMatrix.GetTranslation(); const Vec3 cameraWorldDirectionForward = viewCameraMatrix.GetColumn1().GetNormalized(); float highestDotProduct = -2.0f; const CActionController::TActionControllerList& actionControllersList = CActionController::GetGlobalActionControllers(); for (size_t i = 0; i < actionControllersList.size(); ++i) { const CActionController* pActionController = actionControllersList[ i ]; CRY_ASSERT(pActionController); const AZ::EntityId entityId = pActionController->GetEntityId(); if (IsLegacyEntityId(entityId)) { if (entityId == AZ::EntityId(0)) { continue; } } else { if (!entityId.IsValid()) { continue; } } IEntity& entity = pActionController->GetEntity(); const IAIObject* pAiObject = entity.GetAI(); const Vec3 entityWorldPosition = pAiObject ? pAiObject->GetPos() : entity.GetWorldPos(); const Vec3 cameraToEntityWorldDirection = (entityWorldPosition - cameraWorldPosition).GetNormalized(); const float dotProduct = cameraWorldDirectionForward.Dot(cameraToEntityWorldDirection); if ((highestDotProduct < dotProduct) && pAiObject) { pDebugEntity = &entity; highestDotProduct = dotProduct; } } } stack_string oldDebugEntityName = ""; { const ICVar* const pMNDebugCVar = gEnv->pConsole->GetCVar("mn_debug"); const char* const mnDebugEntityName = (pMNDebugCVar ? pMNDebugCVar->GetString() : NULL); oldDebugEntityName = (mnDebugEntityName) ? mnDebugEntityName : ""; } const bool wasEnabled = !(oldDebugEntityName.empty()); if (wasEnabled) { // Turn Off gEnv->pConsole->ExecuteString("i_forcefeedback 1"); gEnv->pConsole->ExecuteString("c_shakeMult 1"); gEnv->pConsole->ExecuteString("pl_health.minimalHudEffect 0"); //gEnv->pConsole->ExecuteString( "r_PostProcessEffects 1"); <-- this crashes in certain levels gEnv->pConsole->ExecuteString("ai_debugdraw 0"); gEnv->pConsole->ExecuteString("ac_debugLocations 0"); gEnv->pConsole->ExecuteString("ai_drawpathfollower 0"); gEnv->pConsole->ExecuteString("ca_drawlocator 0"); gEnv->pConsole->ExecuteString("ac_debugfilter 0"); gEnv->pConsole->ExecuteString("ai_filteragentname \"\""); { stack_string cmd; cmd.Format("es_debugAnim %s 0", oldDebugEntityName.c_str()); gEnv->pConsole->ExecuteString(cmd.c_str()); } gEnv->pConsole->ExecuteString("mn_debug 0"); } if (!pDebugEntity) { return; } const bool sameDebugEntity = wasEnabled && !strcmp(oldDebugEntityName.c_str(), pDebugEntity->GetName()); if (!sameDebugEntity) { // Turn On gEnv->pConsole->ExecuteString("i_forcefeedback 0"); gEnv->pConsole->ExecuteString("c_shakeMult 0"); gEnv->pConsole->ExecuteString("pl_health.minimalHudEffect 1"); //gEnv->pConsole->ExecuteString( "r_PostProcessEffects 0"); <-- disabled this as re-enabling it crashes in certain levels gEnv->pConsole->ExecuteString("ai_debugdraw 1"); gEnv->pConsole->ExecuteString("ac_debugLocations 2"); gEnv->pConsole->ExecuteString("ai_drawpathfollower 1"); gEnv->pConsole->ExecuteString("ca_drawlocator 1"); { stack_string cmd; cmd.Format("ac_debugFilter %s", pDebugEntity->GetName()); gEnv->pConsole->ExecuteString(cmd.c_str()); } { stack_string cmd; cmd.Format("ai_filteragentname %s", pDebugEntity->GetName()); gEnv->pConsole->ExecuteString(cmd.c_str()); } { stack_string cmd; cmd.Format("es_debugAnim %s 1", pDebugEntity->GetName()); gEnv->pConsole->ExecuteString(cmd.c_str()); } { stack_string cmd; cmd.Format("mn_debug %s", pDebugEntity->GetName()); gEnv->pConsole->ExecuteString(cmd.c_str()); } } } namespace mannequin { namespace debug { static int mn_logToFile = 1; ////////////////////////////////////////////////////////////////////////// void RegisterCommands() { REGISTER_COMMAND("mn_reload", MN_ReloadAll, VF_CHEAT, "Reloads animation databases"); REGISTER_COMMAND("mn_listAssets", MN_ListAssets, VF_CHEAT, "Lists all the currently referenced animation assets"); REGISTER_COMMAND("mn_DebugAI", MN_DebugAI, VF_CHEAT, ""); REGISTER_CVAR3("mn_LogToFile", mn_logToFile, 0, VF_CHEAT, "Dumps all mann event logging to the file"); } #if MANNEQUIN_DEBUGGING_ENABLED static const int maxSavedMsgs = 10; enum ESavedMsgType { SMT_WARNING, SMT_ERROR }; struct SSavedMsg { ESavedMsgType savedMsgType; char savedMsg[MAX_WARNING_LENGTH]; uint32 renderFrame; bool isNew; bool isUsed; }; static SSavedMsg savedMsgs[maxSavedMsgs]; static int savedMsgIndex = 0; static int lastRenderFrame = 0; //==================================================================== // MannLog //==================================================================== void Log(const IActionController& actionControllerI, const char* format, ...) { const CActionController& actionController = (const CActionController&)actionControllerI; char outputBufferLog[MAX_WARNING_LENGTH]; const uint32 outputBufferSize = sizeof(outputBufferLog); va_list args; va_start(args, format); azvsnprintf(outputBufferLog, outputBufferSize, format, args); outputBufferLog[outputBufferSize - 1] = '\0'; va_end(args); if (mn_logToFile) { gEnv->pSystem->Warning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, 0, 0, "Mann: %s", outputBufferLog); } if (actionController.GetFlag(AC_DebugDraw)) { savedMsgs[savedMsgIndex].savedMsgType = SMT_WARNING; cry_strcpy(savedMsgs[savedMsgIndex].savedMsg, outputBufferLog); savedMsgs[savedMsgIndex].renderFrame = gEnv->pRenderer->GetFrameID(); savedMsgs[savedMsgIndex].isNew = true; savedMsgs[savedMsgIndex].isUsed = true; savedMsgIndex = (savedMsgIndex + 1) % maxSavedMsgs; } } void DrawDebug() { const ColorF fNew(1.0f, 1.0f, 1.0f, 1.0f); const ColorF fOld(0.6f, 0.6f, 0.6f, 1.0f); const float xPosOrigin = 900.0f; const float yPosOrigin = 300.0f; static float fontSize = 1.2f; const uint32 renderFrame = gEnv->pRenderer->GetFrameID(); float xPos = xPosOrigin; float yPos = yPosOrigin; for (uint32 i = savedMsgIndex; i < maxSavedMsgs; i++) { if (savedMsgs[i].isUsed) { const ColorF& drawCol = (savedMsgs[i].isNew) ? fNew : fOld; gEnv->pRenderer->Draw2dLabel(xPos, yPos, fontSize, drawCol, false, "%s", savedMsgs[i].savedMsg); savedMsgs[i].isNew = false; yPos += 20.0f; } } for (uint32 i = 0; i < savedMsgIndex; i++) { if (savedMsgs[i].isUsed) { const ColorF& drawCol = (savedMsgs[i].isNew) ? fNew : fOld; gEnv->pRenderer->Draw2dLabel(xPos, yPos, fontSize, drawCol, false, "%s", savedMsgs[i].savedMsg); savedMsgs[i].isNew = false; yPos += 20.0f; } } lastRenderFrame = renderFrame; } #endif //!MANNEQUIN_DEBUGGING_ENABLED } }