@jeff, good stuff, thank you for your thoughts. I always like hearing your ideas, and I borrow a lot from them
My plan for aspect ratio is to handle that on the mapper tab so you don’t have to code around it. Perhaps a dropdown with these options:
-
fill
- This is default. If necessary, the map will be stretched or squished to fit every dimension.
-
contain
- The map keeps its aspect ratio, but is resized to fit the largest dimension.
-
cover
- The map keeps its aspect ratio, but is resized to fit the smallest dimension. Some of the map may go outside one world unit. Centered around 0.5.
Implementation-wise this is an initial transformation matrix that is applied. The map dimensions would still be normalized to take advantage of the full resolution. The code has this now, but it’s set to an identity matrix (same as fill). I think contain
would be transparent to patterns written for world unit coordinates between 0-1, they just wouldn’t be asked to draw the entire world. With cover
you might see coordinates out of that range, and most existing patterns would handle that OK, but not all.
I like the local storage analogy BoardVars, and string keys would be much easier to use and keep straight than save slots, if a bit harder to implement. I still have concerns if it is used in a playlist and persists each time, I wouldn’t want to write to flash every time the pattern cycles automatically.
@Scruffynerf, right my main concern is doing something that would create a bunch of returns, frustrate customers, and/or shorten PB’s useful lifetime.
I’m starting to see these as potentially 2 different, not necessarily unrelated things:
- A system for sharing state across patterns, or within a single pattern between runs.
- A system for saving state between resets, in flash.
These could work together or independently.
I kicked off this new thread because I found @Petros’s use case for physical controls interesting, plus it’s slightly different from previous discussions. Looking back, I didn’t see an explicit request to save those values on flash permanently, just between pattern switching, but that is where my ideas tended toward.
I could certainly see persistent state useful for the multi segment pattern, are there other asks for persistence specifically?
If these are separable features, I’m happy to focus on the shared state first.
@zranger1, I’m coming around to see what you meant with system/library/palettes.
We’ve previously talked about global code, and I think there’s ideas there that blend with some of the asks here. Global code with its own state could solve much of the non-flash use cases if it persists between patterns.
Imagine that global code could be done in an extension or plugin kind of way. Like patterns, you could install one or more of these extensions. Extensions are a module (just like a pattern) and could export variables. Unlike library code, extensions have a lifecycle outside of the pattern itself.
On the pattern side, we’d use the import
directive to consume exports from an extensions. Import can fail if the module doesn’t exist, and the importer doesn’t define the values/defaults. Import accepts a string/path, can specify which identifiers are of interest, and rename them for local use.
An extension could share an array (an in-memory saveSlot if you will), or expose an API:
export var sharedArray = array(100)
var counter = 0
export function callCount() { return ++counter }
var mode
export function getMode() {return mode}
export function setMode(newMode) {mode = clamp(newMode, 0, 10)}
And used in a pattern, renaming as needed:
import {sharedArray as foo,
callCount as bar,
getMode,
setMode
} from 'extensions/myExtension'
Note that import
would copy the exported var to a local var, so you can’t assign a new value to an imported variable and have it change the extension’s state, but an array is a reference and could be mutated, and functions could be called which can handle pretty much anything else.
You could implement getters/setters for a set of names instead of exposing an array for a bit more structure to keep things clear. Not quite the same as a key value store.
I think extensions might have a slightly different API / convention, but I could see how shared UI controls, access to gpio, etc. would let you write an extension to handle a lot of that stuff and share it across patterns.