Manipulating Data in 3D
=======================

Knobs in 3D are largely the same as knobs in 2D, which you can find details of
here: :ref:`knobs`. However, there are some extra considerations when writing a 3D knob:

- it needs to check whether the Viewer is in 3D mode before drawing itself
- it may need to draw the handle differently, or not at all, depending on the
  current render pass


Checking for 3D Mode
--------------------

You can easily check whether the Viewer is in 3D mode through the
ViewerContext::

  void draw_handles(DD::Image::ViewerContext* ctx) {
    if (ctx->viewer_mode() != VIEWER_2D) {
      // draw the handle.
    }
  }


Check the Render Pass
---------------------

NUKE's 3D Viewer does a series of rendering passes to draw the final image, so
your handle drawing code may be invoked up to three times:

- once for the solid object pass
- once for the wireframe pass
- once for the hidden lines pass

You can tell what the current render pass is by checking the result of
``ViewerContext::event()``:

+---------------+------------------------------------------------------------+
| Event         | Current Render Pass                                        |
+===============+============================================================+
| DRAW_OPAQUE   | Drawing solid objects. If your handle should appear to be  |
|               | part of the scene, just like regular geometry, this is     |
|               | when you should draw it.                                   |
+---------------+------------------------------------------------------------+
| DRAW_LINES    | Wireframe pass. This is where most handles are drawn.      |
+---------------+------------------------------------------------------------+
| DRAW_STIPPLED | Hidden line pass. In this pass, we're drawing lines which  |
|               | would normally be hidden behind geometry. The line style   |
|               | is changed to stippled and the OpenGL depth test function  |
|               | is inverted. Draw here if you want parts of your handle    |
|               | that would otherwise be obscured to show up.               |
+---------------+------------------------------------------------------------+

There are other values that ``event()`` can return besides those above; you
should make sure you aren't drawing for any of those.

For example::

  void draw_handles(DD::Image::ViewerContext* ctx) {
    if (ctx->viewer_mode() == VIEWER_2D)
      return;

    if (ctx->event() == DRAW_LINES || ctx->event() == DRAW_STIPPLED) {
      // draw the handle.
    }
  }


