Repository navigation
Conversation
Coils mapped to a lamp (flashers) went through LampPlayer.HandleCoilEvent(id, bool), which only sends LampStatus.On or Off, so CoilEventArgs.Value was dropped. Device coils already get the value (e.g. PWM-modulated magnets). With PWM-integrated flashers, such as PinMAME's physical outputs where a freezy#89 flasher bulb ramps up over ~20 ms and glows down over ~200 ms, the bulb's brightness never reached the light. Add LampPlayer.HandleCoilEvent(id, float) and use it from CoilPlayer. For a value above 0 it sets the lamp On and then its intensity to the value, 0 sets it Off. Plain coils send 0 and 1, which ends up exactly as before (On at full intensity, Off). RGB mappings keep on/off. The bool overload is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| using var fixture = new Fixture(); | ||
|
|
||
| // a PWM-integrated flasher (e.g. PinMAME's physical outputs) reports its brightness | ||
| fixture.LampPlayer.HandleCoilEvent("17", 0.5f); |
There was a problem hiding this comment.
Tests skip brightness forwarding
All three tests call LampPlayer.HandleCoilEvent directly. None checks that CoilPlayer forwards Value instead of IsEnabled. Reverting that call would leave these tests passing while fractional brightness is lost during play.
Add a test that raises OnCoilChanged with a fractional CoilEventArgs.Value through a started CoilPlayer and checks the lamp's intensity.
What VPX does
VPX tables with PWM flashers (
UseVPMModSol = 2, or modulated solenoids) get a 0-1 level per flasher inSolModCallbackand set it as the light's state, e.g.Flasher.State = value. A #89 flasher bulb then ramps up in ~20 ms and glows down over ~200 ms, following the ROM's actual pulses and PWM.What VPE was missing
CoilEventArgsalready carries a normalized strength (Value, 0-1), and device coils get it (CoilPlayer.cs:186,coil.OnCoil(coilEvent.Value)). Coils mapped to a lamp don't:CoilPlayer.cs:164calls_lampPlayer.HandleCoilEvent(coilEvent.Id, coilEvent.IsEnabled).LampPlayer.cs:198-201turns that intoLampStatus.On/Off.So a flasher whose GLE sends its brightness (the PinMAME PR below does once physical solenoids are on) is fully on while the bulb glows at any level, and then snaps off.
Change
LampPlayer.HandleCoilEvent(string id, float value). For each lamp mapped to the coil, a value above 0 sets the lamp On and then its intensity to the value, and 0 sets it Off. Status comes first because an insert's On status means full intensity, and a light shows its intensity only while it is on. Off keeps the last level, as a status Off does. RGB mappings stay on/off.CoilPlayerpassescoilEvent.Valueto it.booloverload is unchanged.Plain coils send 0 and 1 (
CoilEventArgs(id, bool)setsValueto 0/1), so for every existing table the result is the same as before: On at full intensity, or Off. Only GLEs that send fractional coil values see a difference.GI levels need no Engine change. The PinMAME PR scales physical 0-255 GI into the mapping's
FadingSteps(8 by default), so existing GI mappings keep working.How tested
LampCoilValueTests: a fractional strength drives the light's intensity, the sequence 0.3 → 1 → 0.05 → 0 is followed, and a plain coil (1/0) gives On at full intensity / Off. They compile but have not been run. No Unity editor was available for this (another session had it), so please run them with the EditMode suite.VisualPinball.Unityruntime assembly of this branch builds outside Unity against Unity 6000.5.0f1's managed DLLs (dotnet build, 0 errors, same as master;Collections/CollectionExtensions.csexcluded on both because it needs Unity's internals access).VisualPinball.Engine.Test(dotnet teston Linux, rolled forward to .NET 8): 108 passed / 22 failed, identical on master. The failures are pre-existing mesh-fixture differences on Linux, e.g.ShouldGenerateACube.Notes
FadeSpeedUp/Downstill applies on top. The PinMAME PR turns those fades off for lights it drives with physical outputs, to avoid fading twice.LightComponenta coil event can now mean twoFadeTocalls (status, then intensity) in the same frame. The second one wins.Dependencies
🤖 Generated with Claude Code