Docs: reduce over-documentation across gameplay scripts

Trim restated narration, dead commented-out code, and oversized class
headers; keep all why-comments (authority, timing, edge cases), tooltips,
and serialization caveats.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Fable 5 committed 2026-07-02 10:08:28 +02:00
1 parent 882d30797e
commit 066e308cde
21 files changed
+478 -902

No files matched your search

+22 -56
View File
@@ -5,21 +5,10 @@ public partial class MeshPainter
{
// --- Pipette (eyedropper) ---
//
// A sampling MODE rather than a paint channel: while active (Shift or Ctrl held, or the HUD toggle), a
// left-click raycasts onto ANY surface (not just the paint mesh) and reads the channel values at
// the hit point (albedo, metallic, smoothness, emission) into the brush properties. The brush
// opacities/alphas (albedo alpha, metallic/smoothness opacity, emission alpha) are left UNTOUCHED,
// so a pick changes only WHAT is painted, not how strongly. Height (the occlusion channel) is picked
// and its toggle enabled ONLY when our own paint mesh is hit; any other surface leaves the height
// value untouched and disables its toggle. The height opacity (occlusionOpacity) is untouched either way.
//
// On a FOREIGN object the data channels (metallic/smoothness/emission) come texel-exact
// from the material (raw, UNLIT). Albedo follows the 'pipetteAlbedoFromScreen' toggle: OFF (default)
// reads it texel-exact from the material too; ON takes it from the rendered, fully-lit on-screen
// pixel ("what you see" - honours baked lightmaps/ambient/SSAO), combining material PBR fidelity
// with the lit look. When no texel-exact material read is possible (no readable UV / headless) it
// falls back to a pure screen pick (lit albedo, data channels at defaults). Our own paint mesh and
// terrain are read texel-exact.
// A sampling MODE rather than a paint channel: a click (Shift/Ctrl held, or the HUD toggle) reads the
// channel values at the hit point into the brush, leaving the brush opacities/alphas untouched - a
// pick changes WHAT is painted, not how strongly. Height is adopted only off our own paint mesh.
// Per-surface routing: see PickAtScreen.
[Header("Brush - pipette (eyedropper)")]
[Tooltip("Pipette mode: a click samples the channel values at the hit point on ANY surface " +
@@ -49,12 +38,9 @@ public partial class MeshPainter
private const float TerrainFoliageHeightEpsilon = 0.3f;
/// <summary>
/// Raycasts at a screen position against ANY collider, samples the channel values at the hit
/// (texel-exact where possible) and copies them into the brush, leaving the brush opacities/alphas
/// untouched and enabling those paint channels. Height (occlusion) is adopted and its toggle enabled
/// only when our own paint mesh is hit; any other surface disables it (see FinalizePick). Reads
/// regardless of which channels are currently toggled.
/// Pick paths, by what was hit:
/// Raycasts at a screen position against ANY collider (regardless of which channels are toggled),
/// samples the channel values at the hit and adopts them into the brush (toggle rules: see
/// <see cref="FinalizePick"/>). Pick paths, by what was hit:
/// - our paint mesh -> texel-exact from the painted maps (full PBR);
/// - terrain ground -> blend of the terrain layers by their splat weights (full PBR);
/// - terrain tree / detail -> the rendered on-screen colour (no per-instance renderer/UV);
@@ -65,9 +51,7 @@ public partial class MeshPainter
private void PickAtScreen(Vector2 screenPos)
{
bool ok;
// Height (occlusion) is only meaningful off our OWN painted maps, so a hit on our paint mesh is
// the sole pick that enables the height channel - every other surface leaves it off (FinalizePick).
bool pickedHeight = false;
bool pickedHeight = false; // height is only meaningful off our OWN painted maps
if (TryRaycastAny(screenPos, out RaycastHit hit))
{
if (hit.collider == _collider)
@@ -86,8 +70,7 @@ public partial class MeshPainter
}
else
{
// Ray left the scene entirely (e.g. foliage silhouetted against the sky): the
// on-screen pixel is the only thing to sample.
// Ray left the scene entirely (e.g. foliage against the sky) - only the screen pixel remains.
ok = PickFromScreen(screenPos);
}
if (!ok) return;
@@ -96,13 +79,9 @@ public partial class MeshPainter
}
/// <summary>
/// Common tail of every successful pick: enables the sampled paint channels, leaves pipette mode
/// (one-shot) and notifies listeners (the in-game HUD) to re-sync their widgets. The brush
/// opacities/alphas (albedo alpha, metallic/smoothness opacity, emission alpha) are left UNTOUCHED,
/// so a pick changes only WHAT is painted, not how strongly. Height (the occlusion channel) is a
/// special case: <paramref name="pickedHeight"/> is true only when our own paint mesh was picked -
/// then the height toggle is enabled with the adopted value; any other surface disables the toggle
/// and keeps the deliberate height value. The height opacity (occlusionOpacity) is untouched either way.
/// Common tail of every successful pick: enables the sampled paint channels (height only when our
/// own paint mesh was picked - any other surface disables its toggle and keeps the value), leaves
/// pipette mode (one-shot) and notifies listeners (the HUD) to re-sync their widgets.
/// </summary>
private void FinalizePick(bool pickedHeight)
{
@@ -154,35 +133,26 @@ public partial class MeshPainter
brushColor = new Color(a.r / 255f, a.g / 255f, a.b / 255f, brushColor.a);
metallic = m.r / 255f;
smoothness = m.a / 255f;
// Occlusion (m.g) is the painted HEIGHT: adopted only off our own paint mesh, which is the sole
// pick that enables the height toggle (FinalizePick). Its opacity (occlusionOpacity) is left as-is.
occlusion = m.g / 255f;
occlusion = m.g / 255f; // the painted HEIGHT - adopted only off our own mesh (FinalizePick)
emissionColor = new Color(e.r / 255f, e.g / 255f, e.b / 255f, emissionColor.a);
return true;
}
/// <summary>
/// Foreign-object pick: the data channels (metallic/smoothness/emission) always come
/// texel-exact from the material via <see cref="PickFromForeignMaterial"/> (raw, unlit). Albedo
/// follows <see cref="pipetteAlbedoFromScreen"/>: when set, it is overwritten with the rendered,
/// fully-lit on-screen pixel ("what you see" - honours baked lightmaps/ambient/SSAO); otherwise
/// (default) it stays the material's texel-exact value. When no texel-exact material read is
/// possible (no readable UV / headless) it falls back to a pure screen pick (lit albedo, data
/// channels at defaults).
/// Foreign-object pick: data channels always texel-exact from the material (raw, unlit); albedo
/// optionally overwritten with the fully-lit on-screen pixel (<see cref="pipetteAlbedoFromScreen"/>).
/// Falls back to a pure screen pick when no texel-exact material read is possible.
/// </summary>
private bool PickFromForeignHybrid(RaycastHit hit, Vector2 screenPos)
{
if (PickFromForeignMaterial(hit))
{
// Keep the material's texel-exact PBR; optionally replace albedo with the lit on-screen
// colour. No camera (headless) -> keep the material's raw albedo rather than failing.
// No camera (headless) -> keep the material's raw albedo rather than failing.
if (pipetteAlbedoFromScreen && TrySampleScreenColor(screenPos, out Color lit))
brushColor = new Color(Mathf.Clamp01(lit.r), Mathf.Clamp01(lit.g), Mathf.Clamp01(lit.b), brushColor.a);
return true;
}
// No texel-exact material read possible (no renderer/UV, or non-readable mesh behind a convex
// collider): fall back to the lit screen pixel alone (data channels reset to defaults).
return PickFromScreen(screenPos);
}
@@ -199,12 +169,9 @@ public partial class MeshPainter
if (!rend) rend = col.GetComponentInParent<Renderer>();
if (!rend) return false;
// A UV at the hit is required to sample any material map texel-exact. hit.textureCoord is
// only populated for a NON-convex MeshCollider; convex MeshColliders and primitive colliders
// (Box/Sphere/Capsule/Terrain) return Vector2.zero. In that case recover the UV from the
// renderer's own mesh (ray vs. triangles), which works for any solid collider whose mesh is
// readable. Alongside the UV we resolve which SUBMESH the hit triangle belongs to, so a
// multi-material renderer reads the sub-material covering the hit instead of always slot 0.
// hit.textureCoord is only populated for a NON-convex MeshCollider (convex/primitive colliders
// return zero) - recover the UV from the renderer's own mesh then. The hit SUBMESH is resolved
// alongside so a multi-material renderer reads the covering sub-material, not always slot 0.
Vector2 uv;
bool hasUv;
int subMesh;
@@ -227,9 +194,8 @@ public partial class MeshPainter
: null;
if (!mat) return false;
// A base map exists but no UV could be resolved (e.g. a non-readable mesh behind a convex
// collider): a texel-exact read is impossible, so defer to the rendered on-screen pixel,
// which at least reflects the texture - rather than silently picking the flat _BaseColor.
// Base map but no UV resolvable: defer to the on-screen pixel (which at least reflects the
// texture) rather than silently picking the flat _BaseColor.
if (!hasUv && GetTexProp(mat, "_BaseMap", "_MainTex")) return false;
// --- Albedo: BaseMap (sRGB) * BaseColor ---