You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Paint Tools MVP (epic #313, closed) shipped a solid foundation: TexturePaintController with Paint / Erase / Fill / ColorPicker / Smudge / SmartSelect tools, round/square brushes with radius / strength / falloff, vertex-and-texture targets, undo-wired strokes, paint-buffer image provider for live QML preview, vertex-color baking, and seam dilation.
This epic is Paint v2: build on that foundation to bring QtMeshEditor's painting up to the level users expect from Blender Texture Paint, Substance Painter (the parts that fit a single-binary indie editor), Krita, and 3D-Coat's "paint" workflow. The two features the user explicitly asked for — gradient brushes and textured (stamp / tiling) brushes — anchor the work, plus the rest of the modern-paint feature set the MVP doesn't yet cover.
GUI + CLI + MCP parity (where painting maps to scriptable operations), undo through UndoManager, Sentry breadcrumbs (paint.*), and the slice-PR cadence used by every recent epic.
Why
Plain solid color is the v1 limit. Real surface authoring needs gradient ramps (sunset, gold→rust, hue ramp), textured brushes (a leaf shape, a metal-scratch stamp), and tiling pattern brushes (wood grain, brick, fabric).
One target slot (BaseColor) leaves the PBR story half-done. Painters need to paint into normal, roughness, metallic, AO, emissive, height.
No layers means destructive painting. Every major painter has layered, blendable, maskable, reorderable layers; QtMeshEditor's MVP composites directly into the texture.
No symmetry, no projection painting, no stencils — table-stakes 3D-paint features missing today.
Builds on what's already merged, doesn't replace it:
PaintLayerStack — per-material ordered list of PaintLayer { name, type, blendMode, opacity, visible, mask, buffer }. The MVP's single TexturePaintBuffer becomes one layer ("Background") on a new stack; existing strokes route to the active layer.
BrushEngine — extracted from TexturePaintController's stamp loop:
PaintChannelRouter — routes the active brush onto BaseColor / Normal / Roughness / Metallic / AO / Emissive / Height with channel-aware presets.
SymmetryEngine — mirror painting across X/Y/Z (world or local) and topology-aware mirror for asymmetric meshes.
ProjectionPainter — paint from the active viewport camera (stencil / projection); paint from a 2D image projected through a placed plane (decals).
Reuses every MVP component: TexturePaintBuffer becomes per-layer; PaintSelectionMask extends to layer masks; PaintBufferImageProvider becomes layer-aware; VertexColorBaker becomes "Bake vertex layer to texture layer"; existing undo commands gain a layerIndex field.
Cross-cutting integration: UV editor (#458) overlap/stretch overlays surface in paint mode; HDR/IBL (#466) renders painted PBR correctly; AI generators (#403, #404) land into a new layer instead of overwriting.
Child Issues
Slices A–D are the user's directly requested features plus the missing-must-haves; E–H cover the rest of the modern-paint table-stakes; I closes the loop into engine deliverables; J brings everything to project conventions.
User can paint with a gradient ramp (linear / radial / angular), at least 6 bundled ramps, and author/save custom ones.
User can paint with textured / stamp brushes — choosing a stamp image or tiling source — with jitter / scatter / spacing.
Painting is non-destructive via a layer stack with at least 8 blend modes (Normal, Multiply, Screen, Overlay, Add, Subtract, Soft Light, Hue/Sat/Color/Luminosity).
Layers have per-layer masks, opacity, visibility, reorder, rename, duplicate, merge.
User can paint directly into normal / roughness / metallic / AO / emissive / height — not just BaseColor.
Symmetry painting works across world/local X/Y/Z plus a topology-aware mode.
Projection painting from the active viewport camera and from a placed image plane both work.
Cavity / curvature / AO masks auto-generate from the mesh and feed brush color or layer masks.
Tablet pressure modulates size and opacity (Wacom + Apple Pencil).
Brush preset library and color swatches/palettes ship.
Overview
The Paint Tools MVP (epic #313, closed) shipped a solid foundation:
TexturePaintControllerwith Paint / Erase / Fill / ColorPicker / Smudge / SmartSelect tools, round/square brushes with radius / strength / falloff, vertex-and-texture targets, undo-wired strokes, paint-buffer image provider for live QML preview, vertex-color baking, and seam dilation.This epic is Paint v2: build on that foundation to bring QtMeshEditor's painting up to the level users expect from Blender Texture Paint, Substance Painter (the parts that fit a single-binary indie editor), Krita, and 3D-Coat's "paint" workflow. The two features the user explicitly asked for — gradient brushes and textured (stamp / tiling) brushes — anchor the work, plus the rest of the modern-paint feature set the MVP doesn't yet cover.
GUI + CLI + MCP parity (where painting maps to scriptable operations), undo through
UndoManager, Sentry breadcrumbs (paint.*), and the slice-PR cadence used by every recent epic.Why
Architecture
Builds on what's already merged, doesn't replace it:
PaintLayerStack— per-material ordered list ofPaintLayer { name, type, blendMode, opacity, visible, mask, buffer }. The MVP's singleTexturePaintBufferbecomes one layer ("Background") on a new stack; existing strokes route to the active layer.BrushEngine— extracted fromTexturePaintController's stamp loop:PaintChannelRouter— routes the active brush onto BaseColor / Normal / Roughness / Metallic / AO / Emissive / Height with channel-aware presets.SymmetryEngine— mirror painting across X/Y/Z (world or local) and topology-aware mirror for asymmetric meshes.ProjectionPainter— paint from the active viewport camera (stencil / projection); paint from a 2D image projected through a placed plane (decals).Reuses every MVP component:
TexturePaintBufferbecomes per-layer;PaintSelectionMaskextends to layer masks;PaintBufferImageProviderbecomes layer-aware;VertexColorBakerbecomes "Bake vertex layer to texture layer"; existing undo commands gain alayerIndexfield.Cross-cutting integration: UV editor (#458) overlap/stretch overlays surface in paint mode; HDR/IBL (#466) renders painted PBR correctly; AI generators (#403, #404) land into a new layer instead of overwriting.
Child Issues
Slices A–D are the user's directly requested features plus the missing-must-haves; E–H cover the rest of the modern-paint table-stakes; I closes the loop into engine deliverables; J brings everything to project conventions.
Acceptance Criteria (epic-level)
paint.*for every user-visible paint action.CLAUDE.md"Paint" section updated.Dependencies & related issues
Out of scope
Notes for implementers
TexturePaintBuffer,PaintSelectionMask,PaintBufferImageProvider, andVertexColorBakerare tested production code — wrap, don't rewrite.BrushEngineso modifiers compose without re-touching every tool.QTabletEventis portable; no platform-specific code needed.