Refactor: dedupe input reads, material-property guards, button hooks

Extract byte-identical duplicated code into shared helpers (behaviour-neutral):
- New InputUtil.cs: single source for mouse-delta/scroll/cursor-lock, modifier
  and mouse-button reads, previously copied verbatim across camera controllers,
  MeshPainter, FirstPersonMode and PlayerCharacterController.
- GetMatFloat/SetMatFloat replace the 12x material-instance + HasProperty guard
  pattern for the camo/height float properties.
- Route two inline button hooks through the existing Hook() helper.

Bespoke variants deliberately kept local (FreeCam SprintHeld = LeftShift only,
MeshPainter.TryGetMouse with out-params).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-07-02 09:20:40 +02:00
1 parent 626dcc1bdf
commit 882d30797e
11 files changed
+158 -222

No files matched your search

+24 -53
View File
@@ -72,23 +72,23 @@ public partial class MeshPainter : MonoBehaviour
/// </summary>
public float CamoHalfLambert
{
get => _materialInstance && _materialInstance.HasProperty(HalfLambertId) ? _materialInstance.GetFloat(HalfLambertId) : 0f;
set { if (_materialInstance && _materialInstance.HasProperty(HalfLambertId)) _materialInstance.SetFloat(HalfLambertId, value); }
get => GetMatFloat(HalfLambertId, 0f);
set => SetMatFloat(HalfLambertId, value);
}
/// <summary>Companion to <see cref="CamoHalfLambert"/>: additive brightness shift (-1..1) of the
/// flattened diffuse term, so the body tone can be tuned to match the scene.</summary>
public float CamoHalfLambertBrightness
{
get => _materialInstance && _materialInstance.HasProperty(HalfLambertBrightnessId) ? _materialInstance.GetFloat(HalfLambertBrightnessId) : 0f;
set { if (_materialInstance && _materialInstance.HasProperty(HalfLambertBrightnessId)) _materialInstance.SetFloat(HalfLambertBrightnessId, value); }
get => GetMatFloat(HalfLambertBrightnessId, 0f);
set => SetMatFloat(HalfLambertBrightnessId, value);
}
/// <summary>Companion to <see cref="CamoHalfLambert"/>: scales down the direct specular highlight.</summary>
public float CamoSpecularDampen
{
get => _materialInstance && _materialInstance.HasProperty(SpecularDampenId) ? _materialInstance.GetFloat(SpecularDampenId) : 0f;
set { if (_materialInstance && _materialInstance.HasProperty(SpecularDampenId)) _materialInstance.SetFloat(SpecularDampenId, value); }
get => GetMatFloat(SpecularDampenId, 0f);
set => SetMatFloat(SpecularDampenId, value);
}
/// <summary>
@@ -101,23 +101,23 @@ public partial class MeshPainter : MonoBehaviour
/// the deepest painted hole. 0 = no darkening (no black spots), 1 = full black at occ=0.</summary>
public float OcclusionThreshold
{
get => _materialInstance && _materialInstance.HasProperty(OcclusionThresholdId) ? _materialInstance.GetFloat(OcclusionThresholdId) : 0.2f;
set { if (_materialInstance && _materialInstance.HasProperty(OcclusionThresholdId)) _materialInstance.SetFloat(OcclusionThresholdId, value); }
get => GetMatFloat(OcclusionThresholdId, 0.2f);
set => SetMatFloat(OcclusionThresholdId, value);
}
/// <summary>Multiplier on the painted-height relief NORMAL strength (1 = base, 0 = flat).</summary>
public float HeightNormalIntensity
{
get => _materialInstance && _materialInstance.HasProperty(HeightNormalIntensityId) ? _materialInstance.GetFloat(HeightNormalIntensityId) : 1.4f;
set { if (_materialInstance && _materialInstance.HasProperty(HeightNormalIntensityId)) _materialInstance.SetFloat(HeightNormalIntensityId, value); }
get => GetMatFloat(HeightNormalIntensityId, 1.4f);
set => SetMatFloat(HeightNormalIntensityId, value);
}
/// <summary>Multiplier on the painted-height UV PARALLAX amplitude (1 = base <see cref="ParallaxBase"/>,
/// 0 = no displacement). Backed by the material's _Parallax, so it round-trips like the others.</summary>
public float ParallaxIntensity
{
get => _materialInstance && _materialInstance.HasProperty(ParallaxId) ? _materialInstance.GetFloat(ParallaxId) / ParallaxBase : 1f;
set { if (_materialInstance && _materialInstance.HasProperty(ParallaxId)) _materialInstance.SetFloat(ParallaxId, Mathf.Max(0f, value) * ParallaxBase); }
get => GetMatFloat(ParallaxId, ParallaxBase) / ParallaxBase;
set => SetMatFloat(ParallaxId, Mathf.Max(0f, value) * ParallaxBase);
}
/// <summary>Drives the see-through-walls X-ray overlay (see <c>PlayerCamoLit</c>): sets the TARGET for
@@ -1060,6 +1060,15 @@ public partial class MeshPainter : MonoBehaviour
private static float Cross2D(Vector2 a, Vector2 b) => a.x * b.y - a.y * b.x;
// Guarded material float access: absent instance/property -> the caller's fallback, no write.
private float GetMatFloat(int id, float fallback)
=> _materialInstance && _materialInstance.HasProperty(id) ? _materialInstance.GetFloat(id) : fallback;
private void SetMatFloat(int id, float value)
{
if (_materialInstance && _materialInstance.HasProperty(id)) _materialInstance.SetFloat(id, value);
}
private bool TryGetMouse(out bool pressed, out Vector2 screenPos)
{
pressed = false;
@@ -1096,8 +1105,8 @@ public partial class MeshPainter : MonoBehaviour
{
// 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 shift = InputUtil.ShiftHeld();
bool ctrl = InputUtil.CtrlHeld();
bool mod = shift || ctrl;
if (mod && !_pipetteModHeld) _pipetteBeforeMod = pipette;
if (mod) pipette = true;
@@ -1108,7 +1117,7 @@ public partial class MeshPainter : MonoBehaviour
// held, so it does not also zoom).
if (!mod) return;
float scroll = ReadScroll();
float scroll = InputUtil.ReadScroll();
if (Mathf.Approximately(scroll, 0f)) return;
// Geometric resize: the step scales with the current size, so small brushes change a texel
@@ -1121,44 +1130,6 @@ public partial class MeshPainter : MonoBehaviour
BrushSizeChanged?.Invoke();
}
private static bool ShiftHeld()
{
#if ENABLE_INPUT_SYSTEM
var kb = Keyboard.current;
if (kb != null) return kb.leftShiftKey.isPressed || kb.rightShiftKey.isPressed;
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
#else
return false;
#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
if (Mouse.current != null) return Mouse.current.scroll.ReadValue().y;
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
return Input.GetAxis("Mouse ScrollWheel");
#else
return 0f;
#endif
}
/// <summary>True if the pointer is currently over an interactive UI element (raycast target).</summary>
private static bool IsPointerOverUi()
{