Closed pixelzoom closed 3 years ago
Thoughts:
phetioDocumentation
, or inspect (but not set) a color via phetioReadOnly
Looks like profileNameProperty
is the only bit that is currently instrumented.
@pixelzoom I'm trying to note the priority for this. Is there a sim currently under phet-io development that is using a ColorProfile. If not please let us know when that is the case. I think that will be the easiest way to proceed here.
As noted in the first comment, gas-properties uses ColorProfiles, and whether they need to be instrumented is a question for designers. If (for example) allowing PhET-iO clients to change the particle colors is a desired feature, then ColorProfiles (and the Properties that they synthesize) will need to be instrumented.
This came up again in Fourier, where we want to use ColorProfile, and be able to change colors via PhET-iO. See https://github.com/phetsims/fourier-making-waves/issues/5.
Above, I added studio support for PropertyIO<ColorIO>
. It was simple enough, and felt like something we should have no matter what.
This patch could instrument every colorProperty, which could be a poor, manual approach to creating your own color profile, but it can be overridden, for example if you set some Properties, and then toggle the projector mode checkbox on and then off again, it blows away your customizations.
Index: js/ColorProfile.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- js/ColorProfile.js (revision 1a81c88e54ba0f370fdce8459aafb4f1bcfea4dd)
+++ js/ColorProfile.js (date 1604956799275)
@@ -89,6 +89,8 @@
validValues: profileNames
} );
+ const colorPropertiesTandem = options.tandem.createTandem( 'colorProperties' );
+
Object.keys( colors ).sort().forEach( key => {
if ( colors.hasOwnProperty( key ) ) {
@@ -103,9 +105,14 @@
// Use the requested initial profile, fallback to default.
const initialColor = colorMap[ initialProfileName ] || colorMap[ ColorProfile.DEFAULT_COLOR_PROFILE_NAME ];
+ const colorPropertyName = key + 'Property';
+
// Create a Property for the color
- const colorProperty = new Property( initialColor );
- this[ key + 'Property' ] = colorProperty;
+ const colorProperty = new Property( initialColor, {
+ tandem: colorPropertiesTandem.createTandem( colorPropertyName ),
+ phetioType: Property.PropertyIO( Color.ColorIO )
+ } );
+ this[ colorPropertyName ] = colorProperty;
// Update the Property on profile name changes
this.profileNameProperty.lazyLink( profileName => {
I'm not really sure if this is something to look into further, or if we should start here. Likely things should be more designed. In the mean time, @samreid will you check on my commits, and recommend a step forward for this issue as you see fit.
I tested capacitorLabBasics.capacitanceScreen.model.arrowColorProperty
in studio, and it looks really great, nice work @zepumph. I think for many sims, changing the color profile programmatically will be OK. For Fourier's amplitude colors, @ariel-phet said:
I do not even think these colors should be "easily edited" with iO for the same reasons. That seems like a "bell and whistle" that is potentially problematic.
I recommend we wait until we have a concrete use case before working on this further.
My commits from https://github.com/phetsims/scenery-phet/issues/515#issuecomment-724300804 have brought up discussion in https://github.com/phetsims/fourier-making-waves/issues/13#issuecomment-726923339 and https://github.com/phetsims/scenery/issues/1115.
@samreid said that this desire was brought up again in a design meeting yesterday, we spoke about how we may accomplish this and thought about the following:
setColorForProfile
that manipulated the underlying color map (https://github.com/phetsims/scenery-phet/blob/e4ec40deb7170cbb08ee20769f7eb09e469665fa/js/ColorProfile.js#L96). If we got the route of something like ColorProfileIO, let's make sure that we have the ability to exclude some of a profile's color Properties from instrumentation. The set of colors that we put in ColorProfile so that PhET designers can experiment with colors is not necessarily the same set that we want to present to PhET-iO designers in Studio.
EDIT: Or discuss this with PhET designers, to see whether "all or nothing" (always instrumenting the complete set of Properties in a ColorProfile) is acceptable.
I won't be able to serialize Density/Buoyancy without ReferenceIO-style references to ColorProfile Properties. Each Material can take a general Property.<Color>
for its solid or liquid appearance, and many times these are ColorProfile Property references. Elevating priority.
ColorProfile suffers from the same problems that PropertySet did, and we should eliminate it for the same reasons. PropertySet was discussed in https://github.com/phetsims/axon/issues/71, https://github.com/phetsims/axon/issues/101 and https://github.com/phetsims/axon/issues/102. To use the same pattern for ColorProfile, we could create a new supportive type that gives a convenient syntax for specifying Colors:
class SelectionProperty extends DerivedProperty {
constructor( profileNameProperty, map, options ) {
super( [ profileNameProperty ], profileName => map[ profileName ], options );
}
}
ColorProfile could be implemented like so (untested draft):
class MyColorProfile {
constructor( profileNames ) {
this.profileNameProperty = new StringProperty( 'default', { validValues: profileNames } );
this.map = {};
window.addEventListener( 'message', event => {
let data;
try {
data = JSON.parse( event.data );
}
catch( e ) { }
if ( data && data.type === 'setColor' ) {
this.map[ data.name ].value = new Color( data.value );
}
} );
}
addProperties( object ) {
Object.keys( object ).forEach( key => {
const property = object[ key ];
property.link( () => this.reportColor( key, property.value ) );
this.map[ key ] = property;
} );
}
reportColor( key, color ) {
( window.parent !== window ) && window.parent.postMessage( JSON.stringify( {
type: 'reportColor',
name: key,
value: color.toHexString()
} ), '*' );
}
}
And usage sites would look like this:
class MassesAndSpringsColorProfile extends MyColorProfile {
constructor() {
super( [ 'default', 'basics' ] );
this.backgroundProperty = new SelectionProperty( this.profileNameProperty, {
default: Color.white,
basics: new Color( 'rgb( 255, 250, 227 )' )
} )
this.smallMysteryMassProperty = new SelectionProperty( this.profileNameProperty, {
default: new Color( 'rgb( 246, 164, 255 )' ),
basics: new Color( 'rgb( 185, 0, 38 )' )
} );
super.addProperties( {
background: this.backgroundProperty,
smallMysteryMass: this.smallMysteryMassProperty
} );
}
}
This would enable us to provide Property-specific PhET-iO instrumentation in our idiomatic way.
@jonathanolson and @pixelzoom can you please review and advise?
Seems significantly more verbose, what do you see us gaining from this style? Presumably we'd need to add in tandems and phetio types manually?
PropertySet was less verbose than the alternative, but we decided against it anyways because we valued other aspects over succinctness. Using the synthesized Properties makes it look like things are broken, and fails navigation/autocompletion and highlighting:
As mentioned in the comment above, we have the following constraint for phet-io:
If we got the route of something like ColorProfileIO, let's make sure that we have the ability to exclude some of a profile's color Properties from instrumentation.
Creating Property instances allows us to specify phet-io instrumentation individually in the conventional way, without creating a new options syntax or equivalent.
Maybe there is a way to make the proposal a little less verbose, while still retaining the main advantages?
Maybe there is a way to make the proposal a little less verbose, while still retaining the main advantages?
Perhaps a custom ColorProfileProperty
? But yes this seems like a generally decent approach given that flexibility and IDE constraints.
A good next step would be to get feedback on the proposal from @pixelzoom and @zepumph.
When I started at PhET, there was almost zero IDE and navigation support, and because of that I have a hard time ranking the importance of that. @samreid, what would be the ideal pattern here if we used TypeScript? Would anything be different?
In general I feel like we should continue with the path outlined in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-726981907. @samreid can you please note if your opinion is represented by https://github.com/phetsims/scenery-phet/issues/515#issuecomment-870599230, or if you were just brainstorming? If you would like to proceed in that direction, would you please note the primary reasons why that much of an overhaul is worth the cost?
This is common code, so lets elevate to blocking publication in general.
https://github.com/phetsims/scenery-phet/issues/515#issuecomment-726981907 does not support the features requested in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-512055519 or https://github.com/phetsims/scenery-phet/issues/515#issuecomment-726983363, but https://github.com/phetsims/scenery-phet/issues/515#issuecomment-870599230 supports it in the standard way.
Our team voted overwhelmingly in favor of abandoning PropertySet. ColorProperty has the same problems because it uses the same implementation style--I suspect the only reason we tolerate it more is because it is used less.
For context, a reminder that the PhET team decided that all new sims should have a ColorProfile - see https://github.com/phetsims/scenery-phet/issues/642.
@samreid said:
... Using the synthesized Properties makes it look like things are broken, and fails navigation/autocompletion and highlighting:
This is indeed annoying. It will become more annoying as use of ColorProfile increases. It's certainly been annoying in the last few sims that I've implemented, which had ColorProfile.
... I suspect the only reason we tolerate it more is because it is used less.
I suspect that you are correct. Again, I suspect this will change as use of ColorProfile increases.
The ability to conditionally instrument individual Properties and or to supply supplemental, and custom metadata to each Property could be solved in either way. Really this issue comes down to the pros and cons of dependency injection, especially as it pertains to PhET-iO.
We have used both patterns in the project, either supplying metadata in the form of an options object to a container to create elements (RectangularRadioButtonGroup), or to just create them and pass them in (ComboBoxItem). It's not obvious to me that either is a winner.
Can you elaborate on "dependency injection" in this context?
Whether or not ColorProfile is instantiating the Property, or if you are, and then passing them to ColorProfile.
Should we mark this as a dev meeting subgroup so we can make a decision on this?
Discussed during 7/8/21 Developer meeting:
It was agreed during the meeting that the approach in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-870599230 is a good way forward. Everyone agreed that for improved IDE support and the ability to instrument/customize individual Properties it is worth the effort.
Next steps are for a developer to investigate and implement more thoroughly, @samreid volunteered to be assigned.
@samreid also proposed a different solution, where colors can live at their usage sites. But they get an instrumentation to support customization through the "development colors html page". This would also mean that the color would exist in the PhET-iO tree for in the components that own them, much like other instrumented view Properties. Overall, there was a question about what having an explicit ColorProfile bought for us.
Next steps are to discuss this with a design team to decide what exactly we want for customizable colors and how much time we should invest in changing ColorProfile.
Marking for phet-io meeting because the changes suggested in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-876655914 will have some impact on the PhET-iO API for colors, and there are things here that we want to discuss with design team.
I also saw a paper trail starting at https://github.com/phetsims/scenery-phet/issues/156#issuecomment-145726828 which is what led to ColorProfile originally.
From PhET-iO meeting today:
PhET-iO designers are fine with us removing ColorProfiles, and moving color Properties into the sim. In general designers feel like the PhET-iO instrumentation level of colors will be limited (depending on client desires).
We should make color profile a singleton, and we should add support for having common code support. The singleton should live in scenery, and can be imported where ever a color is needed.
KP: We need to make sure that we are thinking about high contrast mode as we implement this.
We will keep the name "colorProfile" as the singleton
Any color can register and profile name to colorProfile, and then it is up to the sim to set only the profiles that it cares about.
This work is not blocking any soon-to-come sims, because no instrumentation of ColorProfile will change.
@samreid has offered to do the initial work on this (thanks!), and will take a shot at doing the work in the individual simulations as well. This plan can change if it's taking too much time.
UPDATE from @samreid: @pixelzoom mentioned that it may be more efficient to do his own sims, after a pattern is established. I'll evaluate when further along.
I asked @arouinfar in slack:
For Gravity and Orbits, I noticed about 10 colors that were all white by default, and black for “projector”. Is it OK to coalesce many or all of these into a single “foreground color” property?
She replied:
Sure
Summary of changes in the upcoming commit:
'default'
or 'projector'
.'name'
which is shown in the HTML color editor. Currently the tandem is a fallback if the name is not provided, but we should probably require 'name'
for now. There is a TODO about that. Names no longer need to be camel cased.null
(the new way, which automatically wires up to the singleton).colorProfiles
which is an array of strings that says which color profiles are supported in the sim. Once all sims are using the new strategy, this will replace colorProfile:boolean
. package.json:colorProfiles
is used to guard valid values of the colorProfile query parameter.foregroundColor
and vice versa for backgroundColor
Next steps:
I also notified about current status on slack.
CT is showing this error: Uncaught Error: Assertion failed: colorProfile must have a profile named undefined
. I'll take a look.
I pushed fixes for the current column of CT issues and will keep an eye on the next column.
Many colors were moved to their usage sites. Colors used in many different places were moved to GravityAndOrbitsConstants.js
There is a problem with this. For instance, assume there are 2 screens, Screen A and Screen B. If both screens are supposed to always have the same background color, they should use the same ColorProperty. However, if the ColorProperty is defined in the Screen constructor, they will have different ColorProperties. Defining it locally in the file as a class-static would work, but not a good match for phet-io, which does not track static tandems. So many of the ColorProperty instances we have seen should remain factored out, and cannot be moved to individual files. On the other hand, if we want the screens backgrounds to vary independently, then it is OK to define the ColorProperty locally. Maybe as a first pass, we will just leave most or all things in the ColorProfile files.
Defining it locally in the file as a class-static would work, but not a good match for phet-io, which does not track static tandems.
But we could come up with a convention for this, if it is otherwise the best plan.
Marking as blocks publication while sims are using different strategies.
ProportionPlaygroundColorProfile history has inadvertently deleted, so I restored it through reverts.
Summarizing status since this issue is getting long. The main changes are described in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-881909812, beyond that there has been a naming improvement and simplification for singleton pattern. The problem in https://github.com/phetsims/scenery-phet/issues/515#issuecomment-881955316 had me rethinking this whole issue since colors are usually per-type instead of per-instance, but I decided to proceed anyways since using the new pattern unlocks PhET-iO instrumentation and IDE support in a nice way even though there is added boilerplate. UPDATE: We can additionally scatter the colors to separate files as long as we set up a convention for the tandems (noting that the tandem tree would look a lot like it does right now, since tandems are instance based not class/static-based).
Finally, I left the @pixelzoom sims for last, considering whether I should take @pixelzoom's offer that it may be equally or more efficient for @pixelzoom to work on those, but there are some finalization steps I cannot work on until all cases are addressed, so I will do my best on those cases for now.
One stylistic question is about filename casing: according to our code review document, singletons should be lowercased, like gravityAndOrbitsColorProfile
and I have updated many of them. However, I didn't know if there would be pushback about lowercasing things like FMWColorProfile
to fmwColorProfile
. So for that class of file, I'll leave the case alone until I have guidance about that.
Likewise, for GasProperties, there are numerous files breaking the singleton lowercase naming convention, so I'll leave those up to @pixelzoom to determine how to proceed.
One stylistic question is about filename casing: according to our code review document, singletons should be lowercased, like
gravityAndOrbitsColorProfile
and I have updated many of them.
I recall that our decision was to have a single global ColorProfile, managed by scenery, that all repos (sims and common-code) will register with. I'm guessing it will be phet.scenery.colorProfile
or something similar. That would make this issue of names like gravityAndOrbitsColorProfile
moot.
Is that still the plan?
EDIT: This also becomes unnecesary with the global ColorProfile:
package.json now supports colorProfiles which is an array of strings that says which color profiles are supported in the sim.
Scenery defines colorProfileProperty
but each sim still needs a place to specify sim-specific colors. For instance, see GasPropertiesColorProfile
in master.
Could we call it instead GasPropertiesColors
?
Could we call it instead
GasPropertiesColors
?
Whether we call it GasPropertiesColors
or GasPropertiesColorScheme
or GasPropertiesColorProfile
seems approximately equally good to me. I'm happy with GasPropertiesColorProfile
because that is the term used elsewhere to indicate the colors are selected from among profiles, like ProfileColorProperty
. I don't think it would be confusing for GasPropertiesColorProfile
to contain other color-related things other than ProfileColorProperty
instances.
@samreid and I discussed on Zoom, he brought me up to speed, looks nice.
Re GasPropertiesColorProfile vis GasPropertiesColors... The former perpetuates a problem that ColorProfile
had -- it's not a single profile, it's a description of 1 or more profiles (plural). Using something other than "color profile" would allow us to ditch that baggage.
Isn't the goal/dream of this issue that modern sims would have have this culminating file of colors, and that instead they would be integrated into the usage sites, or put into CONSTANTS files if needed? So perhaps this is a bit of a moot point? I'm really fine with anything and any pattern as long as we don't suffix with ColorProfile
because these are not ColorProfile instances. We only have one of those, in scenery.
I'm really fine with anything and any pattern as long as we don't suffix with ColorProfile because these are not ColorProfile instances. We only have one of those, in scenery.
We don't even have 1 ColorProfile instance in scenery. We have colorProfileProperty.js, which is a StringProperty that every ProfileColorProperty observes. My understanding is that ColorProfile will be going away.
Yes, I'll be deleting ColorProfile soon.
A reminder of summary comment https://github.com/phetsims/scenery-phet/issues/515#issuecomment-882518280
Reminder to:
I've completed everything for this issue or moved remaining work to side issues. This is a lengthy issue, but I reviewed most of it with @pixelzoom in a meeting this morning. I also thought it was appropriate to ask @pixelzoom to review https://github.com/phetsims/chipper/issues/1061, @pixelzoom do you also have time to review this issue? Please keep in mind a few remaining parts have been moved to side issues.
To review:
I discovered while adding tandems to Gas Properties in https://github.com/phetsims/gas-properties/issues/30 that
ColorProfile
is not set up for PhET-iO use. I'm not sure how important it is, that would be a question for designers. But I can imagine clients wanting to (for example) customize the color of particles in Gas Properties.