Changelog
Version 1.2.0 introduces new tools, a color palette (a lot of you folks were asking for this one!), better UX, performance optimizations, and various bug fixes, all thanks to @Clonephaze ❤️
Don't forget to check the updated documentation here!
New Tools
- Smooth Vertex Colors — Iterative Laplacian smoothing that blends each vertex's color toward its neighbors. Configurable iteration count (1–50) and blend factor (0–1). Topology constraints let you prevent smoothing from crossing Sharp Edges, UV Seams, or mesh Boundaries, so color islands stay clean.
- Color By Selection — Edit-mode-only tool that paints selected and unselected elements with two separate user-defined colors in a single operation. Useful for quickly masking out geometry or highlighting specific parts.
- Color Adjustments — Non-destructive color correction with six operations: Levels (input/output black, white, and gamma), Brightness/Contrast, Hue/Saturation/Value, Invert, Posterize, and Layer Blend. Layer Blend supports six blend modes: Mix, Multiply, Add, Subtract, Overlay, and Screen.
- Attribute Transfer — Copies vertex color data from one object onto another using three strategies: Nearest Vertex (KDTree lookup), Nearest Surface (closest point with barycentric interpolation across the source face), and Raycast (bidirectional projection with fallback for missed rays). Includes a mix factor to blend transferred colors with the target's existing colors.
- Symmetrize Vertex Colors — Mirrors vertex colors across a chosen axis (X, Y, or Z) in either direction. Uses KDTree matching to pair vertices within a configurable distance threshold. Fully selection- and mask-aware, handles both CORNER and POINT attribute domains.
New Gradient Sources (Color By Position)
The gradient tool gains nine new sources on top of the original Position source:
- Distance — Maps color by distance from a chosen origin point (3D Cursor, Object Origin, or World Origin).
- Noise — Generates values from Perlin/Voronoi/Cell noise with configurable scale, detail, seed, basis, type, roughness, lacunarity, and distortion.
- Curvature — Estimates per-vertex curvature from edge-pair normal angle differences. An optional "Cotangent Weights" mode computes a proper mean curvature via cotangent-weighted Laplacian for cleaner results on smooth surfaces.
- Weight — Reads values directly from the active vertex group, making it easy to drive colors from existing weight paint data.
- Dirty Vertex Colors — Computes cavity/occlusion values matching Blender's native Dirty Vertex Colors algorithm, with configurable highlight/dirt angles, blur iterations, and blur strength.
- Valence — Colors vertices by how many edges connect to them, normalized to 0–1. Useful for visualizing mesh topology.
- Face Area — Averages the area of adjacent faces per vertex and normalizes the result, highlighting dense or sparse regions of geometry.
- Edge Length Variance — Measures how much the lengths of edges connected to each vertex vary, highlighting irregular triangulation.
- Face Quality — Computes a per-face aspect ratio metric (equilateral = 1.0, degenerate = 0.0) and averages it per vertex, useful for identifying low-quality geometry.
- Normalize Per Island — A new checkbox available on all sources. When enabled, gradient values are re-normalized independently per connected mesh island, so every island always spans the full 0–1 range regardless of absolute value differences between islands.
Randomize Enhancements
- Face Set element type — Assigns a random color per sculpt face set, reading the
.sculpt_face_set attribute. Each set gets a visually distinct color.
- Per Object element type — Assigns one color to each selected object as a whole. Uses rejection sampling with a minimum RGB distance constraint to ensure the colors are visually separable — particularly useful for object ID visualization.
- Seed as operator property — The random seed is now exposed on the operator itself rather than stored in the scene. Blender's F9 "Adjust Last Operation" panel lets you scroll the seed to browse different random results without re-running the operator.
Performance
All color-modifying operators have been migrated from per-element Python loops to NumPy foreach_get/foreach_set bulk I/O, which is typically 100–1000× faster on large meshes. Beyond the bulk I/O migration, several specific algorithmic improvements were made:
- O(V×F) → O(L) in Fill and Random Color (per-point) — The original code iterated all polygons for every selected vertex to find matching loops. Replaced with a single-pass vertex→loop map built in O(L).
- O(E×F) → O(F) in island detection — The original adjacency build for "per island" random color tested every face for every edge. Replaced with a single polygon pass that builds the edge→face map directly.
- Gradient coordinate loading — Vertex positions are now loaded in a single
foreach_get("co") call and optionally transformed with the world matrix via NumPy matrix multiplication, rather than accessed per-vertex through Python.
UI/UX
- Addon Preferences — A full preferences panel with startup defaults for every tool property. Defaults are applied via a persistent
load_post handler so they survive file loads. The panel uses a tabbed layout (General / Paint Tools / Adjust Tools) to keep things organized rather than one long list. The General tab includes an editable default palette with a swatch grid editor.
- Adjust tools — Smooth, Color Adjustments, Attribute Transfer, and Symmetrize are grouped under a collapsible "Adjust" parent panel in the sidebar, separating "paint new colors" tools from "modify existing colors" tools.
- Blender Pallets — Integrated Blender's official pallets into the Panel, which allows users to add as many colors as they like, or use their own saved pallet assets, or other add-ons' pallets. Each swatch, when clicked, will fill the color for the fill tool.
- Quick Fill — A toggle in the Fill panel. When enabled, clicking any palette swatch immediately applies that color to the selected object without needing to press the Apply button separately.
- Visibility warning — After any color operation, if vertex colors aren't currently visible in the viewport (wrong shading mode or display setting), a pop-up explains the issue and offers a one-click "Enable Attribute View" button to fix it. Includes a "don't warn me about this" toggle that persists in preferences.
- Keyboard shortcuts reference — Replaced the static collapsible panel section with a modal popup dialog. Each operator ID is displayed in a selectable text field so users can copy it directly into Blender's keymap editor.
Bug Fixes
obj.data.update() missing in Reset operator — Color changes written via the mesh data API were never flushed to the GPU. The viewport wouldn't update until something else triggered a redraw.
bl_options = {'REGISTER', 'UNDO'} missing on all operators — None of the original data-modifying operators declared undo support, so color changes couldn't be undone with Ctrl+Z.
- Division by zero in Color By Position — When all vertices share the same coordinate along the gradient axis,
max - min is zero. The original code is divided by this unconditionally, crashing with ZeroDivisionError.
range built-in shadowed — The variable range = max_pos - min_pos in add_color_by_position.py shadowed Python's built-in range(), breaking any subsequent use of it in that scope.
- Version hardcoded in About panel — The version string was a literal
"Version 1.1.0". Now reads from blender_manifest.toml at draw time via tomllib.