예제 #1
0
void VAppBase::Execute(VAppImpl* pImpl)
{
  // Early out in case one of the startup modules triggered a quit
  if (WantsToQuit())
    return;

  if(pImpl == NULL)
  {
    hkvLog::FatalError("No implmentation found!");
    return;
  }
  
  m_pAppImpl = pImpl;
	Vision::SetApplication(this);

  // On callback based platforms the remaining code of the execute function
  // is triggered via the corresponding platform specific functions
  if (IsCallbackBased())
    return;

  AppInit();
  {
    // Main application loop (non callback based platforms only)
    bool bRun = true;
    while (bRun)
    {
      bRun = AppRun();
    }
  }
  AppDeInit();
}
예제 #2
0
//Update, render and display the scene
bool VisionApp_cl::Run()
{
  static bool bInsideGameLoop = false;

  // Make sure the game loop isn't executed recursively. In Windows builds, this could for example happen if a shown message box triggers
  // a repaint message. This case needs to be handled by the code calling the game loop.
  if(bInsideGameLoop)
  {
    // We can't report this error in a form that could trigger a message box, so reporting a warning and breaking the debugger is the best we can do.
    Vision::Error.Warning("VisionApp_cl::Run called recursively! This is usually caused by triggering a repaint from inside the game loop.");

#if defined(HK_DEBUG)
    VDBGBREAK;
#endif

    // Just skip the game loop - this may invoke weird behavior if the calling code expects the game loop to complete, but is better
    // than recursing
    return true;
  }

  bInsideGameLoop = true;

  //Update the scene
  m_iUpdateSceneTickCount = 1; // by default one simulation tick per loop
  if (m_spUpdateSceneController!=NULL)
    m_iUpdateSceneTickCount = m_spUpdateSceneController->GetUpdateTickCount();

  for (int i=0;i<m_iUpdateSceneTickCount;i++)
  {
    OnUpdateScene();
    if (i<m_iUpdateSceneTickCount-1) // the last one is performed after rendering
    {
      OnFinishScene();
      UpdateTimer();
    }
  }

  // update everything that has to be done once per loop rather than per simulation steps
  OnFrameUpdatePreRender();

  Vision::Profiling.Update();

  VASSERT_MSG(Vision::Renderer.GetRendererNode(0) != NULL, "No renderer node is set. This isn't supported anymore. Use a VSimpleRendererNode instead of registering the main context globally.");

  // If in debug build, perform a sanity check - no context registered with the main context should also be registered
  // with a renderer node!
#ifdef HK_DEBUG_SLOW
  static bool bContextErrorShown = false;
  if (!bContextErrorShown)
  {
    int iContextCount = Vision::Contexts.GetContextCount();
    for (int iContext = 0; iContext < iContextCount; iContext++)
    {
      for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++)
      {
        IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode);
        VisRenderContext_cl* pContext = Vision::Contexts.GetContext(iContext);
        if (pNode != NULL && pNode->IsContextRegistered(Vision::Contexts.GetContext(iContext)))
        {
          Vision::Error.Warning("Context %s (%p) is registered globally AND in renderer node %s (%p). This may be intended, but it is most likely a porting issue introduced by porting from a pre-8.0 version of the Vision Engine.",
            pContext->GetName(), pContext, pNode->GetTypeId()->m_lpszClassName, pNode);
          bContextErrorShown = true;
        }
      }
    }
  }
#endif

  {
    INSERT_PERF_MARKER_SCOPE("BeginRendering");

    // Inform the renderer that we are now going to start rendering
    Vision::Renderer.BeginRendering();
    Vision::Callbacks.BeginRendering.TriggerCallbacks();
  }


  Vision::Renderer.SetCurrentRendererNode(NULL);
  VisRendererNodeDataObject_cl data(&Vision::Callbacks.OnRendererNodeSwitching, NULL);
  Vision::Callbacks.OnRendererNodeSwitching.TriggerCallbacks(&data);


  {
    INSERT_PERF_MARKER_SCOPE("PreRendererNodeContexts");
    Vision::Contexts.PerformVisibilityTests();
    Vision::Contexts.RenderContexts(-FLT_MAX, VIS_RENDERCONTEXTPRIORITY_SCENE);
  }

  {
    for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++)
    {
      IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode);

      if (pNode != NULL && pNode->GetRenderingEnabled())
      {
        char buffer[192];
        sprintf(buffer, "RendererNode %d (%s)", iRendererNode, pNode->GetTypeId()->m_lpszClassName);
        INSERT_PERF_MARKER_SCOPE(buffer);

        VASSERT_MSG(pNode->IsInitialized(), "Renderer Node is registered and enabled, but not initialized");
        pNode->Execute();
      }
    }
  }

  {
    INSERT_PERF_MARKER_SCOPE("PostRendererNodeContexts");
    Vision::Renderer.SetCurrentRendererNode(NULL);
    Vision::Contexts.RenderContexts(VIS_RENDERCONTEXTPRIORITY_SCENE, FLT_MAX);
  }

  {
    INSERT_PERF_MARKER_SCOPE("EndRendering");

    // Tell the renderer that we have finished rendering
    Vision::Callbacks.EndRendering.TriggerCallbacks();
    Vision::Renderer.EndRendering();
  }

  //Finish the scene - the last tick is performed here
  if (m_iUpdateSceneTickCount>0)
    OnFinishScene();

  // update everything that has to be done once per loop rather than per simulation steps
  OnFrameUpdatePostRender();

  //Display the scene
  Vision::Callbacks.OnBeforeSwapBuffers.TriggerCallbacks();
#ifdef WIN32
  if (m_bUpdateScreen) // only supported on win32
#endif
    Vision::Video.UpdateScreen();

  if (m_iUpdateSceneTickCount>0) // same as for OnFinishScene
    UpdateTimer();

  bInsideGameLoop = false;

  return !WantsToQuit();
}