diff --git a/js/common/model/BendingLightModel.ts b/js/common/model/BendingLightModel.ts index 1d859b16..ce4808c5 100644 --- a/js/common/model/BendingLightModel.ts +++ b/js/common/model/BendingLightModel.ts @@ -17,6 +17,7 @@ import BendingLightConstants from '../BendingLightConstants.js'; import Laser from './Laser.js'; import LightRay from './LightRay.js'; import MediumColorFactory from './MediumColorFactory.js'; +import LaserViewEnum from './LaserViewEnum.js'; // constants const DEFAULT_LASER_DISTANCE_FROM_PIVOT = 9.225E-6; @@ -30,13 +31,13 @@ abstract class BendingLightModel { readonly modelWidth: number; readonly modelHeight: number; readonly allowWebGL: boolean; - readonly laserViewProperty: Property; - readonly wavelengthProperty: Property; - readonly speedProperty: Property; - private readonly indexOfRefractionProperty: Property; - readonly showNormalProperty: Property; - readonly isPlayingProperty: Property; - readonly showAnglesProperty: Property; + readonly laserViewProperty: Property; + readonly wavelengthProperty: Property; + readonly speedProperty: Property; + private readonly indexOfRefractionProperty: Property; + readonly showNormalProperty: Property; + readonly isPlayingProperty: Property; + readonly showAnglesProperty: Property; readonly laser: Laser; static DEFAULT_LASER_DISTANCE_FROM_PIVOT: number; rotationArrowAngleOffset: number | null; @@ -64,9 +65,10 @@ abstract class BendingLightModel { this.allowWebGL = Utils.checkWebGLSupport() && phet.chipper.queryParameters.webgl; // @public (read-only) // @public, Whether the laser is Ray or Wave mode - this.laserViewProperty = new Property( 'ray', { + this.laserViewProperty = new Property( 'ray', { validValues: [ 'wave', 'ray' ] } ); + this.wavelengthProperty = new Property( BendingLightConstants.WAVELENGTH_RED ); this.isPlayingProperty = new Property( true ); diff --git a/js/common/model/IntensityMeter.ts b/js/common/model/IntensityMeter.ts index 73083e73..60a9e7ff 100644 --- a/js/common/model/IntensityMeter.ts +++ b/js/common/model/IntensityMeter.ts @@ -16,11 +16,11 @@ import bendingLight from '../../bendingLight.js'; import Reading from './Reading.js'; class IntensityMeter { - readonly readingProperty: Property; + readonly readingProperty: Property; readonly sensorPositionProperty: Vector2Property; readonly bodyPositionProperty: Vector2Property; private rayReadings: Reading[]; - readonly enabledProperty: Property; + readonly enabledProperty: Property; /** * @param {number} sensorX - sensor x position in model coordinates diff --git a/js/common/model/Laser.ts b/js/common/model/Laser.ts index 25110206..e2a2b8e6 100644 --- a/js/common/model/Laser.ts +++ b/js/common/model/Laser.ts @@ -7,6 +7,7 @@ * @author Chandrashekar Bemagoni (Actual Concepts) */ +import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; import DerivedProperty from '../../../../axon/js/DerivedProperty.js'; import Property from '../../../../axon/js/Property.js'; import Vector2 from '../../../../dot/js/Vector2.js'; @@ -14,15 +15,16 @@ import Vector2Property from '../../../../dot/js/Vector2Property.js'; import bendingLight from '../../bendingLight.js'; import BendingLightConstants from '../BendingLightConstants.js'; import LaserColor from '../view/LaserColor.js'; +import ColorModeEnum from './ColorModeEnum.js'; class Laser { readonly topLeftQuadrant: boolean; - readonly onProperty: Property; - readonly waveProperty: Property; - readonly colorModeProperty: Property; + readonly onProperty: Property; + readonly waveProperty: Property; + readonly colorModeProperty: Property<'white' | 'singleColor'>; readonly emissionPointProperty: Vector2Property; readonly colorProperty: DerivedProperty; - readonly wavelengthProperty: Property; + readonly wavelengthProperty: Property; private readonly directionUnitVector: Vector2; readonly pivotProperty: Vector2Property; @@ -32,13 +34,13 @@ class Laser { * @param {number} angle - laser angle * @param {boolean} topLeftQuadrant - specifies whether laser in topLeftQuadrant */ - constructor( wavelengthProperty: Property, distanceFromPivot: number, angle: number, topLeftQuadrant: boolean ) { + constructor( wavelengthProperty: Property, distanceFromPivot: number, angle: number, topLeftQuadrant: boolean ) { this.topLeftQuadrant = topLeftQuadrant; this.pivotProperty = new Vector2Property( new Vector2( 0, 0 ) ); // @public, point to be pivoted about, and at which the laser points - this.onProperty = new Property( false ); // @public, true if the laser is activated and emitting light - this.waveProperty = new Property( false ); // @public - this.colorModeProperty = new Property( 'singleColor' ); // @public + this.onProperty = new BooleanProperty( false ); // @public, true if the laser is activated and emitting light + this.waveProperty = new BooleanProperty( false ); // @public + this.colorModeProperty = new Property<'white' | 'singleColor'>( 'singleColor' ); // @public this.emissionPointProperty = new Vector2Property( Vector2.createPolar( distanceFromPivot, angle ) ); // @public model the point where light comes out of the laser where the light comes from // @public (read-only) diff --git a/js/common/model/MediumColorFactory.ts b/js/common/model/MediumColorFactory.ts index 50fbcb77..5e8226df 100644 --- a/js/common/model/MediumColorFactory.ts +++ b/js/common/model/MediumColorFactory.ts @@ -15,7 +15,7 @@ import bendingLight from '../../bendingLight.js'; import Substance from './Substance.js'; class MediumColorFactory { - lightTypeProperty: Property; + lightTypeProperty: Property<'singleColor' | 'white'>; // TODO: Single wavelength or single color??? getColorAgainstWhite: ( indexForRed: number ) => Color; getColorAgainstBlack: ( indexForRed: number ) => Color; @@ -81,7 +81,7 @@ const colorBlend = ( a: Color, b: Color, ratio: number ): Color => { ); }; -const createProfile = ( AIR_COLOR:Color, WATER_COLOR:Color, GLASS_COLOR:Color, DIAMOND_COLOR:Color ) => ( indexForRed: number) => { +const createProfile = ( AIR_COLOR: Color, WATER_COLOR: Color, GLASS_COLOR: Color, DIAMOND_COLOR: Color ) => ( indexForRed: number ) => { // precompute to improve readability below const waterIndexForRed = Substance.WATER.indexOfRefractionForRedLight; diff --git a/js/common/model/Substance.ts b/js/common/model/Substance.ts index f454b369..76b5dfc1 100644 --- a/js/common/model/Substance.ts +++ b/js/common/model/Substance.ts @@ -28,7 +28,7 @@ class Substance { readonly indexOfRefractionForRedLight: number; readonly name: string; readonly indexForRed: number; - private readonly custom: boolean; + readonly custom: boolean; static AIR: Substance; static WATER: Substance; static GLASS: Substance; diff --git a/js/common/view/BendingLightScreenView.ts b/js/common/view/BendingLightScreenView.ts index 13b356a0..ecfea538 100644 --- a/js/common/view/BendingLightScreenView.ts +++ b/js/common/view/BendingLightScreenView.ts @@ -22,6 +22,7 @@ import SingleColorLightCanvasNode from './SingleColorLightCanvasNode.js'; import ColorModeEnum from '../model/ColorModeEnum.js'; import LaserViewEnum from '../model/LaserViewEnum.js'; import Tandem from '../../../../tandem/js/Tandem.js'; +import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; type BendingLightScreenViewOptions = { occlusionHandler: () => void, @@ -36,7 +37,7 @@ type BendingLightScreenViewOptions = { }; abstract class BendingLightScreenView extends ScreenView { - protected readonly showProtractorProperty: Property; + protected readonly showProtractorProperty: Property; readonly bendingLightModel: BendingLightModel; protected readonly beforeLightLayer: Node; protected readonly beforeLightLayer2: Node; @@ -130,8 +131,8 @@ abstract class BendingLightScreenView extends ScreenView { this.addChild( this.laserViewLayer ); // add rotation for the laser that show if/when the laser can be rotated about its pivot - const showRotationDragHandlesProperty = new Property( false ); - const showTranslationDragHandlesProperty = new Property( false ); + const showRotationDragHandlesProperty = new BooleanProperty( false ); + const showTranslationDragHandlesProperty = new BooleanProperty( false ); const laserNode = new LaserNode( this.modelViewTransform, @@ -164,7 +165,7 @@ abstract class BendingLightScreenView extends ScreenView { this.addChild( this.afterLightLayer3 ); // switches between ray and wave - bendingLightModel.laserViewProperty.link( laserView => { + bendingLightModel.laserViewProperty.link( ( laserView: LaserViewEnum ) => { bendingLightModel.laser.waveProperty.value = ( laserView === 'wave' ); } ); @@ -174,7 +175,7 @@ abstract class BendingLightScreenView extends ScreenView { } ); - this.visibleBoundsProperty.link( visibleBounds => this.singleColorLightNode.setCanvasBounds( visibleBounds ) ); + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => this.singleColorLightNode.setCanvasBounds( visibleBounds ) ); } /** @@ -206,7 +207,7 @@ abstract class BendingLightScreenView extends ScreenView { * @param {number} laserImageWidth * @protected */ - addLaserHandles( showRotationDragHandlesProperty: Property, showTranslationDragHandlesProperty: Property, + addLaserHandles( showRotationDragHandlesProperty: Property, showTranslationDragHandlesProperty: Property, clockwiseArrowNotAtMax: ( n: number ) => boolean, ccwArrowNotAtMax: ( n: number ) => boolean, laserImageWidth: number ) { const bendingLightModel = this.bendingLightModel; diff --git a/js/common/view/FloatingLayout.ts b/js/common/view/FloatingLayout.ts index 5297b41b..cc1b7f56 100644 --- a/js/common/view/FloatingLayout.ts +++ b/js/common/view/FloatingLayout.ts @@ -10,6 +10,7 @@ import ScreenView from '../../../../joist/js/ScreenView.js'; import bendingLight from '../../bendingLight.js'; import Node from '../../../../scenery/js/nodes/Node.js'; +import Bounds2 from '../../../../dot/js/Bounds2.js'; // The fraction the objects can float out of the layout bounds const floatFraction = 0.3; @@ -27,7 +28,7 @@ const FloatingLayout = { * @param {Node[]} nodes */ floatRight: ( screenView: ScreenView, nodes: Node[] ) => { - screenView.visibleBoundsProperty.link( visibleBounds => { + screenView.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // Let the panels move to the right, but not too far const right = Math.min( visibleBounds.right - leftRightPadding, screenView.layoutBounds.width * ( 1 + floatFraction ) ); @@ -45,7 +46,7 @@ const FloatingLayout = { * @param {number} delta */ floatLeft: ( screenView: ScreenView, nodes: Node[], delta: number = 0 ) => { - screenView.visibleBoundsProperty.link( visibleBounds => { + screenView.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // Let the panels move to the left, but not too far const left = Math.max( visibleBounds.left + leftRightPadding, -screenView.layoutBounds.width * floatFraction ); @@ -62,7 +63,7 @@ const FloatingLayout = { * @param {Node[]} nodes */ floatTop: ( screenView: ScreenView, nodes: Node[] ) => { - screenView.visibleBoundsProperty.link( visibleBounds => { + screenView.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // Let the panels move to the top, but not too far const top = Math.max( visibleBounds.top + topBottomPadding, -screenView.layoutBounds.width * floatFraction ); @@ -79,7 +80,7 @@ const FloatingLayout = { * @param {Node[]} nodes */ floatBottom: ( screenView: ScreenView, nodes: Node[] ) => { - screenView.visibleBoundsProperty.link( visibleBounds => { + screenView.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // Let the panels move to the bottom, but not too far const bottom = Math.min( visibleBounds.bottom - topBottomPadding, screenView.layoutBounds.width * ( 1 + floatFraction ) ); diff --git a/js/common/view/IntensityMeterNode.ts b/js/common/view/IntensityMeterNode.ts index af7916a5..0723e437 100644 --- a/js/common/view/IntensityMeterNode.ts +++ b/js/common/view/IntensityMeterNode.ts @@ -132,11 +132,11 @@ class IntensityMeterNode extends Node { } ); - intensityMeter.sensorPositionProperty.link( sensorPosition => { + intensityMeter.sensorPositionProperty.link( ( sensorPosition: Vector2 ) => { this.probeNode.translation = modelViewTransform.modelToViewPosition( sensorPosition ); } ); - intensityMeter.bodyPositionProperty.link( bodyPosition => { + intensityMeter.bodyPositionProperty.link( ( bodyPosition: Vector2 ) => { this.bodyNode.translation = modelViewTransform.modelToViewPosition( bodyPosition ); } ); diff --git a/js/common/view/LaserNode.ts b/js/common/view/LaserNode.ts index 4267a30a..d138eed6 100644 --- a/js/common/view/LaserNode.ts +++ b/js/common/view/LaserNode.ts @@ -23,6 +23,7 @@ import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransfo import Laser from '../model/Laser.js'; import Tandem from '../../../../tandem/js/Tandem.js'; import SceneryEvent from '../../../../scenery/js/input/SceneryEvent.js'; +import Bounds2 from '../../../../dot/js/Bounds2.js'; type LaserNodeOptions = { tandem: Tandem @@ -46,8 +47,8 @@ class LaserNode extends Node { * there * @param {Object} [options?] */ - constructor( modelViewTransform: ModelViewTransform2, laser: Laser, showRotationDragHandlesProperty: Property, showTranslationDragHandlesProperty: Property, - clampDragAngle: ( n: number ) => number, hasKnob: boolean, dragBoundsProperty: Property, occlusionHandler: ( laserNode: LaserNode ) => void, + constructor( modelViewTransform: ModelViewTransform2, laser: Laser, showRotationDragHandlesProperty: Property, showTranslationDragHandlesProperty: Property, + clampDragAngle: ( n: number ) => number, hasKnob: boolean, dragBoundsProperty: Property, occlusionHandler: ( laserNode: LaserNode ) => void, options?: Partial ) { const filledOptions = merge( { tandem: Tandem.OPTIONAL }, options ) as LaserNodeOptions; @@ -84,8 +85,8 @@ class LaserNode extends Node { // When mousing over or starting to drag the laser, increment the over count. If it is more than zero // then show the drag handles. This ensures they will be shown whenever dragging or over, and they won't flicker - const overCountProperty = new Property( 0 ); - overCountProperty.link( overCount => showRotationDragHandlesProperty.set( overCount > 0 ) ); + const overCountProperty = new Property( 0 ); + overCountProperty.link( ( overCount: number ) => showRotationDragHandlesProperty.set( overCount > 0 ) ); super( merge( { cursor: 'pointer' }, options ) ); @@ -103,7 +104,7 @@ class LaserNode extends Node { const emissionPointEndPosition = new Vector2( 0, 0 ); // When the window reshapes, make sure the laser remains in the play area - dragBoundsProperty.link( dragBounds => { + dragBoundsProperty.link( ( dragBounds: Bounds2 ) => { const center = laser.emissionPointProperty.value; const eroded = dragBounds.erodedXY( lightImageHeight / 2, lightImageHeight / 2 ); @@ -178,7 +179,7 @@ class LaserNode extends Node { phetioDocumentation: 'This Property determines whether the laser can be translated, in the "Prisms" screen only. ' + 'A value of false means the laser cannot be translated, though it may still be rotatable.' } ); - isTranslationEnabledProperty.lazyLink( isEnabled => { + isTranslationEnabledProperty.lazyLink( ( isEnabled: boolean ) => { if ( isEnabled ) { laserPointerNode.addInputListener( translationListener ); laserPointerNode.addInputListener( translationOverListener ); @@ -242,7 +243,7 @@ class LaserNode extends Node { 'the rotation knob on the back of the laser and makes it non-rotatable (though it may still ' + 'be translatable).' } ); - isRotationEnabledProperty.lazyLink( isEnabled => { + isRotationEnabledProperty.lazyLink( ( isEnabled: boolean ) => { if ( isEnabled ) { rotationTarget.addInputListener( rotationListener ); rotationTarget.addInputListener( rotationOverListener ); @@ -257,7 +258,7 @@ class LaserNode extends Node { } ); // update the laser position - laser.emissionPointProperty.link( newEmissionPoint => { + laser.emissionPointProperty.link( ( newEmissionPoint: Vector2 ) => { const emissionPointX = modelViewTransform.modelToViewX( newEmissionPoint.x ); const emissionPointY = modelViewTransform.modelToViewY( newEmissionPoint.y ); this.setTranslation( emissionPointX, emissionPointY ); diff --git a/js/common/view/MediumControlPanel.ts b/js/common/view/MediumControlPanel.ts index 216c10f2..1d432d1b 100644 --- a/js/common/view/MediumControlPanel.ts +++ b/js/common/view/MediumControlPanel.ts @@ -53,9 +53,9 @@ type MediumControlPanelOptions = { class MediumControlPanel extends Node { private readonly mediumColorFactory: MediumColorFactory; - private readonly mediumProperty: Property; - private readonly laserWavelengthProperty: Property; - private readonly mediumIndexProperty: Property; + private readonly mediumProperty: Property; + private readonly laserWavelengthProperty: Property; + private readonly mediumIndexProperty: Property; /** * @param {BendingLightScreenView} view - view of the simulation @@ -67,7 +67,7 @@ class MediumControlPanel extends Node { * @param {number} decimalPlaces - decimalPlaces to show for index of refraction * @param {Object} [options] - options that can be passed on to the underlying node */ - constructor( view: BendingLightScreenView, mediumColorFactory: MediumColorFactory, mediumProperty: Property, name: string, textFieldVisible: boolean, laserWavelength: Property, + constructor( view: BendingLightScreenView, mediumColorFactory: MediumColorFactory, mediumProperty: Property, name: string, textFieldVisible: boolean, laserWavelength: Property, decimalPlaces: number, options?: Partial ) { super(); @@ -336,7 +336,7 @@ class MediumControlPanel extends Node { } updateComboBox(); } ); - comboBoxSubstanceProperty.link( selected => { + comboBoxSubstanceProperty.link( ( selected: Substance ) => { if ( !selected.custom ) { this.setSubstance( selected ); } diff --git a/js/common/view/MediumNode.ts b/js/common/view/MediumNode.ts index 9df801d8..4a978850 100644 --- a/js/common/view/MediumNode.ts +++ b/js/common/view/MediumNode.ts @@ -11,6 +11,7 @@ import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransfo import Node from '../../../../scenery/js/nodes/Node.js'; import Path from '../../../../scenery/js/nodes/Path.js'; import bendingLight from '../../bendingLight.js'; +import Medium from '../model/Medium.js'; class MediumNode extends Node { @@ -18,7 +19,7 @@ class MediumNode extends Node { * @param {ModelViewTransform2} modelViewTransform - converts between model and view co-ordinates * @param {Property.} mediumProperty - specifies medium */ - constructor( modelViewTransform: ModelViewTransform2, mediumProperty: Property ) { + constructor( modelViewTransform: ModelViewTransform2, mediumProperty: Property ) { super( { pickable: false } ); // user can't interact with the medium except through control panels. // add the shape that paints the medium @@ -29,7 +30,7 @@ class MediumNode extends Node { this.addChild( mediumRectangleNode ); // Update whenever the medium changes - mediumProperty.link( medium => { + mediumProperty.link( (medium:Medium) => { // @ts-ignore mediumRectangleNode.fill = medium.color; } ); diff --git a/js/common/view/RotationDragHandle.ts b/js/common/view/RotationDragHandle.ts index ec28cea1..22ab8ff8 100644 --- a/js/common/view/RotationDragHandle.ts +++ b/js/common/view/RotationDragHandle.ts @@ -31,7 +31,7 @@ class RotationDragHandle extends Node { * @param {number} rotationArrowAngleOffset - for unknown reasons the rotation arrows are off by PI/4 on the * intro/more-tools screen, so account for that here. */ - constructor( modelViewTransform: ModelViewTransform2, laser: Laser, deltaAngle: number, showDragHandlesProperty: Property, notAtMax: ( n: number ) => boolean, + constructor( modelViewTransform: ModelViewTransform2, laser: Laser, deltaAngle: number, showDragHandlesProperty: Property, notAtMax: ( n: number ) => boolean, laserImageWidth: number, rotationArrowAngleOffset: number ) { super(); diff --git a/js/common/view/TranslationDragHandle.ts b/js/common/view/TranslationDragHandle.ts index 5044e782..281bc252 100644 --- a/js/common/view/TranslationDragHandle.ts +++ b/js/common/view/TranslationDragHandle.ts @@ -27,7 +27,7 @@ class TranslationDragHandle extends Node { * @param {number} laserImageWidth - width of the laser * @constructor */ - constructor( modelViewTransform: ModelViewTransform2, laser: Laser, dx: number, dy: number, showDragHandlesProperty: Property, laserImageWidth: number ) { + constructor( modelViewTransform: ModelViewTransform2, laser: Laser, dx: number, dy: number, showDragHandlesProperty: Property, laserImageWidth: number ) { super(); diff --git a/js/common/view/WavelengthControl.ts b/js/common/view/WavelengthControl.ts index 4239b742..d60f5f64 100644 --- a/js/common/view/WavelengthControl.ts +++ b/js/common/view/WavelengthControl.ts @@ -33,10 +33,10 @@ class WavelengthControl extends Node { * @param {Property.} enabledProperty * @param {number} trackWidth */ - constructor( wavelengthProperty: Property, enabledProperty: Property, trackWidth: number ) { - const wavelengthPropertyNM = new Property( wavelengthProperty.value * 1E9, { reentrant: true } ); + constructor( wavelengthProperty: Property, enabledProperty: Property, trackWidth: number ) { + const wavelengthPropertyNM = new Property( wavelengthProperty.value * 1E9, { reentrant: true } ); - wavelengthProperty.link( wavelength => { + wavelengthProperty.link( ( wavelength: number ) => { wavelengthPropertyNM.value = wavelength * 1E9; } ); // Add WavelengthSlider node @@ -83,7 +83,7 @@ class WavelengthControl extends Node { } ); // disable the minus button at minimum wavelength and plus button at max wavelength - wavelengthPropertyNM.link( wavelength => { + wavelengthPropertyNM.link( ( wavelength: number ) => { plusButton.enabled = ( wavelength < BendingLightConstants.LASER_MAX_WAVELENGTH ); minusButton.enabled = ( wavelength > VisibleColor.MIN_WAVELENGTH ); } ); @@ -117,14 +117,14 @@ class WavelengthControl extends Node { wavelengthSlider ] } ); - enabledProperty.link( enabled => { + enabledProperty.link( ( enabled: boolean ) => { // set the opacity when not selected this.setPickable( enabled ); this.opacity = enabled ? 1 : 0.4; } ); - wavelengthPropertyNM.link( wavelength => { + wavelengthPropertyNM.link( ( wavelength: number) => { // set the laser wavelength according to the slider wavelength wavelengthProperty.set( wavelength / 1E9 ); diff --git a/js/intro/model/IntroModel.ts b/js/intro/model/IntroModel.ts index e3c18037..f864178f 100644 --- a/js/intro/model/IntroModel.ts +++ b/js/intro/model/IntroModel.ts @@ -35,8 +35,8 @@ const CHARACTERISTIC_LENGTH = BendingLightConstants.WAVELENGTH_RED; const BEAM_LENGTH = 1E-3; class IntroModel extends BendingLightModel { - topMediumProperty: Property; - bottomMediumProperty: Property; + topMediumProperty: Property; + bottomMediumProperty: Property; time: number; indexOfRefractionOfTopMediumProperty: DerivedProperty; indexOfRefractionOfBottomMediumProperty: DerivedProperty; diff --git a/js/intro/view/AngleNode.ts b/js/intro/view/AngleNode.ts index 8bec2149..96456be3 100644 --- a/js/intro/view/AngleNode.ts +++ b/js/intro/view/AngleNode.ts @@ -46,7 +46,7 @@ class AngleNode extends Node { * @param {ModelViewTransform2} modelViewTransform * @param {function} addStepListener - */ - constructor( showAnglesProperty: Property, laserOnProperty: Property, showNormalProperty: Property, rays: ObservableArray, modelViewTransform: ModelViewTransform2, + constructor( showAnglesProperty: Property, laserOnProperty: Property, showNormalProperty: Property, rays: ObservableArray, modelViewTransform: ModelViewTransform2, addStepListener: ( x: () => void ) => void ) { super(); @@ -95,7 +95,7 @@ class AngleNode extends Node { // Only redraw when necessary to improve performance. let dirty = true; - showNormalProperty.link( showNormal => { + showNormalProperty.link( ( showNormal: boolean) => { // Only show the top marker when the normal is not shown, since they would interfere if both shown together upperMark.visible = !showNormal; diff --git a/js/intro/view/IntroScreenView.ts b/js/intro/view/IntroScreenView.ts index 19659be7..db04495d 100644 --- a/js/intro/view/IntroScreenView.ts +++ b/js/intro/view/IntroScreenView.ts @@ -43,6 +43,7 @@ import WaveCanvasNode from './WaveCanvasNode.js'; import WaveWebGLNode from './WaveWebGLNode.js'; import BendingLightModel from '../../common/model/BendingLightModel.js'; import TimeSpeed from '../../../../scenery-phet/js/TimeSpeed.js'; +import LaserViewEnum from '../../common/model/LaserViewEnum.js'; const anglesString = bendingLightStrings.angles; const materialString = bendingLightStrings.material; @@ -58,8 +59,8 @@ class IntroScreenView extends BendingLightScreenView { stepEmitter: Emitter; topMediumControlPanel: MediumControlPanel; bottomMediumControlPanel: MediumControlPanel; - dropInToolbox: ( node: Node, enabledProperty: Property ) => void; - bumpLeft: ( node: Node, positionProperty: Property ) => void; + dropInToolbox: ( node: Node, enabledProperty: Property ) => void; + bumpLeft: ( node: Node, positionProperty: Property ) => void; toolbox: Panel; timeControlNode: TimeControlNode; @@ -263,7 +264,7 @@ class IntroScreenView extends BendingLightScreenView { } ); protractorNodeIcon.mouseArea = Shape.bounds( protractorNodeIcon.localBounds ); protractorNodeIcon.touchArea = Shape.bounds( protractorNodeIcon.localBounds ); - this.showProtractorProperty.link( showProtractor => { + this.showProtractorProperty.link( ( showProtractor: boolean ) => { protractorNodeIcon.visible = !showProtractor; } ); @@ -274,7 +275,7 @@ class IntroScreenView extends BendingLightScreenView { const protractorPositionProperty = new Property( protractorPosition ); // When a node is released, check if it is over the toolbox. If so, drop it in. - const dropInToolbox = ( node: Node, enabledProperty: Property ) => { + const dropInToolbox = ( node: Node, enabledProperty: Property ) => { if ( node.getGlobalBounds().intersectsBounds( this.toolbox.getGlobalBounds() ) ) { enabledProperty.value = false; } @@ -299,14 +300,14 @@ class IntroScreenView extends BendingLightScreenView { const modelViewTransform = this.modelViewTransform; // When a node is dropped behind a control panel, move it to the side so it won't be lost. - const bumpLeft = ( node: Node, positionProperty: Property ) => { + const bumpLeft = ( node: Node, positionProperty: Property ) => { while ( node.getGlobalBounds().intersectsBounds( topMediumControlPanel.getGlobalBounds() ) || node.getGlobalBounds().intersectsBounds( bottomMediumControlPanel.getGlobalBounds() ) ) { positionProperty.value = positionProperty.value.plusXY( modelViewTransform.viewToModelDeltaX( -20 ), 0 ); } }; - protractorPositionProperty.link( protractorPosition => { + protractorPositionProperty.link( ( protractorPosition: Vector2 ) => { protractorNode.center = protractorPosition; } ); @@ -321,7 +322,7 @@ class IntroScreenView extends BendingLightScreenView { intensityMeterNodeIcon.touchArea = Shape.bounds( intensityMeterNodeIcon.localBounds ); const intensityMeterNode = new IntensityMeterNode( this.modelViewTransform, introModel.intensityMeter ); - introModel.intensityMeter.enabledProperty.link( enabled => { + introModel.intensityMeter.enabledProperty.link( ( enabled: boolean ) => { intensityMeterNode.visible = enabled; intensityMeterNodeIcon.visible = !enabled; } ); @@ -413,7 +414,7 @@ class IntroScreenView extends BendingLightScreenView { if ( !hasMoreTools ) { // show play pause and step buttons only in wave view - introModel.laserViewProperty.link( laserType => this.timeControlNode.setVisible( laserType === 'wave' ) ); + introModel.laserViewProperty.link( ( laserType: LaserViewEnum ) => this.timeControlNode.setVisible( laserType === 'wave' ) ); } FloatingLayout.floatRight( this, [ topMediumControlPanel, bottomMediumControlPanel, resetAllButton ] ); @@ -429,7 +430,7 @@ class IntroScreenView extends BendingLightScreenView { this.toolbox.bottom = checkboxPanel.top - 10; } ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { protractorNodeListener.setDragBounds( visibleBounds ); probeListener.setDragBounds( modelViewTransform.viewToModelBounds( visibleBounds ) ); @@ -497,7 +498,6 @@ class IntroScreenView extends BendingLightScreenView { * @private */ addLightNodes( bendingLightModel: BendingLightModel ) { - // super.addLightNodes( bendingLightModel ); this.addChild( this.incidentWaveLayer ); @@ -511,7 +511,7 @@ class IntroScreenView extends BendingLightScreenView { canvasBounds: new Bounds2( 0, 0, 1000, 1000 ) } ); this.incidentWaveLayer.addChild( waveCanvasNode ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { waveCanvasNode.setCanvasBounds( visibleBounds ); } ); } diff --git a/js/intro/view/LaserTypeAquaRadioButtonGroup.ts b/js/intro/view/LaserTypeAquaRadioButtonGroup.ts index dea67746..a23e737f 100644 --- a/js/intro/view/LaserTypeAquaRadioButtonGroup.ts +++ b/js/intro/view/LaserTypeAquaRadioButtonGroup.ts @@ -13,6 +13,7 @@ import AquaRadioButton from '../../../../sun/js/AquaRadioButton.js'; import bendingLightStrings from '../../bendingLightStrings.js'; import bendingLight from '../../bendingLight.js'; import Property from '../../../../axon/js/Property.js'; +import LaserViewEnum from '../../common/model/LaserViewEnum.js'; const rayString = bendingLightStrings.ray; const waveString = bendingLightStrings.wave; @@ -22,7 +23,7 @@ class LaserTypeAquaRadioButtonGroup extends VBox { /** * @param laserTypeProperty 'ray' or 'wave' */ - constructor( laserTypeProperty: Property ) { + constructor( laserTypeProperty: Property ) { const radioButtonOptions = { radius: 6, font: new PhetFont( 12 ) diff --git a/js/more-tools/model/DataPoint.ts b/js/more-tools/model/DataPoint.ts index 523f0841..3f1b1333 100644 --- a/js/more-tools/model/DataPoint.ts +++ b/js/more-tools/model/DataPoint.ts @@ -10,8 +10,8 @@ import bendingLight from '../../bendingLight.js'; class DataPoint { - private readonly time: number; - private readonly value: number; + readonly time: number; + readonly value: number; /** * @param {number} time - time of simulation diff --git a/js/more-tools/model/Probe.ts b/js/more-tools/model/Probe.ts index 4192b86c..6c12d71d 100644 --- a/js/more-tools/model/Probe.ts +++ b/js/more-tools/model/Probe.ts @@ -6,7 +6,7 @@ import Vector2 from '../../../../dot/js/Vector2.js'; import DataPoint from './DataPoint.js'; class Probe { - readonly seriesProperty: Property; + readonly seriesProperty: Property>; readonly positionProperty: Vector2Property; /** diff --git a/js/more-tools/model/Series.ts b/js/more-tools/model/Series.ts index 482363bc..85cc3781 100644 --- a/js/more-tools/model/Series.ts +++ b/js/more-tools/model/Series.ts @@ -10,16 +10,17 @@ import Property from '../../../../axon/js/Property.js'; import Color from '../../../../scenery/js/util/Color.js'; import bendingLight from '../../bendingLight.js'; +import DataPoint from './DataPoint.js'; class Series { - readonly seriesProperty: Property; + readonly seriesProperty: Property; readonly color: Color; /** * @param {Property.<[]>} seriesProperty - contains data points of series * @param {Color} color - color of series */ - constructor( seriesProperty: Property, color: Color ) { + constructor( seriesProperty: Property, color: Color ) { // @public (read-only) this.seriesProperty = seriesProperty; diff --git a/js/more-tools/model/VelocitySensor.ts b/js/more-tools/model/VelocitySensor.ts index fd37162c..4ec2e419 100644 --- a/js/more-tools/model/VelocitySensor.ts +++ b/js/more-tools/model/VelocitySensor.ts @@ -16,7 +16,7 @@ import bendingLight from '../../bendingLight.js'; class VelocitySensor { readonly positionProperty: Vector2Property; readonly valueProperty: Vector2Property; - readonly enabledProperty: Property; + readonly enabledProperty: Property; readonly isArrowVisibleProperty: DerivedProperty; constructor() { diff --git a/js/more-tools/model/WaveSensor.ts b/js/more-tools/model/WaveSensor.ts index a7f7b43e..85ad937b 100644 --- a/js/more-tools/model/WaveSensor.ts +++ b/js/more-tools/model/WaveSensor.ts @@ -19,7 +19,7 @@ class WaveSensor { probe1: Probe; probe2: Probe; bodyPositionProperty: Vector2Property; - enabledProperty: Property; + enabledProperty: Property; probe1Value: ( position: Vector2 ) => { time: number, magnitude: number } | null; probe2Value: ( position: Vector2 ) => { time: number, magnitude: number } | null; diff --git a/js/more-tools/view/ChartNode.ts b/js/more-tools/view/ChartNode.ts index 09d8b7ef..215156cf 100644 --- a/js/more-tools/view/ChartNode.ts +++ b/js/more-tools/view/ChartNode.ts @@ -31,7 +31,7 @@ class SeriesNode extends Node { * frames * @param {Bounds2} chartBounds - bounds of the chart node */ - constructor( series: Series, modelViewTransformProperty: Property, chartBounds: Bounds2 ) { + constructor( series: Series, modelViewTransformProperty: Property, chartBounds: Bounds2 ) { super(); @@ -54,7 +54,7 @@ class ChartNode extends Node { chartBounds: Bounds2; seriesArray: Series[]; timeWidth: number; - modelViewTransformProperty: Property; + modelViewTransformProperty: Property; gridLines: ObservableArray<{ x1: number, y1: number, x2: number, y2: number, lineDashOffset: number }>; gridCanvasNode: GridCanvasNode; diff --git a/js/more-tools/view/GridCanvasNode.ts b/js/more-tools/view/GridCanvasNode.ts index 2c4fc30e..056da9ca 100644 --- a/js/more-tools/view/GridCanvasNode.ts +++ b/js/more-tools/view/GridCanvasNode.ts @@ -12,9 +12,10 @@ import Property from '../../../../axon/js/Property.js'; import CanvasNode from '../../../../scenery/js/nodes/CanvasNode.js'; import bendingLight from '../../bendingLight.js'; +import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransform2'; class GridCanvasNode extends CanvasNode { - modelViewTransformProperty: Property; + modelViewTransformProperty: Property; strokeDash: number[]; gridLines: ObservableArray<{ x1: number, y1: number, x2: number, y2: number, lineDashOffset: number }>; @@ -24,7 +25,7 @@ class GridCanvasNode extends CanvasNode { * @param {array.} strokeDash * @param {Object} [options] - options that can be passed on to the underlying node */ - constructor( gridLines: ObservableArray<{ x1: number, y1: number, x2: number, y2: number, lineDashOffset: number }>, modelViewTransformProperty: Property, strokeDash: number[], options?: Partial ) { + constructor( gridLines: ObservableArray<{ x1: number, y1: number, x2: number, y2: number, lineDashOffset: number }>, modelViewTransformProperty: Property, strokeDash: number[], options?: Partial ) { super( options ); this.gridLines = gridLines; // @private diff --git a/js/more-tools/view/MoreToolsScreenView.ts b/js/more-tools/view/MoreToolsScreenView.ts index 60a2d7b9..d954e683 100644 --- a/js/more-tools/view/MoreToolsScreenView.ts +++ b/js/more-tools/view/MoreToolsScreenView.ts @@ -26,6 +26,7 @@ import WaveSensorNode from './WaveSensorNode.js'; import LaserViewEnum from '../../common/model/LaserViewEnum.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import BendingLightModel from '../../common/model/BendingLightModel.js'; +import Bounds2 from '../../../../dot/js/Bounds2.js'; // constants const arrowScale = 1.5E-14; @@ -99,7 +100,7 @@ class MoreToolsScreenView extends IntroScreenView { const dropInToolbox = this.dropInToolbox; - const createMovableDragHandler = ( node: Node, positionProperty: Property, enabledProperty: Property ) => { + const createMovableDragHandler = ( node: Node, positionProperty: Property, enabledProperty: Property ) => { return new MovableDragHandler( positionProperty, { modelViewTransform: modelViewTransform, endDrag: () => { @@ -140,7 +141,7 @@ class MoreToolsScreenView extends IntroScreenView { waveSensor.enabledProperty.set( true ); // Center the body label on the pointer - const pt = waveSensorNode.bodyNode.globalToParentPoint( event.pointer.point as Vector2) + const pt = waveSensorNode.bodyNode.globalToParentPoint( event.pointer.point as Vector2 ) .plusXY( 0, -waveSensorNode.bodyNode.height / 2 + 5 ); waveSensor.bodyPositionProperty.value = modelViewTransform.viewToModelPosition( pt ); waveSensorNode.resetRelativePositions(); @@ -148,7 +149,7 @@ class MoreToolsScreenView extends IntroScreenView { } ) ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // The body node origin is at its top left, so translate the allowed drag area so that the center of the body // node will remain in bounds @@ -186,7 +187,7 @@ class MoreToolsScreenView extends IntroScreenView { scale: 2 } ); - moreToolsModel.velocitySensor.enabledProperty.link( enabled => { + moreToolsModel.velocitySensor.enabledProperty.link( ( enabled: boolean) => { velocitySensorIconNode.visible = !enabled; velocitySensorNode.visible = enabled; } ); @@ -211,12 +212,12 @@ class MoreToolsScreenView extends IntroScreenView { this.moreToolsModel.velocitySensor.enabledProperty.value = true; // Center the protractor on the pointer - const viewPosition = velocitySensorNode.globalToParentPoint( event.pointer.point as Vector2); + const viewPosition = velocitySensorNode.globalToParentPoint( event.pointer.point as Vector2 ); const velocitySensorModelPosition = this.modelViewTransform.viewToModelPosition( viewPosition ); this.moreToolsModel.velocitySensor.positionProperty.set( velocitySensorModelPosition ); } ) ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { // The body node origin is at its top left, so translate the allowed drag area so that the center of the body // node will remain in bounds diff --git a/js/more-tools/view/SeriesCanvasNode.ts b/js/more-tools/view/SeriesCanvasNode.ts index 819be4f5..c54bbf89 100644 --- a/js/more-tools/view/SeriesCanvasNode.ts +++ b/js/more-tools/view/SeriesCanvasNode.ts @@ -10,10 +10,12 @@ import Property from '../../../../axon/js/Property.js'; import CanvasNode from '../../../../scenery/js/nodes/CanvasNode.js'; import bendingLight from '../../bendingLight.js'; +import DataPoint from '../model/DataPoint.js'; +import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransform2'; class SeriesCanvasNode extends CanvasNode { - seriesProperty: Property; - modelViewTransformProperty: Property; + seriesProperty: Property; + modelViewTransformProperty: Property; color: string; /** @@ -23,7 +25,7 @@ class SeriesCanvasNode extends CanvasNode { * @param {string} color - color of the series * @param {Object} [options] - options that can be passed on to the underlying node */ - constructor( seriesProperty: Property, modelViewTransformProperty: Property, color: string, options?: Partial ) { + constructor( seriesProperty: Property, modelViewTransformProperty: Property, color: string, options?: Partial ) { super( options ); this.seriesProperty = seriesProperty; // @private diff --git a/js/more-tools/view/VelocitySensorNode.ts b/js/more-tools/view/VelocitySensorNode.ts index 2f8d33c9..53219547 100644 --- a/js/more-tools/view/VelocitySensorNode.ts +++ b/js/more-tools/view/VelocitySensorNode.ts @@ -135,7 +135,7 @@ class VelocitySensorNode extends Node { } ); this.bodyNode.addChild( this.arrowShape ); - velocitySensor.valueProperty.link( velocity => { + velocitySensor.valueProperty.link( ( velocity: Vector2) => { const positionX = modelViewTransform.modelToViewDeltaX( velocity.x ) * arrowScale; const positionY = modelViewTransform.modelToViewDeltaY( velocity.y ) * arrowScale; @@ -151,7 +151,7 @@ class VelocitySensorNode extends Node { velocitySensor.isArrowVisibleProperty.linkAttribute( this.arrowShape, 'visible' ); // update the velocity node position - velocitySensor.positionProperty.link( position => { + velocitySensor.positionProperty.link( ( position: Vector2) => { const velocitySensorXPosition = modelViewTransform.modelToViewX( position.x ); const velocitySensorYPosition = modelViewTransform.modelToViewY( position.y ); this.setTranslation( velocitySensorXPosition, velocitySensorYPosition ); diff --git a/js/more-tools/view/WaveSensorNode.ts b/js/more-tools/view/WaveSensorNode.ts index 4db1540a..f7842b34 100644 --- a/js/more-tools/view/WaveSensorNode.ts +++ b/js/more-tools/view/WaveSensorNode.ts @@ -195,7 +195,7 @@ class WaveSensorNode extends Node { this.addChild( this.wire2Node ); // Synchronize the body position with the model (centered on the model point) - waveSensor.bodyPositionProperty.link( position => { + waveSensor.bodyPositionProperty.link( ( position: Vector2 ) => { this.bodyNode.center = modelViewTransform.modelToViewPosition( position ); } ); diff --git a/js/prisms/model/BendingLightCircle.ts b/js/prisms/model/BendingLightCircle.ts index 0ba68d0d..62ea71f5 100644 --- a/js/prisms/model/BendingLightCircle.ts +++ b/js/prisms/model/BendingLightCircle.ts @@ -14,10 +14,10 @@ import ColoredRay from './ColoredRay.js'; import PrismIntersection from './PrismIntersection.js'; class BendingLightCircle { - center: Vector2; - centroid: Vector2; - radius: number; - shape: Shape; + readonly center: Vector2; + readonly centroid: Vector2; + readonly radius: number; + readonly shape: Shape; /** * @param {Vector2} center - center of the circle @@ -42,6 +42,10 @@ class BendingLightCircle { return new BendingLightCircle( this.center.plusXY( deltaX, deltaY ), this.radius ); } + getRotatedInstance( angle: number, rotationCenter: Vector2 ) { + return this; + } + /** * Finds the intersections between the edges of the circle and the specified ray * @public diff --git a/js/prisms/model/Polygon.ts b/js/prisms/model/Polygon.ts index ec65022e..adc14131 100644 --- a/js/prisms/model/Polygon.ts +++ b/js/prisms/model/Polygon.ts @@ -19,8 +19,8 @@ class Polygon { private readonly points: Vector2[]; private readonly referencePointIndex: number; private readonly radius: number; - private readonly centroid: Vector2; - private readonly shape: Shape; + readonly centroid: Vector2; + readonly shape: Shape; private readonly center: Vector2 | null; /** diff --git a/js/prisms/model/Prism.ts b/js/prisms/model/Prism.ts index c214e11c..43d28c36 100644 --- a/js/prisms/model/Prism.ts +++ b/js/prisms/model/Prism.ts @@ -10,6 +10,7 @@ import Property from '../../../../axon/js/Property.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import Vector2Property from '../../../../dot/js/Vector2Property.js'; +import Shape from '../../../../kite/js/Shape.js'; import bendingLight from '../../bendingLight.js'; import BendingLightCircle from './BendingLightCircle.js'; import ColoredRay from './ColoredRay.js'; @@ -17,7 +18,7 @@ import Polygon from './Polygon.js'; import SemiCircle from './SemiCircle.js'; class Prism { - shapeProperty: Property; + shapeProperty: Property; positionProperty: Vector2Property; typeName: string; diff --git a/js/prisms/model/PrismsModel.ts b/js/prisms/model/PrismsModel.ts index 9e49d469..5f203dca 100644 --- a/js/prisms/model/PrismsModel.ts +++ b/js/prisms/model/PrismsModel.ts @@ -34,15 +34,15 @@ const WAVELENGTH_RED = BendingLightConstants.WAVELENGTH_RED; const CHARACTERISTIC_LENGTH = WAVELENGTH_RED; class PrismsModel extends BendingLightModel { - prisms: ObservableArray; - intersections: ObservableArray; - manyRaysProperty: Property; - showReflectionsProperty: Property; - showNormalsProperty: Property; - showProtractorProperty: Property; - environmentMediumProperty: Property; - prismMediumProperty: Property; - intersectionStrokeProperty: Property; + readonly prisms: ObservableArray; + readonly intersections: ObservableArray; + readonly manyRaysProperty: Property; + readonly showReflectionsProperty: Property; + readonly showNormalsProperty: Property; + readonly showProtractorProperty: Property; + readonly environmentMediumProperty: Property; + readonly prismMediumProperty: Property; + readonly intersectionStrokeProperty: Property; dirty: boolean; constructor( options?: Partial ) { @@ -56,7 +56,6 @@ class PrismsModel extends BendingLightModel { this.mediumColorFactory = new MediumColorFactory(); - // Show multiple beams to help show how lenses work this.manyRaysProperty = new Property( 1 ); @@ -72,7 +71,7 @@ class PrismsModel extends BendingLightModel { this.prismMediumProperty = new Property( new Medium( Shape.rect( -1, -1, 2, 1 ), Substance.GLASS, this.mediumColorFactory.getColor( Substance.GLASS.indexOfRefractionForRedLight ) ), { reentrant: true } ); this.intersectionStrokeProperty = new Property( 'black' ); - this.laser.colorModeProperty.link( colorMode => { + this.laser.colorModeProperty.link( ( colorMode: 'white' | 'singleColor' ) => { this.intersectionStrokeProperty.value = colorMode === 'white' ? 'white' : 'black'; } ); Property.multilink( [ diff --git a/js/prisms/view/IntersectionNode.ts b/js/prisms/view/IntersectionNode.ts index 5430efbb..1df735ea 100644 --- a/js/prisms/view/IntersectionNode.ts +++ b/js/prisms/view/IntersectionNode.ts @@ -20,7 +20,7 @@ class IntersectionNode extends Line { * @param {Intersection} intersection - specifies details of intersection point and unit normal * @param {Property.} strokeProperty - the stroke to use for the intersection node */ - constructor( modelViewTransform: ModelViewTransform2, intersection: Intersection, strokeProperty: Property ) { + constructor( modelViewTransform: ModelViewTransform2, intersection: Intersection, strokeProperty: Property ) { const centerX = modelViewTransform.modelToViewX( intersection.point.x ); const centerY = modelViewTransform.modelToViewY( intersection.point.y ); diff --git a/js/prisms/view/LaserTypeRadioButtonGroup.ts b/js/prisms/view/LaserTypeRadioButtonGroup.ts index af9084fc..f177269b 100644 --- a/js/prisms/view/LaserTypeRadioButtonGroup.ts +++ b/js/prisms/view/LaserTypeRadioButtonGroup.ts @@ -15,6 +15,7 @@ import Rectangle from '../../../../scenery/js/nodes/Rectangle.js'; import RectangularRadioButtonGroup from '../../../../sun/js/buttons/RectangularRadioButtonGroup.js'; import laserImage from '../../../images/laser_png.js'; import bendingLight from '../../bendingLight.js'; +import LaserViewEnum from '../../common/model/LaserViewEnum.js'; class LaserTypeRadioButtonGroup extends RectangularRadioButtonGroup { @@ -22,7 +23,7 @@ class LaserTypeRadioButtonGroup extends RectangularRadioButtonGroup { * @param {Property.} radioButtonAdapterProperty * @param {Object} [options] */ - constructor( radioButtonAdapterProperty: Property, options?: Partial ) { + constructor( radioButtonAdapterProperty: Property<'white'|'singleColor'|'singleColor5x'>, options?: Partial ) { const laserImageNode = new Image( laserImage, { scale: 0.6, clipArea: Shape.rectangle( 100, 0, 44, 100 ) diff --git a/js/prisms/view/PrismNode.ts b/js/prisms/view/PrismNode.ts index 44101187..43d498dd 100644 --- a/js/prisms/view/PrismNode.ts +++ b/js/prisms/view/PrismNode.ts @@ -8,6 +8,7 @@ */ import Property from '../../../../axon/js/Property.js'; +import Bounds2 from '../../../../dot/js/Bounds2.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import Shape from '../../../../kite/js/Shape.js'; import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransform2.js'; @@ -41,7 +42,7 @@ class PrismNode extends Node { * @param {boolean} isIcon - true if the prism node is being created to be shown as an icon in the toolbox * - false if the prism node will be dragged in the play area */ - constructor( prismsModel: PrismsModel, modelViewTransform: ModelViewTransform2, prism: Prism, prismToolboxNode: Node, prismLayer: Node, dragBoundsProperty: Property, + constructor( prismsModel: PrismsModel, modelViewTransform: ModelViewTransform2, prism: Prism, prismToolboxNode: Node, prismLayer: Node, dragBoundsProperty: Property, occlusionHandler: ( prismNode: PrismNode ) => void, isIcon: boolean ) { super( { cursor: 'pointer' } ); @@ -60,14 +61,14 @@ class PrismNode extends Node { knobNode.addInputListener( new SimpleDragHandler( { start: ( event: SceneryEvent ) => { this.moveToFront(); - const start = knobNode.globalToParentPoint( event.pointer.point as Vector2); + const start = knobNode.globalToParentPoint( event.pointer.point as Vector2 ); prismCenterPoint = prism.getTranslatedShape().getRotationCenter(); const startX = modelViewTransform.viewToModelX( start.x );// model values const startY = modelViewTransform.viewToModelY( start.y );// model values previousAngle = Math.atan2( ( prismCenterPoint.y - startY ), ( prismCenterPoint.x - startX ) ); }, drag: ( event: SceneryEvent ) => { - const end = knobNode.globalToParentPoint( event.pointer.point as Vector2); + const end = knobNode.globalToParentPoint( event.pointer.point as Vector2 ); prismCenterPoint = prism.getTranslatedShape().getRotationCenter(); const endX = modelViewTransform.viewToModelX( end.x );// model values const endY = modelViewTransform.viewToModelY( end.y );// model values @@ -89,7 +90,7 @@ class PrismNode extends Node { // When the window reshapes, make sure no prism is left outside of the play area // TODO: Broken, see https://github.com/phetsims/bending-light/issues/372 - dragBoundsProperty.link( dragBounds => { + dragBoundsProperty.link( ( dragBounds: Bounds2 ) => { const center = prism.shapeProperty.get().centroid; const inBounds = modelViewTransform.viewToModelBounds( dragBounds ).getClosestPoint( center.x, center.y ); prism.translate( inBounds.x - center.x, inBounds.y - center.y ); diff --git a/js/prisms/view/PrismToolboxNode.ts b/js/prisms/view/PrismToolboxNode.ts index 79c338b7..6b897fae 100644 --- a/js/prisms/view/PrismToolboxNode.ts +++ b/js/prisms/view/PrismToolboxNode.ts @@ -52,7 +52,7 @@ class PrismToolboxNode extends Node { * - control panel * @param {Object} [options] that can be passed on to the underlying node */ - constructor( modelViewTransform: ModelViewTransform2, prismsModel: PrismsModel, prismLayer: Node, dragBoundsProperty: Property, occlusionHandler: () => void, + constructor( modelViewTransform: ModelViewTransform2, prismsModel: PrismsModel, prismLayer: Node, dragBoundsProperty: Property, occlusionHandler: () => void, options?: Partial ) { super(); diff --git a/js/prisms/view/PrismsScreenView.ts b/js/prisms/view/PrismsScreenView.ts index 7206321d..b8b8c6a0 100644 --- a/js/prisms/view/PrismsScreenView.ts +++ b/js/prisms/view/PrismsScreenView.ts @@ -31,6 +31,11 @@ import LaserTypeRadioButtonGroup from './LaserTypeRadioButtonGroup.js'; import PrismToolboxNode from './PrismToolboxNode.js'; import WhiteLightCanvasNode from './WhiteLightCanvasNode.js'; import BendingLightModel from '../../common/model/BendingLightModel.js'; +import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; +import Vector2 from '../../../../dot/js/Vector2.js'; +import Bounds2 from '../../../../dot/js/Bounds2.js'; +import LaserViewEnum from '../../common/model/LaserViewEnum.js'; +import Medium from '../../common/model/Medium.js'; // constants const INSET = 10; @@ -41,7 +46,9 @@ class PrismsScreenView extends BendingLightScreenView { prismLayer: Node; prismsModel: PrismsModel; resetPrismsView: () => void; - whiteLightNode: WhiteLightCanvasNode | null; + + // @ts-ignore assigned in the supercall which calls addLightNodes + whiteLightNode: WhiteLightCanvasNode; /** * @param {PrismsModel} prismsModel - model of prisms screen @@ -83,14 +90,13 @@ class PrismsScreenView extends BendingLightScreenView { }, options ) ); - this.whiteLightNode = null; this.prismLayer = new Node( { layerSplit: true } ); this.prismsModel = prismsModel; // Node for the environment that spans the screen (only for monochromatic light, the white light background // is rendered as opaque in the white light node for blending purposes) const environmentMediumNodeForMonochromaticLight = new Rectangle( 0, 0, 0, 0 ); - prismsModel.environmentMediumProperty.link( environmentMedium => { + prismsModel.environmentMediumProperty.link( ( environmentMedium: Medium ) => { // This medium node only shows the color for monochromatic light const indexOfRefractionForRed = environmentMedium.substance.dispersionFunction.getIndexOfRefractionForRed(); @@ -117,10 +123,10 @@ class PrismsScreenView extends BendingLightScreenView { this.layoutBounds.right - 2 * INSET - environmentMediumControlPanel.width, this.layoutBounds.top + 15 ); this.afterLightLayer2.addChild( environmentMediumControlPanel ); - const sliderEnabledProperty = new Property( false ); + const sliderEnabledProperty = new BooleanProperty( false ); - const radioButtonAdapterProperty = new Property( 'singleColor' ); - radioButtonAdapterProperty.link( radioButtonAdapterValue => { + const radioButtonAdapterProperty = new Property<'white' | 'singleColor' | 'singleColor5x'>( 'singleColor' ); + radioButtonAdapterProperty.link( ( radioButtonAdapterValue: 'white' | 'singleColor' | 'singleColor5x' ) => { prismsModel.laser.colorModeProperty.value = radioButtonAdapterValue === 'white' ? 'white' : 'singleColor'; prismsModel.manyRaysProperty.value = radioButtonAdapterValue === 'singleColor5x' ? 5 : 1; @@ -196,7 +202,7 @@ class PrismsScreenView extends BendingLightScreenView { rotatable: true, scale: 0.46 } ); - const protractorPositionProperty = new Property( this.modelViewTransform.modelToViewXY( 2E-5, 0 ) ); + const protractorPositionProperty = new Property( this.modelViewTransform.modelToViewXY( 2E-5, 0 ) ); const protractorNodeListener = new MovableDragHandler( protractorPositionProperty, { targetNode: protractorNode, @@ -213,7 +219,7 @@ class PrismsScreenView extends BendingLightScreenView { } ); protractorNode.addInputListener( protractorNodeListener ); - protractorPositionProperty.link( protractorPosition => { + protractorPositionProperty.link( ( protractorPosition: Vector2 ) => { protractorNode.center = protractorPosition; } ); @@ -229,12 +235,12 @@ class PrismsScreenView extends BendingLightScreenView { FloatingLayout.floatBottom( this, [ prismToolboxNode, resetAllButton ] ); FloatingLayout.floatTop( this, [ environmentMediumControlPanel ] ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { laserTypeRadioButtonGroup.top = environmentMediumControlPanel.bottom + 15; laserControlPanel.top = laserTypeRadioButtonGroup.bottom + 15; } ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { this.whiteLightNode && this.whiteLightNode.setCanvasBounds( visibleBounds ); protractorNodeListener.setDragBounds( visibleBounds ); environmentMediumNodeForMonochromaticLight.setRect( visibleBounds.x, visibleBounds.y, visibleBounds.width, visibleBounds.height ); @@ -247,18 +253,15 @@ class PrismsScreenView extends BendingLightScreenView { // Add a thin gray line to separate the navigation bar when the environmentMediumNode is black const navigationBarSeparator = new Rectangle( 0, 0, 100, 100, { fill: '#999999', pickable: false } ); - this.visibleBoundsProperty.link( visibleBounds => { + this.visibleBoundsProperty.link( ( visibleBounds: Bounds2 ) => { const rectHeight = 2; navigationBarSeparator.setRect( visibleBounds.x, visibleBounds.y + visibleBounds.height - rectHeight, visibleBounds.width, rectHeight ); } ); - prismsModel.laser.colorModeProperty.link( color => { + prismsModel.laser.colorModeProperty.link( ( color: 'white' | 'singleColor' ) => { navigationBarSeparator.visible = color === 'white'; + prismsModel.mediumColorFactory.lightTypeProperty.value = color; } ); this.addChild( navigationBarSeparator ); - - prismsModel.laser.colorModeProperty.link( colorMode => { - prismsModel.mediumColorFactory.lightTypeProperty.value = colorMode; - } ); } /** @@ -280,7 +283,7 @@ class PrismsScreenView extends BendingLightScreenView { /** * @private, for internal use only. */ - updateWhiteLightNode() { + private updateWhiteLightNode() { if ( this.prismsModel.laser.colorModeProperty.value === 'white' && this.prismsModel.dirty ) { this.whiteLightNode && this.whiteLightNode.step(); this.prismsModel.dirty = false; @@ -298,7 +301,6 @@ class PrismsScreenView extends BendingLightScreenView { const stageWidth = this.layoutBounds.width; const stageHeight = this.layoutBounds.height; - // const bendingLightModel = this.bendingLightModel; this.whiteLightNode = new WhiteLightCanvasNode( this.modelViewTransform, stageWidth, @@ -308,15 +310,17 @@ class PrismsScreenView extends BendingLightScreenView { bendingLightModel.mediumColorFactory ); this.whiteLightNode.setExcludeInvisible( true ); + console.log( this ); + console.log( this.whiteLightNode ); // Since the light canvas is opaque, it must be placed behind the control panels. this.addChild( this.whiteLightNode ); // switch between light render for white vs nonwhite light - bendingLightModel.laser.colorModeProperty.link( color => { - const white = color === 'white'; - - this.whiteLightNode && this.whiteLightNode.setVisible( white ); + bendingLightModel.laser.colorModeProperty.link( ( color: 'white' | 'singleColor' ) => { + console.log( this ); + console.log( this.whiteLightNode ); + this.whiteLightNode && this.whiteLightNode.setVisible( color === 'white' ); } ); } @@ -330,7 +334,7 @@ class PrismsScreenView extends BendingLightScreenView { */ // @ts-ignore addLaserHandles( showRotationDragHandlesProperty: Property, showTranslationDragHandlesProperty: Property, - clockwiseArrowNotAtMax: Property, ccwArrowNotAtMax: Property, laserImageWidth: number ) { + clockwiseArrowNotAtMax: Property, ccwArrowNotAtMax: Property, laserImageWidth: number ) { const bendingLightModel = this.bendingLightModel; super.addLaserHandles( showRotationDragHandlesProperty, diff --git a/js/prisms/view/WhiteLightCanvasNode.ts b/js/prisms/view/WhiteLightCanvasNode.ts index 543b309c..0224953b 100644 --- a/js/prisms/view/WhiteLightCanvasNode.ts +++ b/js/prisms/view/WhiteLightCanvasNode.ts @@ -24,12 +24,13 @@ import Color from '../../../../scenery/js/util/Color.js'; import bendingLight from '../../bendingLight.js'; import BendingLightConstants from '../../common/BendingLightConstants.js'; import LightRay from '../../common/model/LightRay.js'; +import Medium from '../../common/model/Medium.js'; import MediumColorFactory from '../../common/model/MediumColorFactory.js'; class WhiteLightCanvasNode extends CanvasNode { modelViewTransform: ModelViewTransform2; whiteLightRays: LightRay[]; - environmentMediumProperty: Property; + environmentMediumProperty: Property; colorCSS: string | null; /** @@ -41,7 +42,7 @@ class WhiteLightCanvasNode extends CanvasNode { * @param {MediumColorFactory} mediumColorFactory - for creating colors from index of refraction */ constructor( modelViewTransform: ModelViewTransform2, stageWidth: number, stageHeight: number, whiteLightRays: LightRay[], - environmentMediumProperty: Property, mediumColorFactory: MediumColorFactory ) { + environmentMediumProperty: Property, mediumColorFactory: MediumColorFactory ) { super( { canvasBounds: new Bounds2( 0, 0, stageWidth, stageHeight )