Commit Graph
20 Commits
Author SHA1 Message Date
adminandClaude Opus 4.8 8abcb8b4ff MeshPainter-Pipette: von AVP/*-Shadern picken + Console-Spam-Fix
- Material-Read-Helper (GetColorProp/GetTexProp/GetFloatProp/ApplyST) auf
  variadische Namenslisten umgestellt
- Albedo/Metallic/Smoothness/Emission der AVP-Shader (POM, Glass, Velvet,
  Velvet_Curtains) werden jetzt name- und typ-tolerant gepickt
- typ-gepruefter HasProp (Shader.GetPropertyType) verhindert GetFloat-Spam
  bei _Metallic/_Smoothness als Textur
- ConcealmentVolume: begleitende Anpassung

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 21:36:43 +02:00
adminandClaude Fable 5 1d5676ab3c Stop paint particles when no stamp lands during a held stroke
Particles kept playing at the last hit position when the cursor left the
mesh mid-stroke. New _stampLandedThisFrame flag: reset before each stamp
attempt, set only where the dab actually paints (after placement and
corner guard); no landed stamp -> StopPaintParticles immediately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:21:56 +02:00
adminandClaude Fable 5 094cf3a493 Paint-Partikel beim Malen: Emission pro Stamp, Scale = Brush-Radius, Farbe = Brush-Albedo mit Helligkeits-Streuung
- MeshPainter: Paint Particles Prefab, lazy Instanz, Play/Stop am Stroke, MinMaxGradient (Albedo +-25%/15% dunkel/hell)
- PaintSplatter.prefab + Paint Particle Material/Textur, Wiring am Player.prefab
- FurShellRenderer: Kill-Switch-Destroy nur im Play-Mode (Edit-Mode-Error beim Prefab-Load)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:13:16 +02:00
adminandClaude Fable 5 423a2d15ec Cursors: Krea-Grafiken in voller Auflösung, Blank-Cursor beim Malen, normalisierte Hotspots
- Cursor_Normal/Paint/Pipette: generierte Grafiken jetzt in Vollauflösung (766-829 px, Max Size im Importer steuert Anzeigegröße), Paint-Ring-Inneres freigestellt
- Neuer Cursor_Blank (transparent): wird während eines Strokes auf dem Mesh gesetzt statt Cursor.visible zu togglen (fixt Flicker-Kampf mit dem Orbit-Input)
- CursorController: Hotspots normalisiert (0-1, unabhängig von Import Max Size); Zustandskette Pipette > (Stroke ? Blank : Paint) > Normal; off-mesh während Stroke -> Normal
- MeshPainter: StrokeInProgress-Flag (Maustaste auf Paint-Pfad gehalten)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:35:36 +02:00
adminandClaude Fable 5 ae5fa63141 Custom mouse cursor: normal/paint/pipette with recorder-aware software mode
- CursorController: polls painter state in LateUpdate; paint cursor only
  while the brush preview decal actually draws (MeshPainter.BrushPreviewVisible),
  pipette while held/toggled, fallback to normal over UI (InputUtil.PointerOverUi)
- Auto ForceSoftware while Unity Recorder is recording (reflection into
  editor-only assembly, 0.5s poll, editor-only) so the cursor is captured;
  back to hardware cursor when recording stops
- 3 placeholder cursor PNGs (32x32, cursor import type) with per-cursor hotspots

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:09:14 +02:00
adminandClaude Fable 5 7fb0ff54b1 Add double-click-to-reset on all sliders (interval + pointer tolerance) and sync PaintHud slider defaults
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 19:28:22 +02:00
adminandClaude Fable 5 6c03e5d3f6 Refactor Assets/Scripts: trim restating comments, minor structure cleanups
Sweep over 48 files (Editor/ excluded): remove comments that restate the
code, condense class summaries, fix three stale doc statements
(HsvColorPicker alpha bar, PaintHud layoutPrefab, MasterVolume
FallbackDefault). Inline two single-use wrappers (IsPointerOverUi,
BuildModes), drop an unused using, replace a magic literal with the
existing ParallaxBase constant, and convert ~10 UnityEngine.Object null
checks to the implicit-bool convention. No serialized fields, signatures,
RPC/NetworkVariable names, defaults, or #if blocks touched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 08:29:18 +02:00
adminandClaude Opus 4.8 50781e32d2 Camo: generalize brightness + add persistent saturation
Move brightness out of the half-lambert diffuse term to a final exposure
multiply on the whole shaded body color (diffuse + GI + specular), and add
a saturation grade (0 = neutral, -1 = grayscale, >0 = boosted) on the same
final stage. Saturation rides as a 4th component on CamoKnobs (Vector3 ->
Vector4) so it inherits all three persistence paths: HUD JSON, network
replication (_camo NetworkVariable), and painting-slot metadata. Wires the
renamed Slider_Brightness and new Slider_Saturation. Bumps HudFileVersion
and PaintMetaVersion with load-time remaps so existing paintings keep their
look (old 1=neutral saturation remaps to 0=neutral).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 07:23:40 +02:00
adminandClaude Opus 4.8 ee01b3b8ab MeshPainter: resample saved paint to avatar resolution on load
Drop the resolution gate in LoadPaintByName/ReadMapPng. A slot saved at any size is now bilinearly resampled per map to the current avatar's textureSize (new ResampleBilinear/Bilerp helpers, running on the stored bytes with no gamma conversion to match downstream consumption), so any painting loads onto any avatar regardless of the size it was saved at.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 22:36:53 +02:00
adminandClaude 9dc8f21528 FurShell: scale-aware length/curvature + X-ray glow mirror
The fur is drawn from a CPU-baked unit-scale mesh whose instance matrix
carries the avatar's world scale, so the extrusion scaled fully 1:1 with
the player (hider 0.5 / hunter 1.5). That read as too-short fur on the
small hider and too-long on the big hunter, and the curvature droop was
sized off the raw unity_ObjectToWorld which doesn't carry the per-instance
scale in the RenderMeshInstanced path.

- FurShellRenderer pushes the avatar's lossyScale (_FurObjScale) plus a new
  Fur Scale Influence (0..1, default 0.5) that blends the fur SIZE between
  fully proportional (1) and a constant world length (0). The shader
  pre-divides the object-space displacement so the net world length follows
  effScale; curl droop and wind use the same effScale, keeping the curl
  SHAPE invariant across avatar sizes and influence settings.
- The body's see-through X-ray reveal (forward half) is mirrored onto the
  visible fur so strands glow WITH the reveal instead of hiding it under
  opaque fur. FurShellRenderer pulls the live colour/pulse/flash from the
  sibling MeshPainter (new getters), in phase with the body. A new X-Ray
  Fur Strength (default 0.2) tames the per-shell accumulation, since the
  body writes the glow once (opaque) but the fur stacks N transparent
  shells that each composite it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 16:33:21 +02:00
adminandClaude Opus 4.8 48975c0f20 perf(paint): stronger X-ray hit flash + kill spawn/respawn freeze
X-ray hit flash: drive a dedicated flash mode instead of the normal
reveal - pulse off (steady), intensity boost (xrayFlashBoost, default 3x),
snap-on, then restore authored color/pulse exactly. Fixes the weak/dark
flicker where the 0.35s hit window often caught only the pulse's near-off
plateau.

Spawn/respawn freeze: pool GPU RenderTextures across despawn->respawn
(TeardownGpu recycles, CreateRT pops) so a hider->hunter conversion no
longer churns ~70MB of RT alloc/free on every observer; reuse staging
textures to cut per-map GC. Defer the blank base-seed on reveal-gated
remote replicas (DeferInitialSeed) - the real pixels arrive with the
snapshot apply anyway; gate the FurShellRenderer alongside the body so a
deferred replica never shows the pooled RT's stale fur; EnsureBackendSeeded
+ TryCaptureSnapshot guard against capture-before-reseed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 15:14:20 +02:00
adminandClaude Opus 4.8 9290ef650b Hunter shot: replicated laser beam + X-ray hit flash; snapshot apply in-place reseed
- Laser.shader + HunterLaserBeam: additive HDR beam, fade in/out over opacity
  and thickness, code-driven LineRenderer, tunable emission multiplier.
- FirstPersonMode: TryShoot computes world endpoint, fires beam with lateral
  muzzle offset (right) so it isn't dead-center from hunter view.
- NetworkPlayerSetup: shot relay RPCs (owner->server->all) + hit-flash RPC
  (server->all), flash OR-branch in ComputeXRay.
- MatchManager: hit reveal broadcasts X-ray flash first, delays hider removal
  by hitRevealDelay so the glow is visible before the body vanishes.
- MeshPainter reseed: in-place fast path avoids full GPU backend teardown on
  snapshot apply (no ~70MB RT churn), fixes spawn/paint-load hitch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 14:18:55 +02:00
adminandClaude Opus 4.8 ed09d6a1b0 Netcode: receiver-side paint reveal gate + fur pipette gating
Hide remote avatars until this client has actually applied a snapshot
reaching the owner-published baseline cutoff, preventing the default
grey/white material from flashing before a player's painting has loaded.

- PlayerPaintSync: owner-authoritative _publishedCutoff NetworkVariable,
  receiver tracks _appliedCutoff; explicit blank publish for never-painted
  avatars so they still reveal.
- NetworkPlayerSetup: cache _paintSync, hide body renderers on spawn, gate
  UpdateVisibility on PaintRevealReady.
- MeshPainter.Pick: fur toggle now follows pickedHeight (own paint-mesh
  only), matching the Occlusion/Height pipette behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 12:08:46 +02:00
adminandClaude Opus 4.8 1b783a39be Fur: Albedo-gekoppelte Länge, Toggle-Gate, Soft-Edge, World-Gravity, Pipette & FP-Hide
- Fur-Map trägt nur noch R = Länge (linearer Datenkanal); Farbe kommt per-texel
  aus der Live-Albedo-RT (an _BaseMap des Shell-Shaders gebunden)
- Toggle_Fur als echtes Gate (IsChannelActive = fur), Default aus, furLength 0.5
- Weicher Alpha-Übergang (radial/tip/length coverage) statt Hard-Clip; Transparent-
  Pass mit Depth-Bias (Offset -1,-1) gegen Body-Durchflimmern
- Root dunkler / Tip heller aus gemalter Farbe abgeleitet (kein Fix-Tint)
- Gravity/Curl in World-Space nach Transform (unabhängig von Mesh-Rotation)
- Pipette aktiviert Fur-Toggle immer; liest R-Kanal als Länge
- First-Person blendet FurShellRenderer mit aus
- Netzwerk (FlagFur), Undo, Persistence (fur.png R=Länge) mitgezogen

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 23:40:58 +02:00
adminandClaude Opus 4.8 7536e8ec8b Fur als 4. Paint-Map + Ziel-Opacity-Blend
Fur wird die vierte kanonische Paint-Map (RGB=Farbe, A=Länge). Integration
über Seed (kahl), GPU/CPU-Paint, Undo, Netzwerk-Sync, Persistence (fur.png,
v6) und Live-RT-Hook im FurShellRenderer. HUD-Binding (Toggle/Picker/Alpha)
aktiviert. Fur-Alpha lerpt jetzt zu einer Ziel-Opacity (Slider_FurOpacity)
statt additiv Richtung 1 zu akkumulieren (zwei Brush-Passes: Fade + Deposit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 21:35:53 +02:00
adminandClaude Opus 4.8 50efc7e8b3 Fix: wheel over UI scrolls the list instead of zooming the camera
The orbit rig read the wheel unfiltered for zoom, so scrolling a paint-mode
scroll list also zoomed the camera. Gate the zoom behind a shared
InputUtil.PointerOverUi() helper (EventSystem raycast); MeshPainter's private
IsPointerOverUi() now delegates to the same helper (DRY).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:04:51 +02:00
adminandClaude Opus 4.8 6ef4f56394 Store paintings as per-painting folder of PNGs + JSON
Replace the flat binary .paint format with a folder per painting under
Paintings/<key>/: albedo/emission as sRGB PNGs, the packed MSO map split
into human-readable metallic/occlusion/smoothness grayscale PNGs, and the
non-baked scalars (name, size, emission intensity, camo/height knobs) in
painting.json. MSO.B is always 0 (pack shader), so the split round-trips
losslessly with no alpha ambiguity. Public API (SavePaintAs/LoadPaintByName/
ListSavedPaintings/PaintExists/DeletePaint) and the network snapshot path
(WriteCanonicalMaps/ReadCanonicalMaps) are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:52:16 +02:00
adminandClaude Opus 4.8 fbbb4f7419 Fix low-opacity paint never reaching the target colour
Paint RTs were ARGB32 (8 bpp). Repeated source-over at low alpha rounds
back to the previous value once the per-stroke decrement dst*alpha drops
below half an LSB, so it freezes at a grey floor (~0.5/alpha in 255ths) -
e.g. black at low opacity never reaches 0. Switch the accumulation buffers
to ARGBHalf (16-bit linear). The sRGB round-trip stays at the byte boundary
(seed decodes on upload, ReadRtPixels re-encodes on readback), so canonical
bytes and CPU/GPU parity are unchanged - only the accumulation gained bits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:32:29 +02:00
adminandClaude Opus 4.8 0d14980a76 Fix maps never binding due to partial-class static init order
MapPropIds (in MeshPainter.Backend.cs) referenced the *Id fields from the
MeshPainter.cs partial in its field initializer. Static field-initializer
order across partial-class files is unspecified in C#; after the script
reorg the composite array initialized before the *Id fields and captured 0
for every property id. HasProperty(0) is always false, so AssignMapTexture
bound no maps at all -> the shader fell back to its white default textures,
making every fresh avatar fully glossy (smoothness 1) and emissive.

Build MapPropIds lazily on first access (runtime, after all static
initializers) so the file order no longer matters. The per-stroke allocation
savings are preserved; only a single null-check per call is added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 16:23:37 +02:00
adminandClaude Opus 4.8 e23fae0c50 Reorganize scripts into subfolders by responsibility
Move scripts under Assets/Scripts/ into Components, GameMode, Helper,
Network, Enum, Struct and ScriptableObject folders. Pure file moves
(plus folder .meta files); no code changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:02:15 +02:00