#ifndef SO@GUI@_VIEWER_H
#define SO@GUI@_VIEWER_H

// @configure_input@

/**************************************************************************\
 * Copyright (c) Kongsberg Oil & Gas Technologies AS
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\**************************************************************************/

/**************************************************************************\
 * 
 *  A WORD OF ADVICE
 *
 *  It is fruitless to modify the contents of the So@Gui@Viewer.h file
 *  because it is autogenerated by configure from the SoAnyViewer.h.in 
 *  file which you will find in the src/Inventor/@Gui@/common/ directory.
 *  Do your modifications to that file instead.
 *  
\**************************************************************************/

// Include this first, as a workaround for building on top of SGI and
// TGS Inventor on some Linux distributions. (The bug is in SGI/TGS
// Inventor.)
#include <cmath>

#include <Inventor/SbTime.h>
#include <Inventor/SoType.h>
#include <Inventor/SbLinear.h>

#include <Inventor/@Gui@/So@Gui@RenderArea.h>

#ifndef SO@GUI@_INTERNAL
#include <Inventor/events/SoKeyboardEvent.h>
#endif // SO@GUI@_INTERNAL

class SoCallbackList;
class SoBaseColor;
class SoCamera;
class SoComplexity;
class SoDirectionalLight;
class SoDrawStyle;
class SoGetBoundingBoxAction;
class SoGroup;
class SoLightModel;
class SoMaterialBinding;
class SoNode;
class SoPolygonOffset;
class SoSensor;
class SoSeparator;
class SoSwitch;
class SoTimerSensor;

class So@Gui@Viewer;

typedef void So@Gui@ViewerCB(void * data, So@Gui@Viewer * viewer);
typedef void So@Gui@ViewerFPSCB(float fps, void * data, So@Gui@Viewer * viewer);

typedef SbVec2f So@Gui@AutoClippingCB(void * data, const SbVec2f & nearfar);

// *************************************************************************

class SO@GUI@_DLL_API So@Gui@Viewer : public So@Gui@RenderArea {
  SO@GUI@_OBJECT_ABSTRACT_HEADER(So@Gui@Viewer, So@Gui@RenderArea);

public:
  enum Type {
    BROWSER,
    EDITOR
  };

  enum DrawStyle {
    VIEW_AS_IS,
    VIEW_HIDDEN_LINE,
    VIEW_NO_TEXTURE,
    VIEW_LOW_COMPLEXITY,
    VIEW_LINE,
    VIEW_POINT,
    VIEW_BBOX,
    VIEW_LOW_RES_LINE,
    VIEW_LOW_RES_POINT,
    VIEW_SAME_AS_STILL,
    VIEW_WIREFRAME_OVERLAY
  };

  enum DrawType {
    STILL = 0,
    INTERACTIVE
  };

  enum BufferType {
    BUFFER_SINGLE,
    BUFFER_DOUBLE,
    BUFFER_INTERACTIVE
  };

  enum AutoClippingStrategy {
    VARIABLE_NEAR_PLANE,
    CONSTANT_NEAR_PLANE
  };

  virtual void setCamera(SoCamera * camera);
  SoCamera * getCamera(void) const;

  virtual void setCameraType(SoType type);
  SoType getCameraType(void) const;

  virtual void toggleCameraType(void);

  virtual void viewAll(void);

  virtual void saveHomePosition(void);
  virtual void resetToHomePosition(void);

  virtual void setHeadlight(SbBool enable);
  SbBool isHeadlight(void) const;
  SoDirectionalLight * getHeadlight(void) const;

  virtual void setDrawStyle(So@Gui@Viewer::DrawType type, So@Gui@Viewer::DrawStyle style);
  So@Gui@Viewer::DrawStyle getDrawStyle(const So@Gui@Viewer::DrawType type) const;

  virtual void setBufferingType(So@Gui@Viewer::BufferType type);
  So@Gui@Viewer::BufferType getBufferingType(void) const;

  virtual void setViewing(SbBool enable);
  SbBool isViewing(void) const;

  virtual void setCursorEnabled(SbBool enable);
  SbBool isCursorEnabled(void) const;

  void setAutoClipping(SbBool enable);
  SbBool isAutoClipping(void) const;

  void setAutoClippingStrategy(const AutoClippingStrategy strategy,
                               const float value = 0.6f,
                               So@Gui@AutoClippingCB * cb = NULL,
                               void * cbuserdata = NULL);

  virtual void setStereoViewing(SbBool enable);
  SbBool isStereoViewing(void) const;

  virtual void setStereoOffset(const float dist);
  float getStereoOffset(void) const;

  enum StereoType {
    STEREO_NONE, STEREO_ANAGLYPH, STEREO_QUADBUFFER,
    STEREO_INTERLEAVED_ROWS, STEREO_INTERLEAVED_COLUMNS
  };

  SbBool setStereoType(So@Gui@Viewer::StereoType s);
  So@Gui@Viewer::StereoType getStereoType(void) const;

  void setAnaglyphStereoColorMasks(const SbBool left[3], const SbBool right[3]);
  void getAnaglyphStereoColorMasks(SbBool left[3], SbBool right[3]);

  void setDetailSeek(const SbBool enable);
  SbBool isDetailSeek(void) const;

  void setSeekTime(const float seconds);
  float getSeekTime(void) const;

  void addStartCallback(So@Gui@ViewerCB * func, void * data = NULL);
  void addFinishCallback(So@Gui@ViewerCB * func, void * data = NULL);
  void removeStartCallback(So@Gui@ViewerCB * func, void * data = NULL);
  void removeFinishCallback(So@Gui@ViewerCB * func, void * data = NULL);

  void setWireframeOverlayColor(const SbColor & color);
  const SbColor & getWireframeOverlayColor(void) const;

  virtual void setDoubleBuffer(const SbBool enable);

  virtual void setSceneGraph(SoNode * root);
  virtual SoNode * getSceneGraph(void);

protected:
  So@Gui@Viewer(@WIDGET@ parent,
                const char * name,
                SbBool embed,
                Type type,
                SbBool build);
  ~So@Gui@Viewer();

  virtual void sizeChanged(const SbVec2s & size);
  virtual void setSeekMode(SbBool enable);
  SbBool isSeekMode(void) const;
  SbBool seekToPoint(const SbVec2s screenpos);
  void seekToPoint(const SbVec3f & scenepos);
  virtual void computeSeekFinalOrientation(void);

  virtual void actualRedraw(void);
  virtual SbBool processSoEvent(const SoEvent * const event);

  void interactiveCountInc(void);
  void interactiveCountDec(void);
  int getInteractiveCount(void) const;

  void setSeekDistance(const float distance);
  float getSeekDistance(void) const;
  void setSeekValueAsPercentage(const SbBool on);
  SbBool isSeekValuePercentage(void) const;

  virtual void changeCameraValues(SoCamera * camera);

  void addSuperimposition(SoNode * scene);
  void removeSuperimposition(SoNode * scene);
  void setSuperimpositionEnabled(SoNode * scene, const SbBool enable);
  SbBool getSuperimpositionEnabled(SoNode * scene) const;

private:
  class So@Gui@ViewerP * pimpl;
  friend class So@Gui@ViewerP;
  friend class So@Gui@PlaneViewer;
};

// *************************************************************************

#endif // ! SO@GUI@_VIEWER_H
