[2.0] Proposal: A standard mechanism for reading renderer state
As discussed with @limzykenneth, there is not currently a consistent usage pattern for reading renderer state properties. In some cases (e.g. textWeight()) calling the function with no argument returns the current setting, while in other cases (rectMode(), for example) it results in an error message.
There are many use-cases for this information (for example, writing a function which needs to adjust to the various rect-modes) and in v1.x, people have used non-API access like _renderer._rectMode. In 2.x, this info is available in _renderer.states, also not part of the API, and also not available in global mode (for example, in the editor, where one would have to do p5.instance._renderer.states.rectMode.
The proposal here is to standardise the API so that calling no-argument versions of the state-setting functions return the current values. This will require evaluating whether there are existing uses of any of the existing no-argument versions of these methods (for example, randomSeed()) as well as checking for any other problematic cases
Drawing functions
- [x] background
- [x] fill
- [x] stroke
- [x] tint
- [x] rectMode
- [x] colorMode
- [x] blendMode
- [x] imageMode
- [x] ellipseMode
- [x] strokeWeight
- [x] strokeCap
- [x] strokeJoin
- [x] pixelDensity
- [x] cursor
- [x] rotate
- [x] translate
- [x] scale
- [x] bezierOrder
- [x] splineProperty
- [x] splineProperties
- [x] ~noiseSeed~
- [x] ~randomSeed~
- [ ] shearX ?
- [ ] shearY ?
Text functions
- [x] textAlign
- [x] textLeading
- [x] textFont
- [x] textSize
- [x] textStyle
- [x] textWrap
- [x] textDirection
- [x] textWeight
- [x] textProperty
- [x] textProperties
Questions
1. what to return for the no-arg functions dealing with color (fill, stroke, etc)?
In the current implementation I simply return the full color object, but an alternative that might be more manageable for new users would be to return a 4-element array in the current color-mode. Any thoughts @limzykenneth, @davepagurek, others?
2. how to handle background() ?
Currently we don't save the background color when we set it - my suggestion is to save this in renderer.states as a color object
3. how to handle randomSeed() and noiseSeed() which already have no-arg functionality?
Thanks for putting this together @dhowe . Just my 2 cents:
- I have no objections to
background()returning the color, and storing that inrenderer.states. - If
fill()stroke()background()return theColorobject rather than array would allow easier use ofColorutilities (for example, the contrast check). If they return the more easy-to-read array, that seems more useful for debugging. Arguably, for debugging,_renderer.statesis sufficient; one benefit for standardizing renderer state reading functions is to make them more usable in program logic. From that POV, I think color object makes more sense. - Re:
noiseSeed()andrandomSeed()- please see https://github.com/processing/p5.js/issues/7711. Per @limzykenneth:
That is not possible, when
randomSeed()is not explicitly called,random()delegates to Math.random() (ie. p5.js is not randomizing the seed by default at the start), and it is not possible to retrieve the seed value of Math.random() (not to mention they use different RNG implementation depending on the browser). Changing unseeded RNG to use our own RNG implementation presents performance tradeoff, ie.Math.random()is significantly faster than our seedable RNG implementation.
On reflection after that discussion, it seems randomNoise and randomSeed without arguments would have to stay as they are.
In addition to adding the setters listed above (let me know if I am missing any), I've made the following changes:
- updated
paramaterData.jsonfor functions above to accept no-argument calls - for getters that return an object (
textAlign,scale,translate, etc.), the setter now accepts that object - added
background(either a color or an image) torenderer.state - all color-related getters return
p5.Color - no change to
randomSeed()ornoiseSeed()for now - added tests for all of these in
test/unit/core/properties.js
I would think fill(), stroke() etc to return p5.Color as it is more flexible than an array of numbers which can have ambiguities around the color mode and color range.
background() is a bit different though as it is not really a state, ie. if you have drawn on top of the background, calling background() again doesn't preserve those things drawn on top and change the background color but rather draw over the whole thing. I'm not sure utility wise and in terms of conceptual understanding whether it would make sense to have a background state.
For randomSeed() and noiseSeed() as mentioned in #7711 the behavior of calling them without arguments set a random seed is not documented and something I find rather unusual/not very useful. As such it can be argued that randomSeed() and noiseSeed() without arguments are undefined behavior that we can set a new behavior for them, eg. returning set seed value if any or null/undefined if not set.