text: //  Copyright Regents of the University of Minnesota and Brown University, 2010.  All rights are reserved.
  
  /**
   * \author Daniel Keefe (dfk)
   *
   * \file  VRApp.h
   *
   */
  
  
  #ifndef VRAPP_H
  #define VRAPP_H
  
  #include <G3D/G3D.h>
  #include <GLG3D/GLG3D.h>
  
  using namespace std;
  
  #include  "DisplayTile.h"
  #include  "InputDevice.h"
  #include  "ProjectionVRCamera.h"
  
  #include  <iostream>
  
  //This is a stale version using synchit rather than g3d networking.
  //#include <synchit_client.h>
  //#define VRG3D_DEFAULT_SYNCHIT_PORT 4045
  
  #define CLUSTER_NET_PORT 4045
  
  class OmniMap;
  
  namespace VRG3D {
  
  
  /** Base class for a basic G3D-style VR application.  This class
      provides a typical application structure that may be useful for
      many applications.  See vrg3d-demo.cpp for an example.
  */
  class VRApp
  {
  public:
  
    /// Call init() after creating a new VRApp
    ///    share - Configuration file directory.
    ///
    VRApp( std::string  share = "" );
  
    virtual ~VRApp();
  
    /// This is an easy constructor to use for many typical situations.
    /// The vrSetup argument corresponds to a config file that specifies
    /// the type of window to open and devices to connect to.  Look in
    /// $G/src/VRG3D/share/desktop.vrsetup for an example.  Or, run with
    /// vrSetup == "" to print out a list of installed VR setups.
    virtual void init(const std::string &vrSetup, G3D::Log* appLog=NULL);
  
    /// This constructor provides flexibility for other non-standard setups.
    virtual void init(G3D::GWindow *_gwindow, G3D::RenderDevice *_renderDevice, DisplayTile _tile,
                      G3D::Array<InputDevice*> _inputDevices, G3D::CoordinateFrame initialHeadFrame,
                      const std::string &_clusterServerName="", G3D::Log *_log=NULL);
  
    /// This is intended to normally be reimplemented in subclasses
    virtual void doUserInput(G3D::Array<VRG3D::EventRef> &events);
  
    /// This is also intended to normally be reimplemented in subclasses
    virtual void doGraphics(G3D::RenderDevice *rd);
  
    /// This allows for eye specific graphics
    virtual void doGraphics(G3D::RenderDevice *rd, bool leftEye);
  
    /// Call this after init() to startup the program.
    virtual void run();
  
    /// If you need access to the raw GEvent's generated by G3D, you can
    /// reimplement this, but use with care.  One reason to get GEvent's
    /// is to work with the G3D::Gui* 2D screen gui elements.  The
    /// default implementation of this routine already does the
    /// necessary processing for you to use G3D::Gui* if you register
    /// your GuiWindow with VRApp's _widgetManager.
    virtual void guiProcessGEvents(G3D::Array<G3D::GEvent> &gevents, G3D::Array<VRG3D::EventRef> &newGuiEvents);
  
    /// When working with G3D::Gui*, use this routine rather than
    /// GuiPane::addButton() to have the event generated by the button
    /// click transformed into a VRG3D::Event named eventToGenerate.
    virtual G3D::GuiButton* addGuiButtonAndTrapEvent(G3D::GuiPane *pane,
                                                const std::string &eventToGenerate,
                                                const G3D::GuiText &text,
                                                // G3D7:  const GuiCaption &text,
                                                G3D::GuiTheme::ButtonStyle style=G3D::GuiTheme::NORMAL_BUTTON_STYLE);
  
    /// This is the guts of the main program loop.  It's unusual to need
    /// to reimplemet this.
    virtual void oneFrame();
    /// This is the graphics portion of the main program loop.  It's
    /// unusual to need to reimplement this.
    virtual void oneFrameGraphics();
  
  
    G3D::CoordinateFrame       getHeadFrame(int n=0)         { return _cameras[n]->getHeadFrame(); }
    G3D::Log*                  getLog()               { return _log; }
    ProjectionVRCameraRef getCamera(int n=0)            { return _cameras[n]; }
    /// returns the active camera when called during the render loop in a multi-display tile rendering situation
    int                   getActiveCameraNum()   { return _activeCameraNum; }
    G3D::RenderDevice*         getRenderDevice()      { return _renderDevice; }
    bool                  getReadyToEndProgram() { return _endProgram; }
    G3D::UserInput*            getG3DUserInput()      { return _userInput; }
    G3D::WidgetManagerRef      getG3DWidgetManager()  { return _widgetManager; }
  
    /// For clustered rendering (Client side)
    void clientSetup();
    void clientRequestEvents();
    void clientReceiveEvents(G3D::Array<EventRef> &events);
    void clientRequestAndWaitForOkToSwap();
    void clientCheckConnection();
  
    void swapEyes() { _swapEyes = !_swapEyes; };
    void setClearColor(G3D::Color4 clearColor) { _clearColor = clearColor; }
  
    static void setupInputDevicesFromConfigFile(const std::string &filename, G3D::Log* log,
                                                G3D::Array<InputDevice*> &inputDevices);
  
    static void pollWindowForGEvents(G3D::RenderDevice *rd, G3D::Array<G3D::GEvent> &gEvents);
  
    static void appendGEventsToEvents(G3D::RenderDevice *rd, DisplayTile &tile, G3D::Array<EventRef> &events,
                                      G3D::Array<G3D::GEvent> &gEvents, G3D::Vector2 &mousePos, bool adjustTileOnResizeEvent);
  
    static std::string getKeyName(G3D::GKey::Value key, G3D::GKeyMod mod);
  
  
    /// Looks for filename first in the current directory, if it is not there,
    /// then looks in a series of potential paths stored in the _dataFilePaths
    /// array.  Returns "" if the file is not found in any of these locations.
    static std::string findVRG3DDataFile(const std::string &filename);
    static G3D::Array<std::string> _dataFilePaths;
  
  protected:
  
  
    G3D::Log*                  _log;
    G3D::GWindow*              _gwindow;
    G3D::RenderDevice*         _renderDevice;
    G3D::Array<InputDevice*>   _inputDevices;
  
    G3D::Array<ProjectionVRCameraRef> _cameras;
    int                   _activeCameraNum;
    bool                  _endProgram;
    G3D::Vector2               _curMousePos;
    G3D::int64                 _frameCounter;
    G3D::Color4                _clearColor;
    bool                  _adjustTileOnResizeEvent;
    bool                  _blueLineStereoLeftFrame;
    bool                  _swapEyes;
  
    bool                  _isAClusterClient;
    std::string           _clusterServerName;
  
    G3D::NetworkDevice*        _networkDevice;
    G3D::ReliableConduitRef    _conduitToServer;
  
    // To support integration of G3D::Gui*
    G3D::WidgetManagerRef               _widgetManager;
    G3D::UserInput                     *_userInput;
    G3D::Table<G3D::GuiButton*, std::string> _guiBtnToEventMap;
  
    // Declare a pointer to the OmniMap for OpenGL renderer.
    //OmniMap*               _omnimapLib;
  
    // Platform specific initialization.
    void  initScreenSize( G3D::GWindow::Settings  &gwinsettings );
    void  initCreateWindow( G3D::GWindow::Settings  &gwinsettings );
  };
  
  
  /// Sleeps for milliseconds
  void vrg3dSleepMsecs(double msecs);
  
  
  /// Sleeps for seconds
  void vrg3dSleepSecs(double secs);
  
  
  } // end namespace
  
  #endif            // VRAPP_H
  