Skip to content

Commit

Permalink
Making the TimeCounter dynamic, see phetsims/chipper#1302
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanolson committed Aug 13, 2022
1 parent fe7a2e0 commit 025f4fc
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 27 deletions.
5 changes: 3 additions & 2 deletions js/common/GravityAndOrbitsScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import EnumerationProperty from '../../../axon/js/EnumerationProperty.js';
import TimeSpeed from '../../../scenery-phet/js/TimeSpeed.js';
import Multilink from '../../../axon/js/Multilink.js';
import optionize from '../../../phet-core/js/optionize.js';
import IProperty from '../../../axon/js/IProperty.js';

// constants
const PLAY_AREA_WIDTH = GravityAndOrbitsSceneView.STAGE_SIZE.width;
Expand Down Expand Up @@ -77,7 +78,7 @@ class GravityAndOrbitsScene extends PhetioObject {
public velocityVectorScale: number;
public gridSpacing: number;
public gridCenter: Vector2;
public timeFormatter: ( arg0: number ) => string;
public timeFormatter: ( numberProperty: IProperty<number> ) => IProperty<string>;
public measuringTapeStartPointProperty: Vector2Property;
public measuringTapeEndPointProperty: Vector2Property;
public isPlayingProperty: BooleanProperty;
Expand All @@ -104,7 +105,7 @@ class GravityAndOrbitsScene extends PhetioObject {
* @param pairs
* @param [providedOptions]
*/
public constructor( model: GravityAndOrbitsModel, modeConfig: ModeConfig, timeFormatter: ( arg0: number ) => string, iconImage: Node, velocityVectorScale: number, massReadoutFactory: ( arg0: BodyNode, arg1: Property<boolean> ) => Node, gridSpacing: number, tandem: Tandem,
public constructor( model: GravityAndOrbitsModel, modeConfig: ModeConfig, timeFormatter: ( numberProperty: IProperty<number> ) => IProperty<string>, iconImage: Node, velocityVectorScale: number, massReadoutFactory: ( arg0: BodyNode, arg1: Property<boolean> ) => Node, gridSpacing: number, tandem: Tandem,
sceneViewTandem: Tandem, bodies: Body[], pairs: Pair[], providedOptions?: GravityAndOrbitsSceneOptions ) {

const forceScale = modeConfig.forceScale;
Expand Down
63 changes: 46 additions & 17 deletions js/common/SceneFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,12 @@ import Tandem from '../../../tandem/js/Tandem.js';
import BodyNode from './view/BodyNode.js';
import TReadOnlyProperty from '../../../axon/js/TReadOnlyProperty.js';
import optionize from '../../../phet-core/js/optionize.js';
import IProperty from '../../../axon/js/IProperty.js';
import TinyProperty from '../../../axon/js/TinyProperty.js';

const earthDaysString = gravityAndOrbitsStrings.earthDays;
const earthDayString = gravityAndOrbitsStrings.earthDay;
const earthMinutesString = gravityAndOrbitsStrings.earthMinutes;
const earthMinuteString = gravityAndOrbitsStrings.earthMinute;
const earthString = gravityAndOrbitsStrings.earth;
const ourMoonString = gravityAndOrbitsStrings.ourMoon;
const ourSunString = gravityAndOrbitsStrings.ourSun;
const pattern0Value1UnitsString = gravityAndOrbitsStrings.pattern[ '0value' ][ '1units' ];
const spaceStationString = gravityAndOrbitsStrings.spaceStation;

// These constants are only used in SceneFactory, and SceneFactory is used to create the specific model instantiations,
Expand Down Expand Up @@ -118,7 +115,7 @@ class SceneFactory {
this.scenes.push( new GravityAndOrbitsScene(
model,
planetStar,
scaledDays(),
scaledDays,
this.createIconImage( true, true, false, false ),
SUN_MODES_VELOCITY_SCALE,
readoutInEarthMasses,
Expand Down Expand Up @@ -150,7 +147,7 @@ class SceneFactory {
this.scenes.push( new GravityAndOrbitsScene(
model,
sunEarthMoon,
scaledDays(),
scaledDays,
this.createIconImage( true, true, true, false ),
SUN_MODES_VELOCITY_SCALE,
readoutInEarthMasses,
Expand All @@ -176,7 +173,7 @@ class SceneFactory {
this.scenes.push( new GravityAndOrbitsScene(
model,
earthMoon,
scaledDays(),
scaledDays,
this.createIconImage( false, true, true, false ),
SUN_MODES_VELOCITY_SCALE * 0.06,
readoutInEarthMasses,
Expand Down Expand Up @@ -378,22 +375,54 @@ const getSwitchableRenderer = ( image1: string | HTMLImageElement, image2: strin
/**
* Have to artificially scale up the time readout so that Sun/Earth/Moon scene has a stable orbit with correct periods
*/
const scaledDays = () => {
return ( time: number ) => {
const value = ( time / GravityAndOrbitsClock.SECONDS_PER_DAY );
const units = ( value === 1 ) ? earthDayString : earthDaysString;
return StringUtils.format( pattern0Value1UnitsString, Utils.toFixed( value, 0 ), units );
const scaledDays = ( timeProperty: IProperty<number> ) => {
// Can't use a DerivedProperty, because it needs to be settable
const property = new TinyProperty( '' );

const earthDayStringProperty = gravityAndOrbitsStrings.earthDayProperty;
const earthDaysStringProperty = gravityAndOrbitsStrings.earthDaysProperty;
const patternStringProperty = gravityAndOrbitsStrings.pattern[ '0value' ][ '1unitsProperty' ];

const update = () => {
const value = ( timeProperty.value / GravityAndOrbitsClock.SECONDS_PER_DAY );
const units = ( value === 1 ) ? earthDayStringProperty.value : earthDaysStringProperty.value;
property.value = StringUtils.format( patternStringProperty.value, Utils.toFixed( value, 0 ), units );
};
update();

earthDayStringProperty.lazyLink( update );
earthDaysStringProperty.lazyLink( update );
patternStringProperty.lazyLink( update );
timeProperty.lazyLink( update );

return property;
};

/**
* Create a function that converts SI (seconds) to a string indicating elapsed minutes, used in formatting the
* elapsed clock readout
*/
const formatMinutes = ( time: number ) => {
const value = ( time / SECONDS_PER_MINUTE );
const units = ( value === 1 ) ? earthMinuteString : earthMinutesString;
return StringUtils.format( pattern0Value1UnitsString, Utils.toFixed( value, 0 ), units );
const formatMinutes = ( timeProperty: IProperty<number> ) => {
// Can't use a DerivedProperty, because it needs to be settable
const property = new TinyProperty( '' );

const earthMinuteStringProperty = gravityAndOrbitsStrings.earthMinuteProperty;
const earthMinutesStringProperty = gravityAndOrbitsStrings.earthMinutesProperty;
const patternStringProperty = gravityAndOrbitsStrings.pattern[ '0value' ][ '1unitsProperty' ];

const update = () => {
const value = ( timeProperty.value / SECONDS_PER_MINUTE );
const units = ( value === 1 ) ? earthMinuteStringProperty.value : earthMinutesStringProperty.value;
property.value = StringUtils.format( patternStringProperty.value, Utils.toFixed( value, 0 ), units );
};
update();

earthMinuteStringProperty.lazyLink( update );
earthMinutesStringProperty.lazyLink( update );
patternStringProperty.lazyLink( update );
timeProperty.lazyLink( update );

return property;
};

class Satellite extends Body {
Expand Down
15 changes: 7 additions & 8 deletions js/common/view/TimeCounter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @author Aaron Davis (PhET Interactive Simulations)
*/

import IProperty from '../../../../axon/js/IProperty.js';
import merge from '../../../../phet-core/js/merge.js';
import PhetFont from '../../../../scenery-phet/js/PhetFont.js';
import StopwatchNode from '../../../../scenery-phet/js/StopwatchNode.js';
Expand All @@ -23,15 +24,14 @@ import GravityAndOrbitsClock from '../model/GravityAndOrbitsClock.js';
const FONT_SIZE = 22;

class TimeCounter extends Node {
private readonly timeListener: ( time: number ) => void;

/**
* @param timeFormatter
* @param clock
* @param tandem
* @param [providedOptions]
*/
public constructor( timeFormatter: ( time: number ) => string, clock: GravityAndOrbitsClock, tandem: Tandem, providedOptions?: NodeOptions ) {
public constructor( timeFormatter: ( timeProperty: IProperty<number> ) => IProperty<string>, clock: GravityAndOrbitsClock, tandem: Tandem, providedOptions?: NodeOptions ) {
super();

// day text counter
Expand All @@ -52,14 +52,13 @@ class TimeCounter extends Node {
widthSizable: true
} );

dayText.textProperty = timeFormatter( clock.timeProperty );

// update text representation of day
this.timeListener = time => {
clock.timeProperty.link( time => {
assert && assert( !isNaN( time ), 'time should be a number' );
dayText.setText( timeFormatter( time ) );
dayText.right = clearButton.right;
clearButton.enabled = ( time !== 0 );
};
clock.timeProperty.link( this.timeListener );
clearButton.enabled = time !== 0;
} );

this.addChild( new VBox( {
align: 'right',
Expand Down

0 comments on commit 025f4fc

Please sign in to comment.