Open KatieWoe opened 3 weeks ago
I'm not seeing this on iPad, so it may have to do with screen resolution, or some other device specific issue.
I was able to easily reproduce this on macOS 14.5 and latest Chrome.
I think there's a rhythm to it. If I can press with the right tempo, the bulb will either never light or always light.
it may have to do with screen resolution
I think @KatieWoe is on to something. It was very easy to reproduce when I had the sim window split screen (taller, narrower window). When I reduced the browser height to be shorter/wider, I couldn't reproduce at all. I was also not able to reproduce when sizing the window to the layout bounds using ?dev
.
This is the same as https://github.com/phetsims/faradays-electromagnetic-lab/issues/9, which was a legacy bug. I'm not sure if https://github.com/phetsims/faradays-electromagnetic-lab/issues/9 just wasn't fixed at the time it was closed, or if something changed to make the problem come back.
When flipping the polarity, the light bulb only stays lit for 1 time step. The problem in #9 is that we were skipping a frame, and not seeing that time step being rendered. The first attempt to address this was to reimplement ConstantDtClock as a subclass of EventTimer, which did NOT fix the problem; see https://github.com/phetsims/faradays-electromagnetic-lab/issues/9#issuecomment-1942167712. Converting electrons to scenery.Sprites seemed to resolve the problem, probably by improving performance enough that we were skipping a frame less frequently; see https://github.com/phetsims/faradays-electromagnetic-lab/issues/9#issuecomment-1965522316.
EventTimer will make multiple calls to step
if dt
is large enough. To see if that's what is happening in this case, I added this to ConstantDtClock:
public override step( dt: number ): void {
const periodBeforeNextEvent = 1 / ConstantDtClock.FRAMES_PER_SECOND;
const steps = dt / periodBeforeNextEvent;
if ( steps >= 2 ) {
console.log( `dt=${dt} steps=${steps}` );
}
super.step( dt );
}
... and this to LightBulb:
this._brightnessProperty.link( brightness => console.log( `brightness=${brightness} time=${Date.now()}` ) );
In the console, I see the light bulb's brightness go from 0 -> 1 -> 0, for example:
brightness=0 time=1718640618176
brightness=1 time=1718640618811
brightness=0 time=1718640618843
I do not see ConstantDtClock reporting multiple steps. This was my concern, since ConstantDtClock extends EventTimer.
With concerns about getting multiple steps from EventTimer, I resurrected (and improved) the old implementation of ConstantDtClock, see below. This did not resolve the problem.
I've spent ~3 hours on this and I'm no closer to resolving. I'll need help, preferrably from @jonathanolson, who I've contacted on Slack.
In several experiments, I'm seeing a "dropped frame" correlate with the unrendered brightness lines:
UPDATE: I do not see a reliable way to ask the browser if a frame was dropped. My experiments by logging the dts from joist showed that sometimes 0.023s dropped a frame and sometimes 0.023s did not drop a frame. So maybe a reasonable workaround would be to at least render the nonzero brightness for N frames, where N is greater than 1.
My exploratory patch for my reference:
I tried this workaround in FELLightBulbNode.ts. It works if 1 frame is skipped, but apparently multiple frames are being skipped.
Subject: [PATCH] doc tweaks
---
Index: js/common/view/FELLightBulbNode.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/js/common/view/FELLightBulbNode.ts b/js/common/view/FELLightBulbNode.ts
--- a/js/common/view/FELLightBulbNode.ts (revision 6491973eb7ade2ecfb4a0857a683b04ea2b802d8)
+++ b/js/common/view/FELLightBulbNode.ts (date 1718915184965)
@@ -22,6 +22,7 @@
import CurrentIndicator from '../model/CurrentIndicator.js';
import PickRequired from '../../../../phet-core/js/types/PickRequired.js';
import optionize from '../../../../phet-core/js/optionize.js';
+import NumberProperty from '../../../../axon/js/NumberProperty.js';
type SelfOptions = {
maxRayLength?: number; // passed to LightBulbNode
@@ -64,7 +65,20 @@
bottom: baseNode.top + 14 // overlap enough to hide the bottom rounded corners
} );
- const bulbNode = new LightBulbNode( lightBulb.brightnessProperty, {
+ // Workaround for skipped frame, see https://github.com/phetsims/faradays-electromagnetic-lab/issues/180.
+ // When the polarity of the magnet is flipped, lightBulb.brightnessProperty is non-zero for exactly 1 frame.
+ // If the view skips a frame, this event will not be rendered. So this workaround looks for the brightnessProperty
+ // transition 0 -> !0 -> 0, and keeps the !0 value for an additional time step, so that it will be rendered.
+ const brightnessProperty = new NumberProperty( lightBulb.brightnessProperty.value );
+ let oldOldBrightness = 0; // value of brightnessProperty 2 changes ago.
+ lightBulb.brightnessProperty.lazyLink( ( newBrightness, oldBrightness ) => {
+ if ( !( oldOldBrightness === 0 && newBrightness !== 0 && oldBrightness === 0 ) ) {
+ brightnessProperty.value = newBrightness;
+ }
+ oldOldBrightness = oldBrightness;
+ } );
+
+ const bulbNode = new LightBulbNode( brightnessProperty, {
bulbImageScale: 0.5,
// From the Java version, see LightRaysGraphic.java
I've scheduled a meeting for this afternoon with @samreid and @jonathanolson.
To summarize:
lightBulb.brightnessProperty
having a non-zero value for exactly 1 model step.lightBulb.brightnessProperty
is not rendered, so the user does not see the bulb "light".I'd like to understand:
Notes from meeting with @samreid and @jonathanolson ...
renderer: ‘canvas’
did not resolved the problem.Evolution of @samreid's patch is attached below. There are still cases where I'm not seeing the light rays when pressing the "Flip Polarity" button. And there are cases where I'm now seeing light rays twice when pushing the "Flip Polarity" button once.
To verify that scenery-phet LightRaysNode was not a performance problem, I reduced minRays
and maxRays
to 1
. The problem persists.
Subject: [PATCH] doc tweaks
---
Index: js/common/view/FELLightBulbNode.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/js/common/view/FELLightBulbNode.ts b/js/common/view/FELLightBulbNode.ts
--- a/js/common/view/FELLightBulbNode.ts (revision 6491973eb7ade2ecfb4a0857a683b04ea2b802d8)
+++ b/js/common/view/FELLightBulbNode.ts (date 1718922134563)
@@ -70,8 +70,8 @@
// From the Java version, see LightRaysGraphic.java
lightRaysNodeOptions: {
pickable: false,
- minRays: 20,
- maxRays: 20,
+ minRays: 1,
+ maxRays: 1,
minRayLength: 0,
maxRayLength: options.maxRayLength,
longRayLineWidth: 2,
Only because I hadn't done so yet, I tried running with ?webgl=false
. The problem persists.
I tried totally replacing LightBulbNode and LightRaysNode (FELLightBulbNode) with a simple Circle, see patch below. The problem persists. So the problem is not with the implementation of the light bulb view.
I tried totally disabing updates of FieldNode and CurrentNode, my 2 subclasses of Sprites. The problem persists.
Since I often see the flipPolarityButton
stuck in the "pressed" state when frames are dropped, I wanted to rule out performance problems with sun buttons. In the patch below, I replace the TextPushButton with Text + PressListener. The problem persists.
Test device Samsung Operating System Win 11 Browser Chrome Problem description For https://github.com/phetsims/qa/issues/1091 On the second screen, the lightbulb may not light up in conditions when it should. Specifically, if you change the magnetic field by flipping the magnet's polarity, the bulb only sometimes lights. Steps to reproduce
Visuals![lightupflip](https://github.com/phetsims/faradays-electromagnetic-lab/assets/41024075/344978d2-c3b5-44d9-8c1f-d8eb74d5b648)
Troubleshooting information: