/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkScenePicker.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/**
 * @class   vtkScenePicker
 * @brief   Picks an entire viewport at one shot.
 *
 * The Scene picker, unlike conventional pickers picks an entire viewport at
 * one shot and caches the result, which can be retrieved later.
 *    The utility of the class arises during <b>Actor Selection</b>. Let's
 * say you have a couple of polygonal objects in your scene and you wish to
 * have a status bar that indicates the object your mouse is over. Picking
 * repeatedly every time your mouse moves would be very slow. The
 * scene picker automatically picks your viewport every time the camera is
 * changed and caches the information. Additionally, it observes the
 * vtkRenderWindowInteractor to avoid picking during interaction, so that
 * you still maintain your interactivity. In effect, the picker does an
 * additional pick-render of your scene every time you stop interacting with
 * your scene. As an example, see Rendering/TestScenePicker.
 *
 * @warning
 * - Unlike a vtkHoverWidget, this class is not timer based. The hover widget
 *   picks a scene when the mouse is over an actor for a specified duration.
 * - This class uses a vtkHardwareSelector under the hood. Hence, it will
 *   work only for actors that have opaque geomerty and are rendered by a
 *   vtkPolyDataMapper.
 *
 * @sa
 * vtkHoverWidget vtkHardwareSelector
*/

#ifndef vtkScenePicker_h
#define vtkScenePicker_h

#include "vtkRenderingCoreModule.h" // For export macro
#include "vtkObject.h"

class vtkRenderer;
class vtkProp;
class vtkHardwareSelector;
class vtkRenderWindowInteractor;
class vtkScenePickerSelectionRenderCommand;

class VTKRENDERINGCORE_EXPORT vtkScenePicker : public vtkObject
{

  friend class vtkRenderer;
  friend class vtkScenePickerSelectionRenderCommand;

public:
  static vtkScenePicker* New();
  vtkTypeMacro(vtkScenePicker, vtkObject);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  //@{
  /**
   * Set the renderer. Scene picks are restricted to the viewport.
   */
  virtual void SetRenderer(vtkRenderer*);
  vtkGetObjectMacro(Renderer, vtkRenderer);
  //@}

  /**
   * Get cell id at the pick position.
   * Returns -1 if no cell was picked.
   * Makes sense only after Pick has been called.
   */
  vtkIdType GetCellId(int displayPos[2]);

  /**
   * Get cell id at the pick position.
   * Returns -1 if no cell was picked.
   * Makes sense only after Pick has been called.
   */
  vtkIdType GetVertexId(int displayPos[2]);

  /**
   * Get actor at the pick position.
   * Returns NULL if none.
   * Makes sense only after Pick has been called.
   */
  vtkProp* GetViewProp(int displayPos[2]);

  //@{
  /**
   * Vertex picking (using the method GetVertexId()), required
   * additional resources and can slow down still render time by
   * 5-10%. Enabled by default.
   */
  vtkSetMacro(EnableVertexPicking, int);
  vtkGetMacro(EnableVertexPicking, int);
  vtkBooleanMacro(EnableVertexPicking, int);
  //@}

protected:
  vtkScenePicker();
  ~vtkScenePicker() override;

  // Pick render entire viewport
  // Automatically invoked from vtkRenderer at the end of a still render.
  void PickRender();

  // Pick render a region of the renderwindow
  void PickRender(int x0, int y0, int x1, int y1);

  // Internal update method retrieves info from the Selector
  void Update(int displayPos[2]);

  // The RenderWindowInteractor must be set, so that avoid scene picks (which
  // involve extra renders) during interaction. This is done by observing the
  // RenderWindowInteractor for start and end interaction events.
  void SetInteractor(vtkRenderWindowInteractor *);

  int EnableVertexPicking;
  vtkHardwareSelector* Selector;
  vtkRenderer* Renderer;
  vtkRenderWindowInteractor* Interactor;
  vtkIdType VertId;
  vtkIdType CellId;
  vtkProp* Prop;
  bool NeedToUpdate;
  int LastQueriedDisplayPos[2];
  vtkScenePickerSelectionRenderCommand* SelectionRenderCommand;

  vtkTimeStamp PickRenderTime;
private:
  vtkScenePicker(const vtkScenePicker&) = delete;
  void operator=(const vtkScenePicker&) = delete;
};

#endif
