Input needed: functions wishlist

I think that’s the key to adding functions:
If it’s common enough to be used regularly, and will be much faster than doing it in userspace code (as part of a pattern) then the only real question is “is it worth the space it’ll take up?”, since at some point, there are limits and trade-off.

Given the sensor board now, doesn’t it provide enough data to give you that value? Or do we need a better sensor?

Hi Scruffynerf,
You’re correct that the existing sensor board functions give me enough to data to calculate the wheel position using some trig functions, but a built-in function would eliminate the need for me to replicate that calculation and JS code within every pattern. Also, the calculation might be faster if it was implemented by the PB, which I assume is running compiled code rather than JS.

I do realize that this may not be something that’s useful to a lot of people, but I thought I would throw it out there just in case.

Compiled binary implementations would also be a lot smaller than JS, so we hit those trade-offs after many, many common-ish functions.

Maybe we need a way to side-load binary implementations, though. It would be nice to be able to write something in C on my computer and expose it as a function to my patterns.

Even a JavaScript library would be nice, like a side-table of JS functions which are only compiled into your pattern if you import them by name.

It feels to me like we are trying to solve multiple problems and it’s not clear to me that there is just one solution.

1 Like

In the periodic update sent over the websocket - this one:

{
  "fps": 19.06578,
  "vmerr": 0,
  "vmerrpc": -1,
  "mem": 10239,
  "exp": 0,
  "renderType": 1,
  "uptime": 27410873,
  "rr0": 1,
  "rr1": 14
}

Include an accurate RGB representation of the current pixel 0 colour, ie

"rgb": [0,0,0],

Or some other similar way of obtaining the accurate RGB value of a specific index (pixel).

I use this value to synchronize other non-addressable LED lights to the strip colour (eg deck lights, deck lamp).

1 Like

Complex numbers

While I could steal some code from

Having complex number functionality built in would allow a lot of fun math (and displays) that right now aren’t easy to build.

Basic port of the above is now here. That should suffice, until/if it’s added to the math in PB.

Complex numbers and 2D/3D vectors would be nice. I’d actually settle for the ability to allocate (small) temporary arrays on the stack. (and to declare and use multi-dimensional arrays in the normal a[x][y][z] way.)

I’m not asking for garbage collection or heap management – array() can still be a one time allocation. Even if stack space is severely limited, it’d be nice to be able allocate say, a 2D point to use for temporary calculation in a function without having to use a globally allocated array.

1 Like

Similar to an Arduino, have a function setup() which gets run once when a pattern is loaded.

Then you can put all your setup code in there, so you could pre-load tables and such.

1 Like

Maybe it’s bad practice but I just bit that all up top outside of any other function. Runs once!

1 Like

Same. It works fine. That’s one of the advantages of PB.

Right, init/setup code is the code in the main body of the pattern “module,” and is run once when the pattern loads. Even if you don’t write a bunch of code there, just the code setting up exported variables and functions is still being run.

That is different than in a C code file where you generally can’t write arbitrary code outside of a function in the outer file area, and only declarations are possible (which still might evaluate expressions and cause code to run though).

It’s normal for JavaScript modules to do some basic module setup in the module’s body of code, even if it’s just to import/export and set up a function or variable. JavaScript / ES6 module system gave the core language a way to handle module dependencies and sharing and to ensure that things are initialized in the right order based on those dependencies. Some frameworks might give you a hook for initialization, but that is framework dependent.

Arduino popularized the setup() + loop() framework because hitting a beginner with this boilerplate C code is counterproductive:

#include <stdio.h>
int main(void) {
  //put your setup code here
  for(;;) {
    //put your main loop code here
  }
}

By the way, render and beforeRender etc are just variables, like other exports. They just happen to be set to functions while the module code is run and usually only point to a single function definition.

Here is a trick that I’ve been avoiding using because it can lead to things that are too clever (harder to read/understand):

export var render
var redRender = () => hsv(0,1,1)
var greenRender = () => hsv(.333,1,1)
if (random(1) > .5)
  render = redRender
else
  render = greenRender

In the above pattern, each time it is run the render variable’s value is randomly chosen though the setup/init code in the main pattern body to be one of 2 possible functions. I’ve specifically avoided coding anything like this, preferring to add code in a generic render that dispatches to other functions because I think it could get very confusing.

There are also some possible JavaScript / ES6 ways of exporting that we haven’t used. You can do something like this, though there is little reason to do so now:

var redRender = () => hsv(0,1,1)
export {redRender as render}

Here’s some more export syntax examples.

2 Likes

Rubbing my hands and cackling wildly at the new insights based on realizing this exists.

Thing that I found is that you can’t call a function before it’s been defined (no forward declarations).

Also once everything is loaded, the loading mechanism then calls all the slider functions to set them to the preset values, so if you call a function in a slider definition, the initial code runs, then the functions defined in slider functions run - all of them but I don’t know in what order.

But you’re right, you don’t need a setup() function.

Don’t forget that a slider only loads the previous value IF it’s been saved by running previously. On first run, the slider won’t do that.

@wizard , I know it’s on the bottom of the editing page on the PB, but could you update the website expression page?

Pixelblaze Expression Docs — Ben Hencke is still lacking all of v3 changes like array functions, and so on.

I find myself using that page more often when I’m online as it’s handy.

@Scruffynerf
Thanks for the heads up. I had forgot that was there! I’ve updated the page with links to the GitHub source docs.

I think Smooth Speed Slider is a good candidate for a built-in function. Many PBers will encounter the problem early, and be confused at first. The subtlety of the smooth solutions in that thread might be over the average head. I had pondered the ‘maintaining phase’ aspect but was glad to find it solved for me!

1 Like

@sorceror ,
Yes, that has been discussed before as well, and is on the list.

Goals:

  1. A global speed slider like brightness
  2. Changing speed without causing animation jumps
  3. Not breaking timesync across multiple PB - sync the global speed too.
  4. New stateful API, perhaps a timer object, to keep track of internal phase state.
  5. Both timer adjustable speed and global speed so you can add more speed sliders in addition to the global one to fine tune some particular aspect.

Not really a function, but … I was thinking that it would be neat if there was a way to retain values between pattern changes. So for example, to keep a time-slider-controlled wave smooth, or to set a “theme color” which applies to every pattern in a playlist.

Maybe something like:

 export persistent var foo;

which stores foo’s value in a metaglobal hash table when leaving a pattern, and restores it after the next pattern is compiled.

2 Likes

At first, I didn’t understand, I was like “but pattern vars do persist, if you leave and come back…”

but you meant a shared var for multiple patterns.

Yeah, that would be interesting, a ‘superglobal’.