Skip to content

WBP_RuntimeColorPicker

WBP_RuntimeColorPicker is the default runtime color picker widget included with the plugin.

It is designed to work directly with PaintingModeControllerComponent. When paint mode opens, the controller creates the widget, adds it to the viewport, and passes itself to the widget through the runtime paint target interface.

Default WBP_RuntimeColorPicker asset

Parent Class

The parent class is Color Picker Panel Widget, implemented in C++ as UColorPickerPanelWidget.

Color Picker Panel Widget parent class

Keep this parent class when making custom versions. The parent class owns the actual color picker logic:

  • Current and previous color state
  • RGB, HSV, and hex synchronization
  • Brush size, metallic, and roughness values
  • Eraser state
  • Eyedropper mode
  • Recent color history
  • Tool strip behavior
  • Paint target integration
  • Blueprint events

Do not build a custom color picker from an empty widget unless you are intentionally replacing the whole UI system.

The recommended workflow is:

  1. Find WBP_RuntimeColorPicker.
  2. Duplicate it.
  3. Rename the duplicate, for example WBP_MyRuntimeColorPicker.
  4. Keep the parent class as Color Picker Panel Widget.
  5. Change the layout, colors, padding, icons, fonts, and visual style.
  6. Keep the bound widget names unless you intentionally remove that feature.
  7. Assign the duplicated widget to PaintingModeControllerComponent > Widget > Color Picker Widget Class.

Duplicate WBP_RuntimeColorPicker

Custom widget copy next to the default widget

Assign custom color picker widget class

This keeps the C++ event binding, brush setting sync, eyedropper, eraser, and recent color behavior intact.

Designer Overview

You can freely restyle the duplicate widget in the Designer.

Color picker designer overview

Safe changes:

  • Move panels around.
  • Change colors, backgrounds, borders, and padding.
  • Resize rows and previews.
  • Replace icons and styling.
  • Hide optional sections you do not need.

Risky changes:

  • Renaming bound widgets.
  • Deleting a bound widget but expecting its feature to keep working.
  • Changing the parent class.
  • Replacing plugin child widgets with normal UMG widgets that do not expose the expected events.

Important Widget Names

UColorPickerPanelWidget uses optional widget binding. That means the widget can still build a native fallback layout if nothing is provided, but a custom Blueprint should keep these names when it wants the built-in behavior.

Color picker widget hierarchy

Widget NameExpected TypePurpose
RootBorderBorderMain panel area, padding, and cursor-over-UI detection.
ColorWheelColor Wheel WidgetHue/saturation or spectrum color selection.
SaturationBarVertical Color Bar WidgetSaturation adjustment in wheel mode.
ValueBarVertical Color Bar WidgetValue/brightness adjustment.
CurrentPreviewColor Preview WidgetShows the current color.
PreviousPreviewColor Preview WidgetShows and restores the previous color when clicked.
ToolStripColor Picker Tool Strip WidgetColor mode, eyedropper, palette visibility, and eraser buttons.
SrgbPreviewOptionColor Option Row WidgetToggles sRGB preview display.
HexInputHex Color Input WidgetHex color input and validation.
HistoryBarColor History Bar WidgetRecent colors and palette colors.
RedRowColor Channel Row WidgetRed channel.
GreenRowColor Channel Row WidgetGreen channel.
BlueRowColor Channel Row WidgetBlue channel.
HueRowColor Channel Row WidgetHue channel.
SaturationRowColor Channel Row WidgetHSV saturation channel.
ValueRowColor Channel Row WidgetHSV value channel.
BrushSizeRowColor Channel Row WidgetNormalized brush size slider.
MetallicRowColor Channel Row WidgetBrush metallic value.
RoughnessRowColor Channel Row WidgetBrush roughness value.
PaintScalarRowsStackVertical BoxContainer used for brush size, metallic, and roughness rows.

Optional legacy names such as PaletteGrid, RecentColorsArea, ToolRow, and EyedropperButton may still be present in older layouts, but the current default workflow uses ToolStrip and HistoryBar.

How It Connects To Painting

PaintingModeControllerComponent controls widget creation.

When Auto Create Color Picker Widget is enabled, the controller:

  • Creates the widget class stored in Color Picker Widget Class.
  • Adds it to the viewport using Color Picker Widget ZOrder.
  • Calls SetPaintTarget(this) on the widget.
  • Keeps brush size synchronized through OnBrushSizeChanged.
  • Calls NotifyPaintApplied after successful paint so recent colors can be updated.

The widget then pushes brush settings back through ApplyBrushSettingsToPaintTarget when Push Settings To Paint Target is enabled.

Main Settings

SettingPurpose
CurrentColorCurrent paint color.
PreviousColorPrevious color used by the previous-preview button.
BrushSizeNormalized UI brush size from 0.01 to 1.0.
MetallicCurrent brush metallic value.
RoughnessCurrent brush roughness value.
Push Settings To Paint TargetAutomatically applies changed brush settings to the assigned paint target.
Palette Data AssetOptional default palette color source.
Palette Save Slot NameStorage name used by the palette storage object.
Eyedropper Trace ChannelCollision channel used by the eyedropper trace.
Eyedropper Trace ComplexEnables complex tracing for eyedropper hit resolution.
Build Native Layout If MissingAllows the C++ parent class to build a fallback UI if no designer tree exists.
Recent Colors ExpandedShows or hides the recent/history color area.
Panel PaddingPadding applied to RootBorder.

Brush Size Sync

The color picker stores brush size as a normalized UI value.

The actual paint brush size comes from:

text
Normalized Brush Size * PaintingModeControllerComponent.MaxBrushSize

When the controller brush size changes from input, the widget receives OnBrushSizeChanged and updates BrushSizeRow without creating a new paint history entry.

Recent Color History

Recent colors are added after successful painting.

Changing a slider, selecting from the palette, or typing a hex value does not add a color to recent history by itself. This keeps the history focused on colors that were actually used on a mesh.

Eraser mode does not add colors to history.

Eyedropper

The eyedropper can sample both painted targets and visible viewport color.

Flow:

text
Begin eyedropper
-> Left mouse confirms
-> Trace under cursor
-> Try paint target color sample
-> Fallback to viewport pixel sample
-> Update current color
-> Commit color
-> Exit eyedropper

Right mouse or Escape cancels eyedropper mode.

Panel Events

These are the main events exposed by Color Picker Panel Widget.

EventDataWhen It Fires
OnColorChangedColorCurrent color changes from wheel, bars, channel rows, hex input, palette, previous preview, or eyedropper.
OnColorCommittedColorA color interaction is committed, such as finishing a drag, confirming hex, selecting palette color, or sampling with eyedropper.
OnOptionChangedOptionId, bIsEnabledA boolean option changes. The built-in option id is sRGBPreview.
OnScalarChangedScalarId, ValueBrush size, metallic, or roughness changes.
OnScalarCommittedScalarId, ValueA scalar row finishes editing.
OnBrushSettingsChangedSettingsColor, brush size, metallic, roughness, or eraser state changes and a full brush settings struct is rebuilt.
OnToolClickedToolIdA tool strip button is clicked.
OnToolToggledToolId, bIsCheckedA toggle-like tool changes state.
OnPaletteColorSelectedColor, ColorIndexA color is selected from the palette/history area.
OnEyedropperRequestedNoneEyedropper mode starts.
OnEyedropperActiveChangedbIsActiveEyedropper starts or ends.
OnColorSampledSampleResultEyedropper successfully samples a color.

Common ids:

Id TypeValues
Color channel idsR, G, B, H, S, V
Scalar idsBrushSize, Metallic, Roughness
Option idssRGBPreview
Tool idsColorMode, Eyedropper, Palette, Eraser

Child Widget Events

The panel consumes these child widget events internally, but they are also useful when you build advanced custom layouts.

Color Wheel Widget

EventDataUse
OnHueSaturationChangedHue, SaturationReact to hue/saturation movement.
OnHSVChangedHue, Saturation, ValueReact to full HSV changes.
OnInteractionStartedNoneDetect the start of a wheel/spectrum drag.
OnHueSaturationCommittedHue, SaturationReact after wheel interaction finishes.
OnHSVCommittedHue, Saturation, ValueCommit full HSV after interaction finishes.

Color Channel Row Widget

Used by RedRow, GreenRow, BlueRow, HueRow, SaturationRow, ValueRow, BrushSizeRow, MetallicRow, and RoughnessRow.

EventDataUse
OnValueChangedChannelId, ValueA slider/spinbox value changes.
OnInteractionStartedChannelId, InitialValueThe user starts editing this row.
OnValueCommittedChannelId, ValueThe user commits the row value.

Color Bar Widgets

VerticalColorBarWidget is used by saturation/value bars. HorizontalColorBarWidget is available for custom layouts.

EventDataUse
OnValueChangedValueThe bar value changes.
OnInteractionStartedNoneThe user starts dragging the bar.
OnValueCommittedValueThe user finishes dragging the bar.

Hex Color Input Widget

EventDataUse
OnHexCommittedHexText, Color, bIsValid, bHasAlphaA hex value is committed. Invalid values should be ignored.
OnValidityChangedbIsValidThe text becomes valid or invalid while editing.

Tool Widgets

WidgetEventDataUse
ColorPickerToolStripWidgetOnButtonClickedToolIdBuilt-in tool strip button was clicked.
ColorToolButtonWidgetOnClickedToolIdCustom standalone tool button clicked.
ColorToolButtonWidgetOnToggledToolId, bIsCheckedCustom standalone tool toggle changed.
ColorEyedropperButtonWidgetOnClickedNoneLegacy/custom eyedropper button clicked.

Palette and Preview Widgets

WidgetEventDataUse
ColorHistoryBarWidgetOnColorSelectedColor, ColorIndexA recent/history color was selected.
ColorPaletteGridWidgetOnColorSelectedColor, ColorIndexA palette color was selected.
ColorSwatchWidgetOnSwatchSelectedColor, SwatchIndexA single swatch was clicked.
ColorPreviewWidgetOnClickedColorA clickable color preview was clicked.
ColorOptionRowWidgetOnCheckStateChangedOptionId, bIsCheckedA boolean option row changed.

Customization Rules

Follow these rules when making a custom color picker:

  • Duplicate WBP_RuntimeColorPicker.
  • Keep parent class as Color Picker Panel Widget.
  • Assign the duplicate in PaintingModeControllerComponent > Color Picker Widget Class.
  • Keep widget names if you want the built-in binding to keep working.
  • Keep plugin widget classes for color controls. For example, keep ColorWheel as Color Wheel Widget, not a normal image.
  • Do not bind expensive Blueprint logic to high-frequency events such as OnColorChanged, OnScalarChanged, or row OnValueChanged.
  • Use commit events when you only need final user input.
  • Keep RootBorder if you want painting to stop while the cursor is over the color picker UI.

Common Mistakes

  • Creating a new blank widget instead of duplicating WBP_RuntimeColorPicker.
  • Changing the parent class away from Color Picker Panel Widget.
  • Renaming ColorWheel, ToolStrip, HistoryBar, or channel rows and expecting them to keep syncing.
  • Replacing plugin child widgets with standard UMG widgets that do not expose the same events.
  • Binding save/history logic to color changes instead of paint success.
  • Removing RootBorder, causing cursor-over-panel detection to become unreliable.
  • Forgetting to assign the custom widget class on PaintingModeControllerComponent.

Runtime Mesh Painting documentation.