Make the eyedropper a hybrid material/screen pick
On a foreign object the pipette now reads the data channels (metallic/smoothness/occlusion/emission) texel-exact from the material while taking albedo from the rendered, fully-lit on-screen pixel - so the picked colour honours baked lightmaps/ambient/SSAO while keeping the material's PBR fidelity. Falls back to a pure screen pick when no readable UV is available. Pull the render+readback out of PickFromScreen into a shared TrySampleScreenColor. The pipette now also arms on Ctrl (in addition to Shift), and Ctrl+wheel resizes the brush; the orbit camera ignores the wheel while either modifier is held so it does not zoom and resize at once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
db10eef525
commit
188f16a4e8
3 files changed
+110
-49
No files matched your search
@@ -622,8 +622,8 @@ public partial class MeshPainter : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// Shift modifiers: hold Shift for the pipette + Shift+wheel to resize the brush. Runs before
|
||||
// the pipette/paint branches below so the same frame's pipette state reflects the held Shift.
|
||||
// Modifier keys: Shift or Ctrl = pipette, Shift/Ctrl + wheel resizes the brush. Runs before the
|
||||
// pipette/paint branches below so this frame's pipette state is current.
|
||||
HandleBrushModifiers();
|
||||
|
||||
if (updateColliderEveryFrame && _skinned)
|
||||
@@ -644,13 +644,13 @@ public partial class MeshPainter : MonoBehaviour
|
||||
|
||||
// Brush preview (size + mask) at the hover point - independent of painting AND of the
|
||||
// pipette, so you always see the brush footprint: before pressing the button, while the
|
||||
// momentary pipette holds Shift, and live as Shift+wheel resizes the brush.
|
||||
// momentary pipette holds Shift/Ctrl, and live as Shift/Ctrl+wheel resizes the brush.
|
||||
if (previewMode != BrushPreviewMode.Off && _previewMat && paintCamera)
|
||||
UpdatePreview(screenPos);
|
||||
|
||||
// Pipette (eyedropper): a fresh click samples ALL channel values at the hit point
|
||||
// and adopts them into the brush instead of painting. It takes over the click
|
||||
// entirely (no painting), but the brush preview above stays visible.
|
||||
// Pipette (eyedropper): a fresh click samples ALL channel values at the hit point and adopts
|
||||
// them into the brush instead of painting. It takes over the click entirely (no painting),
|
||||
// but the brush preview above stays visible.
|
||||
if (pipette)
|
||||
{
|
||||
EndStrokeIfActive(); // switching to the eyedropper ends any active stroke
|
||||
@@ -881,28 +881,31 @@ public partial class MeshPainter : MonoBehaviour
|
||||
#endif
|
||||
}
|
||||
|
||||
// --- Shift modifiers (paint mode) ---
|
||||
// --- Shift/Ctrl modifiers (paint mode) ---
|
||||
|
||||
private bool _shiftHeld; // edge tracking for the momentary pipette
|
||||
private bool _pipetteBeforeShift; // pipette toggle state to restore when Shift is released
|
||||
private bool _pipetteModHeld; // edge tracking for the momentary pipette (Shift or Ctrl)
|
||||
private bool _pipetteBeforeMod; // pipette toggle state to restore when the modifier is released
|
||||
|
||||
/// <summary>
|
||||
/// While Shift is held the brush enters pipette (eyedropper) mode and the mouse wheel resizes the
|
||||
/// brush (the orbit camera ignores the wheel while Shift is held, so it does not also zoom).
|
||||
/// Releasing Shift restores the pipette toggle's prior state. Called every paint-mode frame.
|
||||
/// While Shift or Ctrl is held the brush enters the pipette (eyedropper), restoring the toggle's
|
||||
/// prior state on release. Shift or Ctrl + the mouse wheel resizes the brush (the orbit camera
|
||||
/// ignores the wheel while either is held, so it does not also zoom). Called every paint-mode frame.
|
||||
/// </summary>
|
||||
private void HandleBrushModifiers()
|
||||
{
|
||||
// Momentary pipette: arm on the Shift/Ctrl press (remembering the toggle's state), force it on
|
||||
// while held (re-arms after a one-shot pick), and restore the prior state on release.
|
||||
bool shift = ShiftHeld();
|
||||
bool ctrl = CtrlHeld();
|
||||
bool mod = shift || ctrl;
|
||||
if (mod && !_pipetteModHeld) _pipetteBeforeMod = pipette;
|
||||
if (mod) pipette = true;
|
||||
else if (_pipetteModHeld) pipette = _pipetteBeforeMod;
|
||||
_pipetteModHeld = mod;
|
||||
|
||||
// Momentary pipette: arm on the Shift press (remembering the toggle's state), force it on while
|
||||
// held (re-arms after a one-shot pick), and restore the prior state on release.
|
||||
if (shift && !_shiftHeld) _pipetteBeforeShift = pipette;
|
||||
if (shift) pipette = true;
|
||||
else if (_shiftHeld) pipette = _pipetteBeforeShift;
|
||||
_shiftHeld = shift;
|
||||
|
||||
if (!shift) return;
|
||||
// Shift or Ctrl + wheel resizes the brush (the orbit camera ignores the wheel while either is
|
||||
// held, so it does not also zoom).
|
||||
if (!mod) return;
|
||||
|
||||
float scroll = ReadScroll();
|
||||
if (Mathf.Approximately(scroll, 0f)) return;
|
||||
@@ -928,6 +931,19 @@ public partial class MeshPainter : MonoBehaviour
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool CtrlHeld()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
var kb = Keyboard.current;
|
||||
if (kb != null) return kb.leftCtrlKey.isPressed || kb.rightCtrlKey.isPressed;
|
||||
#endif
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private static float ReadScroll()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
|
||||
Reference in new issue
Block a user