From d042d53d58ad89d119bcd0ddeda60550c52ca85a Mon Sep 17 00:00:00 2001 From: AgustinVallejo Date: Wed, 24 Jul 2024 12:59:22 -0500 Subject: [PATCH] Providing materials in model with valid values, see https://github.com/phetsims/density-buoyancy-common/issues/270 --- .../model/BuoyancyBasicsExploreModel.ts | 8 ++++++ js/buoyancy/model/BuoyancyExploreModel.ts | 12 ++++++++- js/buoyancy/model/BuoyancyLabModel.ts | 11 +++++++- js/buoyancy/model/applications/Boat.ts | 5 +++- js/buoyancy/model/applications/Bottle.ts | 4 ++- .../applications/BuoyancyApplicationsModel.ts | 22 ++++++++++++++-- .../model/shapes/BuoyancyShapesModel.ts | 9 ++++++- .../BuoyancyApplicationsScreenView.ts | 22 ++++------------ js/common/model/CompareBlockSetModel.ts | 8 +++--- js/common/model/Cube.ts | 6 ++--- js/common/model/Mass.ts | 14 +++++----- js/common/model/Material.ts | 8 ++++++ js/common/model/Scale.ts | 6 ++++- js/common/view/ABControlsNode.ts | 2 +- js/common/view/BlockControlNode.ts | 8 ++---- js/density/model/DensityIntroModel.ts | 10 ++++++- js/density/model/DensityMysteryModel.ts | 26 +++++++++++-------- 17 files changed, 125 insertions(+), 56 deletions(-) diff --git a/js/buoyancy-basics/model/BuoyancyBasicsExploreModel.ts b/js/buoyancy-basics/model/BuoyancyBasicsExploreModel.ts index 17955592..1aef20ff 100644 --- a/js/buoyancy-basics/model/BuoyancyBasicsExploreModel.ts +++ b/js/buoyancy-basics/model/BuoyancyBasicsExploreModel.ts @@ -17,6 +17,7 @@ import Scale, { DisplayType } from '../../common/model/Scale.js'; import TwoBlockMode from '../../common/model/TwoBlockMode.js'; import densityBuoyancyCommon from '../../densityBuoyancyCommon.js'; import MassTag from '../../common/model/MassTag.js'; +import { MaterialSchema } from '../../common/model/Mass.js'; type BuoyancyBasicsExploreModelOptions = DensityBuoyancyModelOptions; @@ -37,11 +38,17 @@ export default class BuoyancyBasicsExploreModel extends DensityBuoyancyModel { phetioFeatured: true } ); + const availableMassMaterials: MaterialSchema[] = [ + ...Material.SIMPLE_MASS_MATERIALS, + 'CUSTOM' + ]; + const blockATandem = blocksTandem.createTandem( 'blockA' ); this.massA = Cube.createWithMass( this.engine, Material.WOOD, new Vector2( -0.2, 0.2 ), 2, { tag: MassTag.OBJECT_A, adjustableMaterial: true, adjustableColor: false, + availableMassMaterials: availableMassMaterials, tandem: blockATandem } ); this.availableMasses.push( this.massA ); @@ -51,6 +58,7 @@ export default class BuoyancyBasicsExploreModel extends DensityBuoyancyModel { tag: MassTag.OBJECT_B, adjustableMaterial: true, adjustableColor: false, + availableMassMaterials: availableMassMaterials, tandem: blockBTandem, visible: false } ); diff --git a/js/buoyancy/model/BuoyancyExploreModel.ts b/js/buoyancy/model/BuoyancyExploreModel.ts index 9e79a715..0e7c8f90 100644 --- a/js/buoyancy/model/BuoyancyExploreModel.ts +++ b/js/buoyancy/model/BuoyancyExploreModel.ts @@ -17,6 +17,7 @@ import Scale, { DisplayType } from '../../common/model/Scale.js'; import TwoBlockMode from '../../common/model/TwoBlockMode.js'; import densityBuoyancyCommon from '../../densityBuoyancyCommon.js'; import MassTag from '../../common/model/MassTag.js'; +import { MaterialSchema } from '../../common/model/Mass.js'; export type BuoyancyExploreModelOptions = DensityBuoyancyModelOptions; @@ -37,9 +38,17 @@ export default class BuoyancyExploreModel extends DensityBuoyancyModel { phetioFeatured: true } ); + const availableMassMaterials: MaterialSchema[] = [ + ...Material.SIMPLE_MASS_MATERIALS, + 'CUSTOM', + Material.MATERIAL_X, + Material.MATERIAL_Y + ]; + this.massA = Cube.createWithMass( this.engine, Material.WOOD, new Vector2( -0.2, 0.2 ), 2, { tag: MassTag.OBJECT_A, - tandem: blocksTandem.createTandem( 'blockA' ) + tandem: blocksTandem.createTandem( 'blockA' ), + availableMassMaterials: availableMassMaterials } ); this.availableMasses.push( this.massA ); this.massB = Cube.createWithMass( this.engine, Material.ALUMINUM, new Vector2( 0.05, 0.35 ), 13.5, { @@ -47,6 +56,7 @@ export default class BuoyancyExploreModel extends DensityBuoyancyModel { // REVIEW: Tandem doesn't match variable name tandem: blocksTandem.createTandem( 'blockB' ), + availableMassMaterials: availableMassMaterials, visible: false } ); this.availableMasses.push( this.massB ); diff --git a/js/buoyancy/model/BuoyancyLabModel.ts b/js/buoyancy/model/BuoyancyLabModel.ts index 24448d92..55f7df6e 100644 --- a/js/buoyancy/model/BuoyancyLabModel.ts +++ b/js/buoyancy/model/BuoyancyLabModel.ts @@ -18,6 +18,7 @@ import DerivedProperty from '../../../../axon/js/DerivedProperty.js'; import DensityBuoyancyCommonConstants from '../../common/DensityBuoyancyCommonConstants.js'; import NumberIO from '../../../../tandem/js/types/NumberIO.js'; import ReadOnlyProperty from '../../../../axon/js/ReadOnlyProperty.js'; +import { MaterialSchema } from '../../common/model/Mass.js'; export type BuoyancyLabModelOptions = DensityBuoyancyModelOptions; @@ -31,8 +32,16 @@ export default class BuoyancyLabModel extends DensityBuoyancyModel { super( options ); + const availableMassMaterials: MaterialSchema[] = [ + ...Material.SIMPLE_MASS_MATERIALS, + 'CUSTOM', + Material.MATERIAL_O, + Material.MATERIAL_P + ]; + this.block = Cube.createWithMass( this.engine, Material.WOOD, new Vector2( -0.2, 0.2 ), 2, { - tandem: options.tandem.createTandem( 'block' ) + tandem: options.tandem.createTandem( 'block' ), + availableMassMaterials: availableMassMaterials } ); this.availableMasses.push( this.block ); diff --git a/js/buoyancy/model/applications/Boat.ts b/js/buoyancy/model/applications/Boat.ts index 5245e72d..1c5cdc47 100644 --- a/js/buoyancy/model/applications/Boat.ts +++ b/js/buoyancy/model/applications/Boat.ts @@ -28,7 +28,9 @@ import DensityBuoyancyCommonConstants, { toLiters } from '../../../common/Densit import NumberProperty from '../../../../../axon/js/NumberProperty.js'; import Pool from '../../../common/model/Pool.js'; -export type BoatOptions = StrictOmit; +// TODO Factor out this type, https://github.com/phetsims/density-buoyancy-common/issues/270 +export type BoatOptions = StrictOmit; export default class Boat extends ApplicationsMass { @@ -65,6 +67,7 @@ export default class Boat extends ApplicationsMass { volume: volume, massShape: MassShape.BLOCK, material: Material.BOAT_BODY, + availableMassMaterials: [ Material.BOAT_BODY ], accessibleName: 'Boat' }, providedOptions ); diff --git a/js/buoyancy/model/applications/Bottle.ts b/js/buoyancy/model/applications/Bottle.ts index bf851b14..aa1be1ee 100644 --- a/js/buoyancy/model/applications/Bottle.ts +++ b/js/buoyancy/model/applications/Bottle.ts @@ -176,7 +176,8 @@ const BOTTLE_INITIAL_INTERIOR_VOLUME = 0.004; // {Material} const BOTTLE_INITIAL_INTERIOR_MATERIAL = Material.WATER; -export type BottleOptions = StrictOmit; +export type BottleOptions = StrictOmit; export default class Bottle extends ApplicationsMass { @@ -202,6 +203,7 @@ export default class Bottle extends ApplicationsMass { shape: Shape.polygon( vertices ), volume: BOTTLE_VOLUME, material: 'CUSTOM', + availableMassMaterials: [ 'CUSTOM' ], materialPropertyOptions: { phetioReadOnly: true }, diff --git a/js/buoyancy/model/applications/BuoyancyApplicationsModel.ts b/js/buoyancy/model/applications/BuoyancyApplicationsModel.ts index d90b6b80..5252e0ef 100644 --- a/js/buoyancy/model/applications/BuoyancyApplicationsModel.ts +++ b/js/buoyancy/model/applications/BuoyancyApplicationsModel.ts @@ -20,7 +20,7 @@ import { BottleOrBoat, BottleOrBoatValues } from './BottleOrBoat.js'; import StringUnionProperty from '../../../../../axon/js/StringUnionProperty.js'; import MassTag from '../../../common/model/MassTag.js'; import Basin from '../../../common/model/Basin.js'; -import Mass from '../../../common/model/Mass.js'; +import Mass, { MaterialSchema } from '../../../common/model/Mass.js'; export type BuoyancyApplicationsModelOptions = DensityBuoyancyModelOptions; @@ -67,9 +67,27 @@ export default class BuoyancyApplicationsModel extends DensityBuoyancyModel { } ); this.availableMasses.push( this.bottle ); + const sortedByDensity: MaterialSchema[] = _.sortBy( [ + Material.PYRITE, + Material.STEEL, + Material.SILVER, + Material.TANTALUM, + Material.GOLD, + Material.PLATINUM + ].concat( Material.SIMPLE_MASS_MATERIALS ), + + material => material.density ); + const availableMassMaterials = sortedByDensity.concat( [ + // Adding custom/mystery Materials separately, so they aren't sorted above by density + 'CUSTOM', + Material.MATERIAL_V, + Material.MATERIAL_W + ] ); + this.block = Cube.createWithVolume( this.engine, Material.BRICK, new Vector2( -0.5, 0.3 ), 0.001, { visible: false, - tandem: objectsTandem.createTandem( 'block' ) + tandem: objectsTandem.createTandem( 'block' ), + availableMassMaterials: availableMassMaterials } ); this.availableMasses.push( this.block ); diff --git a/js/buoyancy/model/shapes/BuoyancyShapesModel.ts b/js/buoyancy/model/shapes/BuoyancyShapesModel.ts index 98e26b5f..06cf804f 100644 --- a/js/buoyancy/model/shapes/BuoyancyShapesModel.ts +++ b/js/buoyancy/model/shapes/BuoyancyShapesModel.ts @@ -42,6 +42,7 @@ export default class BuoyancyShapesModel extends DensityBuoyancyModel { public readonly objectB: BuoyancyShapeModel; public readonly materialProperty: MaterialProperty; + private readonly availableMaterials: Material[]; public constructor( options: BuoyancyShapesModelOptions ) { @@ -54,11 +55,13 @@ export default class BuoyancyShapesModel extends DensityBuoyancyModel { phetioFeatured: true } ); + this.availableMaterials = Material.SIMPLE_MASS_MATERIALS; + this.materialProperty = new MaterialProperty( Material.WOOD, // This hack is a way of saying, we do not create or support a custom material in this case. Material.WOOD, - Material.SIMPLE_MASS_MATERIALS, { + this.availableMaterials, { tandem: objectsTandem.createTandem( 'materialProperty' ), phetioValueType: ReferenceIO( IOType.ObjectIO ) } ); @@ -116,6 +119,10 @@ export default class BuoyancyShapesModel extends DensityBuoyancyModel { private createMass( tandem: Tandem, shape: MassShape, widthRatio: number, heightRatio: number, tag: MassTag ): Mass { const massOptions = { material: this.materialProperty.value, + availableMassMaterials: this.availableMaterials, + materialPropertyOptions: { + phetioReadOnly: true + }, minVolume: 0.0002, // Cones have a smaller volume at min height/width maxVolume: Cuboid.MAX_VOLUME, // Cubes are the highest volume object in this screen tandem: tandem, diff --git a/js/buoyancy/view/applications/BuoyancyApplicationsScreenView.ts b/js/buoyancy/view/applications/BuoyancyApplicationsScreenView.ts index 106b562a..72e90be2 100644 --- a/js/buoyancy/view/applications/BuoyancyApplicationsScreenView.ts +++ b/js/buoyancy/view/applications/BuoyancyApplicationsScreenView.ts @@ -204,23 +204,11 @@ export default class BuoyancyApplicationsScreenView extends BuoyancyScreenView material.density ).concat( [ - // Adding custom/mystery Materials separately, so they aren't sorted by density - model.block.materialProperty.customMaterial, - Material.MATERIAL_V, - Material.MATERIAL_W - ] ), cubicMeters => model.block.updateSize( Cube.boundsFromVolume( cubicMeters ) ), this.popupLayer, true, { - tandem: tandem.createTandem( 'blockControls' ), - highDensityMaxMass: 215 - } ); + const blockControls = new MaterialMassVolumeControlNode( model.block.materialProperty, model.block.massProperty, model.block.volumeProperty, + model.block.materialProperty.availableValues, cubicMeters => model.block.updateSize( Cube.boundsFromVolume( cubicMeters ) ), this.popupLayer, true, { + tandem: tandem.createTandem( 'blockControls' ), + highDensityMaxMass: 215 + } ); model.block.materialProperty.link( material => { if ( material === Material.MATERIAL_V ) { diff --git a/js/common/model/CompareBlockSetModel.ts b/js/common/model/CompareBlockSetModel.ts index 85110f27..98186c22 100644 --- a/js/common/model/CompareBlockSetModel.ts +++ b/js/common/model/CompareBlockSetModel.ts @@ -109,7 +109,8 @@ export default class CompareBlockSetModel extends BlockSetModel { sharedCubeOptions: { materialPropertyOptions: { phetioReadOnly: true // See https://github.com/phetsims/density-buoyancy-common/issues/270#issuecomment-2243371397 - } + }, + availableMassMaterials: [] // TODO: 'CUSTOM' isn't right in here, instead we need to figure out the "side MaterialProperty" instances first. https://github.com/phetsims/density-buoyancy-common/issues/273 }, // BlockSetModel options @@ -168,11 +169,11 @@ export default class CompareBlockSetModel extends BlockSetModel { }, cubeData ); } ); - const getCubeOptions = ( cubeOptions: StrictCubeOptions ) => combineOptions( {}, options.sharedCubeOptions, cubeOptions ); + // TODO: We lost type checking for availableMassMaterials because of the `CubeOptions` type, https://github.com/phetsims/density-buoyancy-common/issues/273 + const getCubeOptions = ( cubeOptions: StrictOmit ) => combineOptions( {}, options.sharedCubeOptions, cubeOptions ); // TODO: Helpful documentation please, see https://github.com/phetsims/density-buoyancy-common/issues/273 const createMasses = ( model: BlockSetModel, blockSet: BlockSet ) => { - // TODO: Helpful documentation please, see https://github.com/phetsims/density-buoyancy-common/issues/273 // In the following code, the cube instance persists for the lifetime of the simulation and the listeners // don't need to be removed. @@ -263,6 +264,7 @@ export default class CompareBlockSetModel extends BlockSetModel { * Otherwise, it creates a custom material with a modified color based on the density. * * TODO: Should this return MaterialProperty and create its own customMaterial? see https://github.com/phetsims/density-buoyancy-common/issues/273 + * TODO: Can we use initialMaterials as the availableMassMaterials for the blocks created for this blockSet? https://github.com/phetsims/density-buoyancy-common/issues/273 */ private static createMaterialProperty( tandem: Tandem, colorProperty: TReadOnlyProperty, densityProperty: TReadOnlyProperty, blockSetValueChangedProperty: TReadOnlyProperty, initialMaterials: Material[] ): TReadOnlyProperty { diff --git a/js/common/model/Cube.ts b/js/common/model/Cube.ts index 096c2b77..4186f873 100644 --- a/js/common/model/Cube.ts +++ b/js/common/model/Cube.ts @@ -13,8 +13,8 @@ import densityBuoyancyCommon from '../../densityBuoyancyCommon.js'; import Cuboid, { CuboidOptions } from './Cuboid.js'; import PhysicsEngine from './PhysicsEngine.js'; import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; -import Material from './Material.js'; import Vector2 from '../../../../dot/js/Vector2.js'; +import { MaterialSchema } from './Mass.js'; type SelfOptions = { @@ -79,7 +79,7 @@ export default class Cube extends Cuboid { /** * Creates a Cube with a defined volume */ - public static createWithVolume( engine: PhysicsEngine, material: Material | 'CUSTOM', position: Vector2, volume: number, options?: StrictCubeOptions ): Cube { + public static createWithVolume( engine: PhysicsEngine, material: MaterialSchema, position: Vector2, volume: number, options?: StrictCubeOptions ): Cube { return new Cube( engine, volume, combineOptions( { matrix: Matrix3.translation( position.x, position.y ), minVolume: Cuboid.MIN_VOLUME, @@ -91,7 +91,7 @@ export default class Cube extends Cuboid { /** * Creates a Cube with a defined volume */ - public static createWithMass( engine: PhysicsEngine, material: Material | 'CUSTOM', position: Vector2, mass: number, options?: StrictCubeOptions ): Cube { + public static createWithMass( engine: PhysicsEngine, material: MaterialSchema, position: Vector2, mass: number, options?: StrictCubeOptions ): Cube { let density: number; if ( material === 'CUSTOM' ) { assert && assert( options?.customMaterialOptions?.density, 'density needed to create with mass' ); diff --git a/js/common/model/Mass.ts b/js/common/model/Mass.ts index b9c9cd6c..222bcfa5 100644 --- a/js/common/model/Mass.ts +++ b/js/common/model/Mass.ts @@ -49,14 +49,16 @@ import ReferenceIO from '../../../../tandem/js/types/ReferenceIO.js'; export const MASS_MIN_SHAPES_DIMENSION = 0.1; // 10cm => 1L square export const MASS_MAX_SHAPES_DIMENSION = Math.pow( 0.01, 1 / 3 ); // 10L square +export type MaterialSchema = Material | 'CUSTOM'; // We pass 'CUSTOM' so materialProperty can create the customMaterial + type SelfOptions = { // Required body: PhysicsEngineBody; shape: Shape; - // Use "CUSTOM" to tell the MaterialProperty to take the initial value from the internal customMaterial it creates. - material: Material | 'CUSTOM'; + material: MaterialSchema; + availableMassMaterials: MaterialSchema[]; volume: number; massShape: MassShape; @@ -66,10 +68,12 @@ type SelfOptions = { // Allow Customization of the material beyond initial value, this includes PhET-iO support for changing the density // and color, as well as support for some screens to adjust density instead of mass/volume as is most typical, see https://github.com/phetsims/density/issues/101 + // TODO AV: Get outta here, https://github.com/phetsims/density-buoyancy-common/issues/270 adjustableMaterial?: boolean; // Only used when adjustableMaterial:true. Set to true to support a PhET-iO instrumented Property to set the color // of the block. Set to false in order to calculate the color based on the current density + the density range. + // TODO AV: Get outta here, https://github.com/phetsims/density-buoyancy-common/issues/270 adjustableColor?: boolean; tag?: MassTag; accessibleName?: PDOMValueType | null; @@ -252,14 +256,12 @@ export default abstract class Mass extends PhetioObject { options.materialPropertyOptions.tandem = options.materialPropertyOptions.tandem || tandem.createTandem( 'materialProperty' ); const customSolidMaterial = new CustomSolidMaterial( options.materialPropertyOptions.tandem.createTandem( 'customMaterial' ), combineOptions( { - density: options.material === 'CUSTOM' ? undefined : options.material.density + density: options.material === 'CUSTOM' ? undefined : options.material.density // The undefined makes sure we don't override the default }, options.customMaterialOptions ) ); const initialMaterial = options.material === 'CUSTOM' ? customSolidMaterial : options.material; this.materialProperty = new MaterialProperty( initialMaterial, customSolidMaterial, - - // TODO: Do this part next, https://github.com/phetsims/density-buoyancy-common/issues/270 - [], + options.availableMassMaterials.map( x => x === 'CUSTOM' ? customSolidMaterial : x ), options.materialPropertyOptions as MaterialPropertyOptions ); this.volumeProperty = new NumberProperty( options.volume, combineOptions( { diff --git a/js/common/model/Material.ts b/js/common/model/Material.ts index cbeeabf2..2f143bff 100644 --- a/js/common/model/Material.ts +++ b/js/common/model/Material.ts @@ -473,6 +473,14 @@ export default class Material extends PhetioObject implements HasValueProperty { Material.ALUMINUM ]; + // TODO: This is the exact list from Density 1.1 (adding in PVC), do we need to support this exactly for some reason? Or can it just be a more general list? https://github.com/phetsims/density-buoyancy-common/issues/270 + public static readonly DENSITY_MYSTERY_PHET_IO_CUSTOMIZABLE_MATERIAL = [ + ...Material.SIMPLE_MASS_MATERIALS, + Material.STEEL, + Material.COPPER, + Material.PLATINUM + ]; + public static readonly BUOYANCY_FLUID_MATERIALS = [ Material.GASOLINE, Material.OIL, diff --git a/js/common/model/Scale.ts b/js/common/model/Scale.ts index 1a7ddf73..8e1f4532 100644 --- a/js/common/model/Scale.ts +++ b/js/common/model/Scale.ts @@ -65,7 +65,10 @@ type SelfOptions = { displayType?: DisplayType; }; -export type ScaleOptions = SelfOptions & StrictOmit & PickOptional; +// TODO: Cleanup https://github.com/phetsims/density-buoyancy-common/issues/270 +export type ScaleOptions = SelfOptions & StrictOmit & + PickOptional; export default class Scale extends Mass { @@ -89,6 +92,7 @@ export default class Scale extends Mass { displayType: DisplayType.NEWTONS, material: Material.PLATINUM, + availableMassMaterials: [ Material.PLATINUM ], accessibleName: 'Scale', diff --git a/js/common/view/ABControlsNode.ts b/js/common/view/ABControlsNode.ts index 5da4cffb..e345b9f3 100644 --- a/js/common/view/ABControlsNode.ts +++ b/js/common/view/ABControlsNode.ts @@ -18,7 +18,7 @@ import ABPanelsNode from './ABPanelsNode.js'; import Material from '../model/Material.js'; type SelfOptions = { - mysteryMaterials?: Material[]; + mysteryMaterials?: Material[]; // TODO: delete, https://github.com/phetsims/density-buoyancy-common/issues/270 }; export type ABControlsNodeOptions = SelfOptions & BlockControlNodeOptions & { tandem: Tandem }; diff --git a/js/common/view/BlockControlNode.ts b/js/common/view/BlockControlNode.ts index d405fee1..939629ff 100644 --- a/js/common/view/BlockControlNode.ts +++ b/js/common/view/BlockControlNode.ts @@ -21,7 +21,7 @@ import UnitConversionProperty from '../../../../axon/js/UnitConversionProperty.j import Range from '../../../../dot/js/Range.js'; type SelfOptions = { - mysteryMaterials: Material[]; // Provide empty list to opt out. + mysteryMaterials: Material[]; // Provide empty list to opt out. // TODO: delete, https://github.com/phetsims/density-buoyancy-common/issues/270 }; export type BlockControlNodeOptions = MaterialMassVolumeControlNodeOptions & SelfOptions; @@ -29,11 +29,7 @@ export type BlockControlNodeOptions = MaterialMassVolumeControlNodeOptions & Sel export default class BlockControlNode extends MaterialMassVolumeControlNode { public constructor( cuboid: Cuboid, listParent: Node, numberControlMassPropertyFeatured: boolean, options: BlockControlNodeOptions ) { - const materials = [ - ...Material.SIMPLE_MASS_MATERIALS, - cuboid.materialProperty.customMaterial, - ...options.mysteryMaterials - ]; + const materials = cuboid.materialProperty.availableValues; // If we have useDensityControlInsteadOfMassControl, we control the logic completely here, and hence do not want the one-way synchronization in the super. if ( assert && options.useDensityControlInsteadOfMassControl ) { diff --git a/js/density/model/DensityIntroModel.ts b/js/density/model/DensityIntroModel.ts index 915e878d..fda628c1 100644 --- a/js/density/model/DensityIntroModel.ts +++ b/js/density/model/DensityIntroModel.ts @@ -17,6 +17,7 @@ import Material from '../../common/model/Material.js'; import TwoBlockMode from '../../common/model/TwoBlockMode.js'; import densityBuoyancyCommon from '../../densityBuoyancyCommon.js'; import MassTag from '../../common/model/MassTag.js'; +import { MaterialSchema } from '../../common/model/Mass.js'; export type DensityIntroModelOptions = DensityBuoyancyModelOptions; @@ -40,14 +41,21 @@ export default class DensityIntroModel extends DensityBuoyancyModel { phetioFeatured: true } ); + const availableMassMaterials: MaterialSchema[] = [ + ...Material.SIMPLE_MASS_MATERIALS, + 'CUSTOM' + ]; + this.massA = Cube.createWithMass( this.engine, Material.WOOD, new Vector2( -0.2, 0.2 ), 2, { tag: MassTag.OBJECT_A, - tandem: blocksTandem.createTandem( 'blockA' ) + tandem: blocksTandem.createTandem( 'blockA' ), + availableMassMaterials: availableMassMaterials } ); this.availableMasses.push( this.massA ); this.massB = Cube.createWithMass( this.engine, Material.ALUMINUM, new Vector2( 0.2, 0.2 ), 13.5, { tag: MassTag.OBJECT_B, tandem: blocksTandem.createTandem( 'blockB' ), + availableMassMaterials: availableMassMaterials, visible: false } ); this.availableMasses.push( this.massB ); diff --git a/js/density/model/DensityMysteryModel.ts b/js/density/model/DensityMysteryModel.ts index 971b7ce8..e764fd45 100644 --- a/js/density/model/DensityMysteryModel.ts +++ b/js/density/model/DensityMysteryModel.ts @@ -30,6 +30,7 @@ import { Color, ColorProperty } from '../../../../scenery/js/imports.js'; import Emitter from '../../../../axon/js/Emitter.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import Tandem from '../../../../tandem/js/Tandem.js'; +import { MaterialSchema } from '../../common/model/Mass.js'; // constants const randomColors = [ @@ -77,7 +78,11 @@ export default class DensityMysteryModel extends BlockSetModel const commonCubeOptions = { adjustVolumeOnMassChanged: true, - adjustableMaterial: true + adjustableMaterial: true, + availableMassMaterials: [ + ...Material.DENSITY_MYSTERY_PHET_IO_CUSTOMIZABLE_MATERIAL, + 'CUSTOM' + ] satisfies MaterialSchema[] }; let densities: number[]; @@ -382,16 +387,15 @@ export default class DensityMysteryModel extends BlockSetModel tandem: cubeTandem.createTandem( 'materialProperty' ).createTandem( 'customMaterial' ).createTandem( 'colorProperty' ) } ); - const cube = Cube.createWithVolume( model.engine, 'CUSTOM', Vector2.ZERO, mysteryVolumes[ i ], { - adjustVolumeOnMassChanged: true, - adjustableMaterial: true, - tag: tags[ i ], - tandem: cubeTandem, - customMaterialOptions: { - colorProperty: colorProperty, - density: densities[ i ] - } - } ); + const cube = Cube.createWithVolume( model.engine, 'CUSTOM', Vector2.ZERO, mysteryVolumes[ i ], + combineOptions( {}, commonCubeOptions, { + tag: tags[ i ], + tandem: cubeTandem, + customMaterialOptions: { + colorProperty: colorProperty, + density: densities[ i ] + } + } ) ); randomizeMaterialsEmitter.addListener( () => { cube.materialProperty.customMaterial.densityProperty.value = densities[ i ];