Overview

The Color Panel brings a familiar, artist-friendly color grading interface to Nuke. Instead of tweaking raw knob values on Grade, ColorCorrect, or ColorLookup nodes, you get interactive color wheels, a top parameter bar, YRGB curves, and range selectors — all in a single dockable panel that follows your node selection in real time. Undo and redo use Nuke's native undo stack.

📷Color Panel full interfaceimg/color-panel/cp-overview.png
The Color Panel controlling a Grade node with Lift / Gamma / Gain / Offset wheels.
4 Color Wheels
3 Node Types
YRGB Curve Editor
CDL Math Model

Opening the Panel

There are two ways to open the Color Panel:

Tip: Dock the Color Panel next to your Viewer for a Resolve-like layout. The panel is designed to stay open permanently and will automatically adopt whichever grading node you select in the DAG.
Layout: The Color Panel supports portrait orientation, but it is designed primarily for landscape (wide) layout where the wheels, sliders, and curves have enough horizontal space to be comfortable.

Supported Node Types

The Color Panel works with three Nuke node classes. Each class exposes different tabs and capabilities:

Node Type Primaries Tab Curves Tab Ranges Tab Notes
Grade Yes Lift / Gamma / Gain / Offset wheels; Contrast & Pivot in parameter bar
ColorCorrect Yes Yes Primaries + per-range grading (Shadows, Midtones, Highlights); Saturation in parameter bar
ColorLookup Yes Full YRGB curve editor with histogram

When you select a node that the panel does not support, it displays a "no supported node selected" message and waits for a valid selection.

More node types will be supported in upcoming releases.

Primaries Tab

The Primaries tab provides four color wheels arranged left to right: Lift, Gamma, Gain, and Offset. Each wheel controls the corresponding CDL parameter of the selected Grade or ColorCorrect node.

📷Primaries tab with four color wheelsimg/color-panel/cp-primaries.png
The Primaries tab showing Lift, Gamma, Gain, and Offset color wheels.

CDL Color Wheels

Each wheel uses a CDL (ASC Color Decision List) model internally and maps to the native Nuke knobs as follows:

Wheel CDL Role Neutral Value Description
Lift Offset 0 Adds a constant to all values; primarily affects shadows
Gamma 1 / Power 1 Applies a power curve; primarily affects midtones
Gain Slope 1 Multiplies all values; primarily affects highlights
Offset Add 0 Adds a constant after the CDL pipeline; uniform shift
🎬Dragging a color wheel to shift Gamma towards warm tonesimg/color-panel/cp-wheels.gif
Animated: dragging the Gamma wheel to push midtones towards a warm orange.

Click and drag inside a wheel to shift the color balance for that parameter. The further you drag from the center, the stronger the color shift. Dragging is sensitive and designed for fine adjustments; hold Ctrl for precision mode.

Master Ring

Each wheel has an outer master ring. Dragging the ring left or right adjusts the luminance component of that parameter uniformly across all channels. This is equivalent to changing the master value (e.g., master Gain) without introducing a color shift.

Luma Intensity

Below each wheel sits a luma intensity slider that controls how strongly the wheel's adjustment affects the luminance channel relative to the chrominance channels. At 0 the wheel adjustment is purely chromatic; at 1 it applies equally to luminance and chrominance.

Top Parameter Bar

Above the wheels, a horizontal parameter bar provides quick access to global grading controls. The available parameters depend on the selected node type:

📷Top parameter bar with slidersimg/color-panel/cp-parameters.png
The parameter bar showing Contrast, Pivot, Saturation, LumMix, Temperature, and Tint.
Parameter Range Default Available On Description
Contrast 0 – 4 1 Grade, ColorCorrect S-curve contrast around the pivot point
Pivot 0 – 1 0.18 Grade only The midpoint around which contrast is applied
Saturation 0 – 4 1 ColorCorrect only Global saturation multiplier
LumMix 0 – 1 0 Grade, ColorCorrect Blends between the original and graded luminance
Temperature -1 – +1 0 Grade, ColorCorrect Cool (blue) to warm (orange) color shift
Tint -1 – +1 0 Grade, ColorCorrect Green to magenta color shift
Note: Temperature and Tint are synthetic parameters that the Color Panel computes and maps to the node's native Gain/Offset knobs. They do not correspond to a single Nuke knob.

Curves Tab

When a ColorLookup node is selected, the panel switches to the Curves tab. This provides a full YRGB curve editor with live dragging, an integrated histogram, and match color functionality.

📷Curves tab with YRGB curves and histogramimg/color-panel/cp-curves.png
The Curves tab displaying the master (Y) curve overlaid on a live histogram.

Ctrl+click or double-click on the curve to add control points. Drag existing points to reshape the curve. Right-click a point to delete it. Changes are applied to the ColorLookup node in real time as you drag.

🎬Live curve dragging with instant feedbackimg/color-panel/cp-curves-drag.gif
Animated: dragging a curve point with live update in the Viewer.

Channel Controls

The curve editor provides the following channel controls:

Live Histogram

A live histogram is drawn behind the curve, showing the tonal distribution of the current frame from the input of the ColorLookup node. The histogram updates when you scrub the timeline or change the input.

Match Color

The Match Color feature allows you to sample a source and target color from the Viewer and automatically generate a curve that maps one to the other. This is useful for color matching between shots.

📷Match Color source and target samplingimg/color-panel/cp-match-color.png
Match Color: sampling a source color (left) and target color (right) to auto-generate curves.

Ranges Tab

The Ranges tab is available when a ColorCorrect node is selected. It provides interactive control over the shadow, midtone, and highlight boundaries that ColorCorrect uses for its per-range grading.

📷Ranges tab with shadow/midtone/highlight slidersimg/color-panel/cp-ranges.png
The Ranges tab showing interactive shadow/midtone/highlight boundary controls.
Tip: Use the Ranges tab in combination with the Primaries tab. Set your boundaries first in Ranges, then switch to Primaries and select the desired range from the range selector to grade shadows and highlights independently.

Global Controls

Reset Button

The orange Reset button in the panel header resets the current tab's parameters to their default (neutral) values:

Warning: The reset action is registered with Nuke's undo system. Press Ctrl+Z to undo a reset.

Node Adoption

The Color Panel automatically adopts the currently selected node in the DAG. When you click a different Grade, ColorCorrect, or ColorLookup node, the panel instantly updates to reflect that node's values and switches to the appropriate tab.

🎬Panel auto-switching when selecting different node typesimg/color-panel/cp-node-adoption.gif
Animated: selecting a Grade node then a ColorLookup node — the panel switches tabs automatically.

CDL Mapping Reference

The Color Panel uses an internal CDL model and maps it to each node type's native knobs. The tables below document the exact mapping.

Grade Node Knobs

Panel Control Nuke Knob Neutral CDL Role
Lift wheellift0Offset
Gamma wheelgamma11 / Power
Gain wheelgain1Slope
Offset wheeloffset0Add
Contrast slidermultiply1
Pivot sliderwhite_clamp / internal0.18

ColorCorrect Node Knobs

Panel Control Nuke Knob Neutral Scope
Lift wheelshadows.offset0Per-range or Master
Gamma wheelmidtones.gamma1Per-range or Master
Gain wheelhighlights.gain1Per-range or Master
Offset wheelmaster.offset0Per-range or Master
Saturation slidersaturation1Global
Range boundariesrangeShadow / Highlight split

ColorLookup Node Knobs

Panel Control Nuke Knob Notes
Master (Y) curvelut.masterApplied to all channels equally
Red curvelut.redRed channel only
Green curvelut.greenGreen channel only
Blue curvelut.blueBlue channel only

Mouse & Controls Reference

Mouse Controls

Action Behavior
Left-click + drag on wheelShift color balance for that parameter
Left-click + drag on master ringAdjust luminance (master value) for that parameter
Ctrl + drag on wheelPrecision mode — fine adjustment
Double-click on wheelReset that single wheel to neutral
Ctrl+click on curveAdd a new control point
Double-click on curveAdd a new control point (alternative)
Left-click + drag on curve pointMove control point (live update)
Right-click on curve pointDelete control point

General

Action Behavior
Global resetClick the orange reset button (top-right)
Switch tabsClick Primaries / Curves / Ranges tab
Undo / RedoCtrl + Z / Ctrl + Shift + Z (standard Nuke undo)

Troubleshooting

Problem Cause Solution
Panel says "No supported node selected" Selected node is not a Grade, ColorCorrect, or ColorLookup Select a supported node in the DAG. The panel adopts it automatically.
Wheels do not update the Viewer in real time The panel's node is not connected to the viewed Viewer input Make sure the controlled node is upstream of the active Viewer input.
Curves tab is grayed out A Grade or ColorCorrect node is selected (curves only work with ColorLookup) Select a ColorLookup node or create one from the panel.
Ranges tab is grayed out A Grade or ColorLookup node is selected (ranges only work with ColorCorrect) Select a ColorCorrect node to access the Ranges tab.
Temperature / Tint have no effect The Gain and Offset knobs are already at extreme values Reset the node and try again, or reduce existing Gain/Offset adjustments.
Panel does not appear in the Panes menu Node Graph Tools is not installed or not loaded Verify the installation by checking ~/.nuke/node_graph_tools/ exists. See the Install guide.
Match Color produces unexpected results Source and target samples are from different color spaces Ensure both samples are taken from the same color space (typically the working space).

Input Devices — Plugin Development

The Color Panel supports hardware and software control surfaces through a plugin-based driver layer. Drivers translate messages from external devices (MIDI controllers, OSC apps, Tangent panels, etc.) into normalised events that the panel understands.

Supported Protocols

Driver Protocol Dependency Status
osc_driver.pyOSC (UDP)None (built-in parser)Complete
midi_driver.pyMIDI CC / Notemido + python-rtmidiComplete
tangent_driver.pyTangent Hub TCPTangent SDKStub
eucon_driver.pyAVID EuConAVID SDKStub

Writing a Driver Plugin

To add support for a new device:

  1. Create a file in input_devices/drivers/ named <protocol>_driver.py
  2. Subclass BaseDriver
  3. Set the three metadata attributes: DRIVER_ID, DRIVER_NAME, DRIVER_VERSION
  4. Implement connect(config), disconnect(), is_connected()
  5. Call self.emit(event) for every incoming message

The DeviceManager discovers your driver automatically on next launch. Only files matching *_driver.py are scanned.

Minimal example

# input_devices/drivers/example_driver.py
from __future__ import print_function, division

from ..base_driver import BaseDriver
from ..event_types import WheelDeltaEvent, WHEEL_LIFT

try:
    import some_sdk
    _AVAILABLE = True
    _UNAVAILABLE_REASON = ""
except ImportError as _e:
    _AVAILABLE = False
    _UNAVAILABLE_REASON = str(_e)


class ExampleDriver(BaseDriver):
    DRIVER_ID      = "example"
    DRIVER_NAME    = "Example Device"
    DRIVER_VERSION = "1.0"

    @classmethod
    def is_available(cls):
        return _AVAILABLE

    @classmethod
    def unavailable_reason(cls):
        return _UNAVAILABLE_REASON

    def get_config_schema(self):
        return {
            "host": {"type": "str",  "default": "localhost", "label": "Host"},
            "port": {"type": "int",  "default": 5000,        "label": "Port"},
        }

    def connect(self, config):
        if not _AVAILABLE:
            return False
        # ... start your listener thread ...
        self._connected = True
        return True

    def disconnect(self):
        # ... stop thread, close sockets ...
        self._connected = False

    def is_connected(self):
        return self._connected

Config schema

get_config_schema() returns a dict describing the parameters your driver needs. The settings UI uses this to generate input fields automatically.

Thread safety

Drivers typically run a listener in a background thread (UDP socket, MIDI port, etc.). Call self.emit(event) from any thread — the DeviceManager routes events through a thread-safe queue and flushes them to the main Qt thread at 60 Hz via a QTimer. Never touch Qt widgets or Nuke knobs directly from your driver thread.

Event Types

Import from input_devices.event_types. All events are Python 2.7 compatible (no dataclasses).

Event Fields Description
WheelDeltaEvent(wheel, dx, dy) wheel: str, dx/dy: float XY movement of a color wheel (trackball, touch pad, jog)
MasterDeltaEvent(wheel, delta) wheel: str, delta: float Rotation of the master luminance ring
WheelResetEvent(wheel) wheel: str Reset a single wheel to neutral
ButtonEvent(button_id, pressed) button_id: str, pressed: bool Named button press/release (e.g. "reset_all")
CurvePointEvent(channel, point_index, x, y) channel: str, point_index: int, x/y: float Direct curve point manipulation (not yet implemented)
TransportEvent(action) action: str Playback controls: play, stop, prev/next frame (not yet implemented)

Wheel constants: WHEEL_LIFT, WHEEL_GAMMA, WHEEL_GAIN, WHEEL_OFFSET, ALL_WHEELS

Channel constants: CH_MASTER, CH_RED, CH_GREEN, CH_BLUE, ALL_CHANNELS

MIDI Mapping Files

MIDI drivers use external JSON mapping files in input_devices/mappings/. Users can create custom mappings for any controller.

{
    "version": 1,
    "description": "My Controller",
    "cc": {
        "1": {"type": "wheel_delta", "wheel": "lift", "axis": "x"},
        "7": {"type": "master_delta", "wheel": "lift"}
    },
    "notes": {
        "36": {"type": "wheel_reset", "wheel": "lift"},
        "39": {"type": "reset_all"}
    }
}

CC types: wheel_delta (requires axis: "x" or "y"), master_delta. Note types: wheel_reset (requires wheel), reset_all, or any custom button_id.

OSC Protocol Reference (iPad App)

The OSC driver expects these addresses:

/grading/<wheel>/delta     float:dx  float:dy
/grading/<wheel>/master   float:delta
/grading/<wheel>/reset
/grading/button/<id>      int:pressed (0 or 1)
/grading/transport/<action>

Where <wheel> is lift, gamma, gain, or offset.

Testing without Nuke

from input_devices import DeviceManager

def log_event(event):
    print("Got:", event)

dm = DeviceManager()
dm.set_event_callback(log_event)
print("Available:", dm.available_drivers())
dm.connect("your_driver_id", {"port": 5000})
# ... send messages from your device ...
dm.disconnect_all()

For bug reports or feature requests, visit the GitLab repository.