JSFX Dojo

So in the @serialize section,

are those 2 lines meant to be indented?
Tale had it like that, unindented

You sure did, and in the next post you quoted the section of the JSFX guide where it says the second half is @init only. :slight_smile: Thatā€™s the second half, for the first part:

gfx_ext_retina = ext_noinit = 1;

ā€¦ as I said a few days back, Iā€™m not sure any gfx_XXX stuff is supposed to be in @init. I had a gfx_setfont in @init and the font wouldnā€™t consistently be set to the font, so I think that @gfx sometimes gets run first ahead of @init. This would mean that variable isnā€™t noticed sometimes. I know Herr Frankel frowns upon it.

This:

@block
  // code starts here


@gfx 200 200
  // code starts here

vs

@block
// code starts here


@gfx 200 200
// code starts here

ā€¦ is just a style choice since whitespace is irrelevant in terms of execution. I just prefer have the @sections in their own indented blocks. Most people donā€™t do that so itā€™s up to you.

edit: fixed whitespace :smiley:

I also had mixtures of capitalised and non-capitalised comment-section lines
Just made them all capitalised now for consistency

TrackNotes_v2.jsfx (5.0 KB)

LOL I should have read that a little closer sorry
esp the part that reads:

Context: @init only
Set this variable to 1.0 in your @init section

The details are easy to skip when youā€™re hoovering up new stuff and are only easier for me to see here since the rest is familiar. Saying that, I havenā€™t read over those docs in some time so there might be some killer feature Iā€™ve missed.

Hereā€™s something from my Windows 'pute I did a few days ago re a responsive gui demo too. Might as well throw it into the mix:

desc:Tiny demo of responsive GUI


@init
  // don't call any 'gfx_' functions here, even if it's really
  // tempting
  

@sample
  spl0 = spl0;
  spl1 = spl1;


// remember that we are just requesting these dimensions
@gfx 400 400

   // choose the Nicest System Font(tm)
   gfx_setfont(1, "Verdana", 16);
   
   // set this var so we can query a nicely named thing when we want
   is_gui_height_small = gfx_h < 150;
   
   // in reaper 6.30+ we can check if the gui is actually embedded 
   // in the tcp or mcp by checking...
   is_gui_embedded = gfx_ext_flags & 1;
   
   // now we can set actual dimensions/positions depending on the
   // real size of the window
   gui_margin_top = is_gui_height_small ? 0 : 30;
   
   // just draw a diagonal line below any margin to bottom right
   gfx_x = 0;
   gfx_y = gui_margin_top;
   gfx_set(1, 0, 0, 1); // set rgba for drawing
   gfx_lineto(gfx_w, gfx_h, 1);
   
   // now we can choose to only display some stuff when the window is
   // big enough...
   !is_gui_height_small ? (
     // that ^^^ is much more fluid than writing 'gfx_h < 150' all the time
     // and we only have to change the 150 value in one place now if
     // we ever want to
     
     gfx_x = 3;
     gui_title_str = "This is a line of text";
     
     // we are going to center the text vertically in the top margin
     // area, so first we need to measure the string height.
     
     // '_' and 'h' are "output" variables, they are set by the 
     // function. in eel2/jsfx they don't have to be declared before
     // the function call.
     // The variable name '_' is a just a general naming convention 
     // which means we are not interested in that result, in this case 
     // the width of the string.
     gfx_measurestr(gui_title_str, _, h);
     
     // position the y 'cursor' half a string height above the
     // halfway mark.
     // notice that there are no parentheses because we are just using
     // the fact that '*' has a greater precedence than '-' ...
     gfx_y = gui_margin_top * .5 - h * .5;
     
     // ... but when it's trickier or non-obvious it's better to put parens 
     // around stuff:
     // gfx_y = (gui_margin_top * .5) - (h * .5);
     
     // dazzling full white is frowned upon and we're not monsters, so 
     // we'll tone it down a tad
     gfx_set(.85, .85, .85, 1);
     gfx_drawstr(gui_title_str);
    );
    
    // here we decide to show something by querying one of our handy vars. 
    // this time, obviously enough, only if the gui is in fact embedded
    is_gui_embedded ? (
      // draw green, centered, semi-transparent square
      gfx_set(0, 1, 0, 0.3);
      square_size = is_gui_height_small ? 40 : 90;
      gfx_x = gfx_w * .5 - square_size * .5;
      gfx_y = gfx_h * .5 - square_size * .5;
      gfx_rectto(gfx_x + square_size, gfx_y + square_size);
    );
1 Like

Appreciate the code review Snooks
Exactly what I wanted, point out everything not 100%
A nudge in the right direction, or an example where that failed

I think Ill retain all that now, having worked through it
Iā€™ll record some notes to be sure

That last graphics stuff looks great, Ill try it out later today

This is way cool, my #1
First thing Ive made via coding thats really useful and Iā€™ll use every day
Even if I did borrow the core of it, and needed mentoring to finish it

No problemo, itā€™s all very therapeutic for me anyway. Code reviews can be brutal as people rip your code apart and formatting crapola isnā€™t a nice thing to bicker over since itā€™s kind of opinion beyond a certain point. Consistency is the key thing, and non-crappiness. :slight_smile:

Taleā€™s stuff still isnā€™t indented like the rest btw, I really recommend getting a Gogs server set up or just using private online repos to get used to git and to have a different read-only view. I sometimes also go from neovim to other editors and things jump out there too.

So not only is the CPU on this plugin uber-low,
0.5% for 50 tracks or so

You can bypass the effect after setting it up, and it still displays the same on the tcp, mcp or plugin window

No CPU cost at all!

Thatā€™s pretty special, I like it even more

Yeah, I left Taleā€™s init section and the latter section intact just to keep my code separate from his
Apart from indenting @serialize, cause it was minimal and right above my @slider code
It would just be one global indent in from the margin to match, at a guess


Do you know the order of execution here Snooks?

TrackNotes_v2.jsfx (5.0 KB)

It seems to be:
sliders,
@init
@serialize
@sliders
@gfx

Taleā€™s code after the @gfx section, what is going on there from line 165 on?
Itā€™s not part of the previous @ sections, is it?
Is it still part of the @gfx section?
Or should it be moved to the @init section? ā† I assume the gfx code needs to be before the character getting etc

I donā€™t quite understand what happens from there, how you end sections without calling something else

The @gfx stuff is on a different thread so we cannot predict if it will run before or after @init. I know from the example I mentioned of a font not changing consistently when set in @init that the first @gfx frame sometimes runs before @init.

I remember there was a bit of an argument over when @serialize runs in relation to @init too, donā€™t remember the details though. For our porpoises I think we can assume that the order you is approximately right, but I donā€™t know for sure.

The @sections end when either another @section begins or when the end of file (EOF) is reached. So Taleā€™s code at the bottom is part of the @gfx section. His other functions are defined at the top of the file.

Thereā€™s an important difference between a function being defined and a function being called. He doesnā€™t use any gfx_ functions or variables in his functions, so they can be defined anywhere and called from anywhere. If they contained gfx_ stuff then they can be defined anywhere but should only be called from the graphics thread, i.e. @gfx.

edit: actually I donā€™t know about that ā€œdefined anywhere, called anywhereā€ thing since order of execution of different sections is different. Iā€™d just put all functions for @gfx in @gfx to be safe.

Hereā€™s the official quote about gfx_ functions and vars:

These functions and variables must only be used from the @gfx section. 

https://www.reaper.fm/sdk/js/gfx.php#js_gfx

So you should also definitely, definitely split the gfx_ext_retina = ext_noinit = 1; line and put the gfx_ part in @gfx. Iā€™m sure thereā€™s probably scripts out there that donā€™t, but we should listen to the glorious leader and not our fellow minions.

Cool, so itā€™s the @gfx section until the file end.

So just to clarify,
when it executes @ init or @gfx etc,
is it inserting the gfx code into the program at that point, like an #include statement?

Like with C++ or Python, for a native function you can click on ā€˜go to definitionā€™ in vscode and it takes you to the related compiler or interpreter code

But, where are the Reascript definitions? Invisible in Reaper?

The way the EEL2 setup works when you are using it yourself in C/C++ is that the @sections are compiled separately and called separately. But while the one big text file we write is broken down into chunks, they still share global variables.

So in Reaper there will be a graphics thread which will call the code handle we see as @gfx while the audio thread will be calling the other sections. Maybe for seamless saving the @serialize stuff is called from a different thread as well which is why the discussion I remember happening happened.

I indented the @init section and the @gfx latter section
Why not

TrackNotes_v1.jsfx (5.3 KB)

Itā€™s looking really good now, just that gfx_ variable set in @init now and Iā€™m only a little twitchy over the non-indented comments within @sections since they are commenting on stuff that happens within and not outside them. Iā€™ll be alright though. :slight_smile:

Are you saying to split it like this?

[ in @init]
ext_noinit = 1

[in @gfx]
gfx_ext_retina = 1
(or maybe gfx_ext_retina = ext_noinit) ??

Here I was thinking I was a bit OCD
Makes sense though, so done

I had to go through and check the comment line end column numbers match after changing that :smiley:

Yes, thatā€™s the right split.

Youā€™re twitches took you in a different direction there re the line endings. I save the long comment splits for @sections and have half length splits for within a section. Thereā€™s precedence baked into that system where you can look at very zoomed out code and see what everything is still.

Itā€™s all extremely tragic, I know! :smiley:

Sounds smart
Iā€™ve set it to 70 columns for section splits now, and 50 columns for within section splits
My OCD would have liked it exactly double,
but the comment names were all 40+, and 90/100 is a bit wide

I split and moved that line also

TrackNotes_v1.jsfx (5.3 KB)

Yeah, the no compromise solution is to not put any text in those and just use them as separators with comments on other lines. But itā€™s doesnā€™t matter at this stage anyhoo.

What does matter is the style of if/elses that Tale used in this very script! This syntax is specific to EEL2 and gets rid of having to cascade to avoid missing parens and breathe via paper bags!:

  backcolor == 0 ? (
    gfx_clear = 0x000000;       //! Black 
  ) : 
  backcolor == 1 ? (
    gfx_clear = 0x222222;       //! Grey
  ) : 
  backcolor == 2 ? (
    gfx_clear = 0x00A5FF;       //! Orange
  ) : 
  backcolor == 3 ? (
    gfx_clear = 0x0000FF;       //! Red
  ) : 
  backcolor == 4 ? (
    gfx_clear = 0xFFFFFF;       //! White
  );
1 Like