BVB Source Codes

CRYENGINE Show ManualFrameStep.cpp Source code

Return Download CRYENGINE: download ManualFrameStep.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "ManualFrameStep.h"
  5.  
  6. #if MANUAL_FRAME_STEP_ENABLED
  7.  
  8.         #include "Network/GameClientChannel.h"
  9.         #include "Network/GameClientNub.h"
  10.         #include "Network/GameServerChannel.h"
  11.         #include "Network/GameServerNub.h"
  12.  
  13.         #if CRY_PLATFORM_WINDOWS
  14.                 #define MANUAL_FRAME_STEP_VIEW_HISTORY 1
  15.         #else
  16.                 #define MANUAL_FRAME_STEP_VIEW_HISTORY 0
  17.         #endif
  18.  
  19.         #if MANUAL_FRAME_STEP_VIEW_HISTORY
  20.                 #include <CryCore/Platform/CryWindows.h>
  21.         #endif
  22.  
  23. /*static*/ void CManualFrameStepController::SCVars::Register()
  24. {
  25.         REGISTER_CVAR2("g_manualFrameStepFrequency", &manualFrameStepFrequency, 60.0f, VF_NET_SYNCED, "Manually step through frames with a fixed time step");
  26. }
  27.  
  28. /*static*/ void CManualFrameStepController::SCVars::Unregister()
  29. {
  30.         if (gEnv->pConsole)
  31.         {
  32.                 gEnv->pConsole->UnregisterVariable("g_manualFrameStepFrequency", true);
  33.         }
  34. }
  35.  
  36. float CManualFrameStepController::SCVars::manualFrameStepFrequency = 0.0f;
  37.  
  38. //////////////////////////////////////////////////////////////////////////
  39.  
  40. CManualFrameStepController::CManualFrameStepController()
  41.         : m_framesLeft(-1)
  42.         , m_framesGenerated(0)
  43.         , m_pendingRequest(false)
  44.         , m_previousStepSmoothing(true)
  45.         , m_previousFixedStep(0.0f)
  46.         , m_heldTimer(-1.0f)
  47. {
  48.         if (gEnv->pInput)
  49.         {
  50.                 gEnv->pInput->AddEventListener(this);
  51.         }
  52.  
  53.         SCVars::Register();
  54. }
  55.  
  56. CManualFrameStepController::~CManualFrameStepController()
  57. {
  58.         if (gEnv->pInput)
  59.         {
  60.                 gEnv->pInput->RemoveEventListener(this);
  61.         }
  62.  
  63.         SCVars::Unregister();
  64. }
  65.  
  66. EManualFrameStepResult CManualFrameStepController::Update()
  67. {
  68.         const EManualFrameStepResult result = (m_framesLeft != 0) ? EManualFrameStepResult::Continue : EManualFrameStepResult::Block;
  69.  
  70.         if (m_framesLeft > 0)
  71.         {
  72.                 --m_framesLeft;
  73.                 ++m_framesGenerated;
  74.  
  75.                 DisplayDebugInfo();
  76.         }
  77.  
  78.         if (result == EManualFrameStepResult::Block)
  79.         {
  80.                 // Manually update core systems which have to be ticked even when blocking the main loop
  81.                 if (gEnv->pInput)
  82.                 {
  83.                         gEnv->pInput->Update(true);
  84.                 }
  85.  
  86.                 if (gEnv->pNetwork)
  87.                 {
  88.                         gEnv->pNetwork->SyncWithGame(eNGS_FrameStart);
  89.                         gEnv->pNetwork->SyncWithGame(eNGS_FrameEnd);
  90.                 }
  91.  
  92.                 if (!gEnv->IsEditor() && gEnv->pRenderer)
  93.                 {
  94.                         gEnv->pSystem->PumpWindowMessage(true, gEnv->pRenderer->GetHWND());
  95.                 }
  96.         }
  97.         else if (m_pendingRequest)
  98.         {
  99.                 m_pendingRequest = false;
  100.         }
  101.  
  102.         return result;
  103. }
  104.  
  105. void CManualFrameStepController::DefineProtocol(IProtocolBuilder* pBuilder)
  106. {
  107.         pBuilder->AddMessageSink(this, GetProtocolDef(), GetProtocolDef());
  108. }
  109.  
  110. NET_IMPLEMENT_SIMPLE_ATSYNC_MESSAGE(CManualFrameStepController, OnNetworkMessage, eNRT_ReliableOrdered, eMPF_NoSendDelay)
  111. {
  112.         ProcessCommand(param.numFrames);
  113.  
  114.         return true;
  115. }
  116.  
  117. bool CManualFrameStepController::IsEnabled() const
  118. {
  119.         return m_framesLeft >= 0;
  120. }
  121.  
  122. void CManualFrameStepController::Enable(const bool enable)
  123. {
  124.         if (IsEnabled() && enable)
  125.         {
  126.                 // Already enabled: early out
  127.                 return;
  128.         }
  129.  
  130.         m_framesLeft = enable ? 0 : -1;
  131.         m_framesGenerated = 0;
  132.  
  133.         // Set fixed step
  134.         if (ICVar* const pFixedStep = gEnv->pConsole->GetCVar("t_FixedStep"))
  135.         {
  136.                 if (enable)
  137.                 {
  138.                         m_previousFixedStep = pFixedStep->GetFVal();
  139.                         pFixedStep->Set(1.0f / SCVars::manualFrameStepFrequency);
  140.                 }
  141.                 else
  142.                 {
  143.                         pFixedStep->Set(m_previousFixedStep);
  144.                 }
  145.         }
  146.  
  147.         // Disable framerate smoothing
  148.         if (ICVar* const pSmoothing = gEnv->pConsole->GetCVar("t_Smoothing"))
  149.         {
  150.                 if (enable)
  151.                 {
  152.                         m_previousStepSmoothing = (pSmoothing->GetIVal() != 0);
  153.                         pSmoothing->Set(false);
  154.                 }
  155.                 else
  156.                 {
  157.                         pSmoothing->Set(m_previousStepSmoothing);
  158.                 }
  159.         }
  160.  
  161.         // And capture output folder
  162.         stack_string framesFolder;
  163.         GetFramesFolder(framesFolder);
  164.  
  165.         if (!gEnv->IsDedicated())
  166.         {
  167.                 if (ICVar* const pCaptureFrames = gEnv->pConsole->GetCVar("capture_frames"))
  168.                 {
  169.                         if (ICVar* const pCaptureFramesFolder = gEnv->pConsole->GetCVar("capture_folder"))
  170.                         {
  171.                                 if (enable)
  172.                                 {
  173.                                         pCaptureFramesFolder->Set(framesFolder.c_str());
  174.                                         pCaptureFrames->Set(1);
  175.                                 }
  176.                                 else
  177.                                 {
  178.                                         pCaptureFramesFolder->Set("CaptureOutput");
  179.                                         pCaptureFrames->Set(0);
  180.                                 }
  181.                         }
  182.                 }
  183.         }
  184. }
  185.  
  186. void CManualFrameStepController::GenerateRequest(const uint8 numFrames)
  187. {
  188.         if (gEnv->bServer)
  189.         {
  190.                 // Process and sync to clients
  191.                 ProcessCommand(numFrames);
  192.         }
  193.         else
  194.         {
  195.                 SNetMessage netMessage(numFrames);
  196.                 NetRequestStepToServer(netMessage);
  197.         }
  198. }
  199.  
  200. void CManualFrameStepController::ProcessCommand(const uint8 numFrames)
  201. {
  202.         switch (numFrames)
  203.         {
  204.         case kDisableMask:
  205.                 Enable(false);
  206.                 break;
  207.         case kEnableMask:
  208.                 Enable(true);
  209.                 DisplayDebugInfo();
  210.                 break;
  211.         default:
  212.                 Enable(true);
  213.                 m_framesLeft += numFrames;
  214.                 break;
  215.         }
  216.  
  217.         SNetMessage netMessage(numFrames);
  218.         NetSyncClients(netMessage);
  219. }
  220.  
  221. void CManualFrameStepController::NetSyncClients(const SNetMessage& netMessage)
  222. {
  223.         if (gEnv->bMultiplayer && gEnv->bServer)
  224.         {
  225.                 if (CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub())
  226.                 {
  227.                         if (TServerChannelMap* pChanneMap = pServerNub->GetServerChannelMap())
  228.                         {
  229.                                 INetSendablePtr pNetMessage = new CSimpleNetMessage<SNetMessage>(netMessage, CManualFrameStepController::OnNetworkMessage);
  230.  
  231.                                 for (TServerChannelMap::iterator iter = pChanneMap->begin(); iter != pChanneMap->end(); ++iter)
  232.                                 {
  233.                                         INetChannel* pNetChannel = iter->second->GetNetChannel();
  234.                                         if ((pNetChannel != nullptr) && (pNetChannel != pServerNub->GetLocalChannel()))
  235.                                         {
  236.                                                 pNetChannel->AddSendable(pNetMessage, 0, NULL, NULL);
  237.  
  238.                                                 CryLog("[ManualFrameStepController] Client Sync sent. Frames = %u", netMessage.numFrames);
  239.                                         }
  240.                                 }
  241.                         }
  242.                 }
  243.         }
  244. }
  245.  
  246. void CManualFrameStepController::NetRequestStepToServer(const SNetMessage& netMessage)
  247. {
  248.         if (!gEnv->bServer)
  249.         {
  250.                 if (CGameClientNub* pClientNub = CCryAction::GetCryAction()->GetGameClientNub())
  251.                 {
  252.                         if (CGameClientChannel* pGameClientChannel = pClientNub->GetGameClientChannel())
  253.                         {
  254.                                 INetSendablePtr pNetMessage = new CSimpleNetMessage<SNetMessage>(netMessage, CManualFrameStepController::OnNetworkMessage);
  255.                                 pGameClientChannel->GetNetChannel()->AddSendable(pNetMessage, 0, NULL, NULL);
  256.                         }
  257.                 }
  258.         }
  259. }
  260.  
  261. bool CManualFrameStepController::OnInputEvent(const SInputEvent& inputEvent)
  262. {
  263.         if ((SCVars::manualFrameStepFrequency < FLT_EPSILON) || (eIDT_Keyboard != inputEvent.deviceType))
  264.                 return false;
  265.  
  266.         const float kKeyHeldThreshold = 0.5f;
  267.  
  268.         switch (inputEvent.keyId)
  269.         {
  270.         case eKI_Pause:
  271.                 if ((eIS_Pressed == inputEvent.state) && (inputEvent.modifiers & eMM_Shift))
  272.                 {
  273.                         GenerateRequest(IsEnabled() ? kDisableMask : kEnableMask);
  274.                 }
  275.                 break;
  276.         case eKI_Right:
  277.                 if (IsEnabled())
  278.                 {
  279.                         if (eIS_Released == inputEvent.state)
  280.                         {
  281.                                 m_heldTimer = -1.0f;
  282.                         }
  283.                         else if (eIS_Down == inputEvent.state)
  284.                         {
  285.                                 const float currTime = gEnv->pSystem->GetITimer()->GetAsyncTime().GetSeconds();
  286.                                 if (m_heldTimer < 0.0f)
  287.                                 {
  288.                                         GenerateRequest(1);
  289.                                         m_heldTimer = currTime;
  290.                                 }
  291.                                 else if (((currTime - m_heldTimer) >= kKeyHeldThreshold) && !m_framesLeft)
  292.                                 {
  293.                                         // Defer "held" requests in order to stay in sync with the server.
  294.                                         // We don't want to send more commands than the server can process
  295.                                         if (!m_pendingRequest)
  296.                                         {
  297.                                                 GenerateRequest(1);
  298.                                         }
  299.                                         m_pendingRequest = true;
  300.                                 }
  301.                         }
  302.                 }
  303.                 break;
  304.         #if MANUAL_FRAME_STEP_VIEW_HISTORY
  305.         case eKI_Left:
  306.                 {
  307.                         // Open last generated frames
  308.                         if (IsEnabled() && eIS_Pressed == inputEvent.state)
  309.                         {
  310.                                 const ICVar* const pCaptureFormat = gEnv->pConsole->GetCVar("capture_file_format");
  311.                                 const char* szFileFormat = pCaptureFormat ? pCaptureFormat->GetString() : "jpg";
  312.  
  313.                                 const ICVar* const pUserPrefix = gEnv->pConsole->GetCVar("capture_file_prefix");
  314.                                 const char* szUserPrefix = pUserPrefix ? pUserPrefix->GetString() : "";
  315.                                 const char* szRealPrefix = szUserPrefix[0] ? szUserPrefix : "Frame";
  316.  
  317.                                 const stack_string& lastFrameName = stack_string().Format("%s%06d.%s", szRealPrefix, m_framesGenerated, szFileFormat);
  318.  
  319.                                 stack_string framesFolder;
  320.                                 GetFramesFolder(framesFolder);
  321.  
  322.                                 char buffer[ICryPak::g_nMaxPath];
  323.                                 const char* szAdjustedFramesFolder = gEnv->pCryPak->AdjustFileName(framesFolder.c_str(), buffer, ICryPak::FLAGS_FOR_WRITING);
  324.  
  325.                                 char szBuffer[MAX_PATH + 256];
  326.                                 cry_sprintf(szBuffer, "explorer.exe %s\\%s", szAdjustedFramesFolder, lastFrameName.c_str());
  327.  
  328.                                 STARTUPINFO startupInfo;
  329.                                 ZeroMemory(&startupInfo, sizeof(startupInfo));
  330.                                 startupInfo.cb = sizeof(startupInfo);
  331.  
  332.                                 PROCESS_INFORMATION processInformation;
  333.                                 ZeroMemory(&processInformation, sizeof(processInformation));
  334.  
  335.                                 CreateProcess(NULL, szBuffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation);
  336.                         }
  337.                         break;
  338.                 }
  339.         #endif // MANUAL_FRAME_STEP_VIEW_HISTORY
  340.         }
  341.  
  342.         return false;
  343. }
  344.  
  345. /*static*/ void CManualFrameStepController::GetFramesFolder(stack_string& outFolder)
  346. {
  347.         outFolder = "%USER%/ManualStepFrames_";
  348.         if (IEntity* const pClientEntity = gEnv->pGameFramework->GetClientEntity())
  349.         {
  350.                 outFolder.append(pClientEntity->GetName());
  351.         }
  352.         else
  353.         {
  354.                 outFolder.append("Default");
  355.         }
  356. }
  357.  
  358. /*static*/ void CManualFrameStepController::DisplayDebugInfo()
  359. {
  360.         if (gEnv->pRenderer)
  361.         {
  362.                 int viewX, viewY, width, height;
  363.                 gEnv->pRenderer->GetViewport(&viewX, &viewY, &width, &height);
  364.  
  365.                 float x = float(viewX) + float(width / 2) - 110.0f;
  366.                 float y = float(viewY) + float(height) - 70.0f;
  367.  
  368.                 IRenderAuxText::Draw2dLabel(x, y, 2.0f, Col_Red, false, "ManualFrameStep active");
  369.                 x += 25.0f;
  370.                 y += 20.0f;
  371.  
  372.                 IRenderAuxText::Draw2dLabel(x, y, 1.3f, Col_White, false, "'Shift+Pause' to toggle");
  373.                 y += 12.0f;
  374.  
  375.                 IRenderAuxText::Draw2dLabel(x, y, 1.3f, Col_White, false, "'Right' to generate a new frame");
  376.                 y += 12.0f;
  377.  
  378.                 IRenderAuxText::Draw2dLabel(x, y, 1.3f, Col_White, false, "'Left' to view history");
  379.                 y += 12.0f;
  380.         }
  381. }
  382.  
  383. #endif // MANUAL_FRAME_STEP_ENABLED
  384.  
downloadManualFrameStep.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top