Old 05-14-2018, 04:49 AM   #1
Flosch259
Human being with feelings
 
Flosch259's Avatar
 
Join Date: May 2018
Posts: 2
Default JSFX scrollbar (too much slider)

Hello,

I want to write a JS Plugin which routes 18 Tracks, has a fader per channel, is able to link channel pairs and turn them off and on.

This is the code so far:
Code:
desc:18x Stereo to 18x Stereo Mixer/Router [flosch259]
//tags: mixer gain
//author: flosch259

//In/Out Pins 18/18

in_pin:input 1
[...]
in_pin:input 18

out_pin:output 1
[...]
out_pin:output 18

// Slider Pairs

// Pair 1,2

slider1:0<-60,12,0.1>Level 1 (dB)

slider2:1<0,1,1{Off, On}>On/Off Channel 1

slider3:0<0,1,1{Unlinked, Linked}>Link Channel 1/2 (Level&On/Off)

slider4:0<0,20,1{Output 1,Output 2,Output 3,Output 4,Output 5,Output 6,Output 7,Output 8,Output 9,Output 10,Output 11,Output 12,Output 13,Output 14,Output 15,Output 16,Output 17,Output 18,Output 19,Output 20}>Route 1

slider5:0<-60,12,0.1>Level 2 (dB)

slider6:1<0,1,1{Off, On}>On/Off Channel 2

slider7:1<0,20,1{Output 1,Output 2,Output 3,Output 4,Output 5,Output 6,Output 7,Output 8,Output 9,Output 10,Output 11,Output 12,Output 13,Output 14,Output 15,Output 16,Output 17,Output 18,Output 19,Output 20}>Route 2

// Pair 3,4
[...]
// Pair 17,18

slider57:0<-60,12,0.1>Level 17 (dB)

slider58:1<0,1,1{Off, On}>On/Off Channel 17

slider59:0<0,1,1{Unlinked, Linked}>Link Channel 17/18 (Level&On/Off)

slider60:16<0,20,1{Output 1,Output 2,Output 3,Output 4,Output 5,Output 6,Output 7,Output 8,Output 9,Output 10,Output 11,Output 12,Output 13,Output 14,Output 15,Output 16,Output 17,Output 18,Output 19,Output 20}>Route 17

slider61:0<-60,12,0.1>Level 18 (dB)

slider62:1<0,1,1{Off, On}>On/Off Channel 18

slider63:17<0,20,1{Output 1,Output 2,Output 3,Output 4,Output 5,Output 6,Output 7,Output 8,Output 9,Output 10,Output 11,Output 12,Output 13,Output 14,Output 15,Output 16,Output 17,Output 18,Output 19,Output 20}>Route 18

@slider

//Slider 1,2

Link12 = slider3; // Links first, otherwise only the display value will update

Link12 > 0 ? slider5 = slider1; // Links the Volume Slider 1+2
Link12 > 0 ? slider6 = slider2; // Links the on/off

Level1 = 2 ^ (slider1 / 6); //Level
Mute1 = slider2;
Route1 = slider4;

Level2 = 2 ^ (slider5 / 6); //Level
Mute2 = slider6;
Route2 = slider7;

//Slider 3,4
[...]
//Slider 17,18

Link1718 = slider59;

Link1718 > 0 ? slider61 = slider57;
Link1718 > 0 ? slider62 = slider58;

Level17 = 2 ^ (slider57 / 6); //Level
Mute17 = slider58;
Route17 = slider60;

Level18 = 2 ^ (slider61 / 6); //Level
Mute18 = slider62;
Route18 = slider63;

@sample

// Level and Mute

spl20 = spl0;

[...]

spl38 = spl18;

spl0 = 0;

[...]

spl18 = 0;

spl(Route1) = spl(Route1) + (spl20 * Level1 * Mute1); //Output Sample is multiplied with the level value and mute factor

[...]

spl(Route18) = spl(Route18) + (spl37 * Level18 * Mute18);

My problem is, that there is not enough space for 63 sliders/UI elements. The default UI only displays up to the 11th level fader, which is slider 36.
How do i make a scroll bar, or move/resize UI elements? When you turn of the UI of vst plugins, there's a scroll bar automatically.
Also, if you see a way to make the script more efficient please tell me. I'm new to this and want to learn as much as possible. This is intended for live usage after all.

Last edited by Flosch259; 05-14-2018 at 04:58 AM. Reason: typos and code usage
Flosch259 is offline   Reply With Quote
Old 05-14-2018, 06:32 AM   #2
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 4,906
Default

This has been requested but is not currently implemented.

Wht you have to do is to draw your own GUI elements.

If you want to go faster than building things from scratch, you can use the advanced geraintluff JSFX GUI framework.

https://geraintluff.github.io/jsfx-ui-lib/
X-Raym is offline   Reply With Quote
Old 05-14-2018, 11:45 AM   #3
Flosch259
Human being with feelings
 
Flosch259's Avatar
 
Join Date: May 2018
Posts: 2
Default

Thank you!
I will look into geraintluff.
Flosch259 is offline   Reply With Quote
Old 05-15-2018, 04:34 AM   #4
geraintluff
Human being with feelings
 
geraintluff's Avatar
 
Join Date: Nov 2009
Location: mostly inside my own head
Posts: 249
Default

The UI framework does not have scrollbars (for now - it's on my wishlist!). However, it can be used to make more compact layouts.

The simplest way to duplicate the existing slider layout is to split the space vertically:
Code:
import ui-lib.jsfx-inc

@init
// The UI library needs some of the memory buffer
freemem = 0;
freemem = ui_setup(freemem);

@gfx 
ui_start("main");
ui_screen() == "main" ? (

  // Divide space into 63 rows
  ui_split_topratio(1/63);
    // Label on right-hand side
    ui_split_right(100);
      ui_textnumber(slider1, "%.2f dB");
    ui_pop();
    // Slider from -60 to 12, linear, default 0
    slider1 = control_slider_x(slider1, -60, 12, 0, 0);
  ui_split_next();
    ui_split_right(100);
      ui_text(slider2 ? "on" : "off");
    ui_pop();
    // On/off switch
    slider2 = control_switch(slider2);
  ui_split_next();
    ui_split_right(100);
      ui_text(slider3 ? "linked" : "unlinked");
    ui_pop();
    slider3 = control_switch(slider3);
  ui_split_next();
    ui_split_right(100);
      ui_text("Output");
    ui_pop();
    // Selector
    sprintf(#display_text, "Output %i", slider4 + 1);
    up_value = slider4 < 19 ? (slider4 + 1) : 19;
    down_value = slider4 > 0 ? (slider4 - 1) : 0;
    slider4 = control_selector(slider4, #display_text, up_value, down_value);
  ui_split_next();
  // etc.
  ui_pop();

) : ui_system();
However, there's still not enough room - we end up squishing 63 sliders into the vertical space, so they end up really tiny. You could list the sliders in multiple columns:

Code:
@gfx 

// Make these functions, so we can re-use them
function draw_gain_slider(value) (
  // Same slider code as before
  ui_split_right(100);
    ui_textnumber(value, "%.2f dB");
  ui_pop();
  // Slider from -60 to 12, linear, default 0
  value = control_slider_x(value, -60, 12, 0, 0);
  // Return new value
  value;
);

function draw_switch(value, on_text, off_text) (
  ui_split_right(100);
    ui_text(value ? on_text, off_text);
  ui_pop();
  control_switch(value);
);

function draw_output_selector(value, on_text, off_text) (
    ui_split_right(100);
      ui_text("Output");
    ui_pop();
    sprintf(#display_text, "Output %i", value + 1);
    up_value = value < 19 ? (value + 1) : 19;
    down_value = value > 0 ? (value - 1) : 0;
    control_selector(value, #display_text, up_value, down_value);
);

ui_start("main");
ui_screen() == "main" ? (

  // Split into three columns
  ui_split_leftratio(1/3);
    // Each column has 21 rows
    ui_split_topratio(1/21);
      slider1 = draw_gain_slider(slider1);
    ui_split_next();
      slider2 = draw_switch(slider2, "on", "off");
    ui_split_next();
      slider3 = draw_switch(slider3, "linked", "unlinked");
    ui_split_next();
      slider4 = draw_output_selector(slider4);
    ui_split_next();
      // etc. - for all the other sliders
    ui_pop();
  ui_split_next(); // Second column
    //etc.
  ui_split_next(); // Third column
    //etc.
  ui_pop();
) : ui_system();
That fits everything in, but it's still just a big list of sliders.

However, here's a more advanced layout which might work for you. It's complex and the code is less easy to understand, but the controls are grouped together more intuitively.

The code's actually shorter than the previous examples, because it uses the slider() function to address sliders, so we can avoid duplication. Here's the complete @gfx block:

Code:
@gfx 520 530

control_start("main", "default");
// We don't have much space - reduce the font size and padding
ui_fontsize(12);
ui_padding(5, 5);

// Draws a two-channel pair in a single row
function draw_row(pair_index) local(left_channel, slider_start, link_control_width, slider_index, linked, left_on, right_on, display_value, output) (
  left_channel = pair_index*2;
  slider_start = pair_index*7 + 1;
  
  linked = slider(slider_start + 2);
  left_on = slider(slider_start + 1);
  right_on = slider(slider_start + 5);

  // Draw "link" switch right in the centre
  link_control_width = 60;  
  ui_push_width(link_control_width); // default alignment is central
    // Vertical padding only
    ui_pad(0, -1);
    ui_pad(0, -1);
  
    ui_split_topratio(0.5);
      ui_text("link");
    ui_pop();
    // Link slider
    slider_index = slider_start + 2;
    slider(slider_index) = control_switch(slider(slider_index));
  ui_pop();
  
  // Left-channel controls - draw to left of link switch
  ui_push_leftof(link_control_width);
    sprintf(#channel_display, "Channel %i", left_channel + 1);
    control_group(#channel_display);

    // Split into 3 even sections
    ui_split_leftratio(1/3);
      ui_split_topratio(0.5);
        // Top half: display gain, or "off"
        left_on ? (
          // Left gain display
          slider_index = slider_start;
          slider(slider_index) = control_hidden_textnumber(slider(slider_index), "%.1fdB");
        ) : (
          ui_text("off");
        );
      ui_split_next();
        // Bottom half: on/off switch
        slider_index  = slider_start + 1;
        slider(slider_index) = control_switch(slider(slider_index));
      ui_pop();
    ui_split_next();
      // Left gain dial
      slider_index = slider_start;
      left_on ? (
        ui_push_height(50); // Max dial height
          slider(slider_index) = control_dial(slider(slider_index), -60, 12, -3.2, 0);
        ui_pop();
      );
    ui_split_next();
      // Routing selector
      slider_index = slider_start + 3;
      output = slider(slider_index);
      // Format to temporary string
      sprintf(#output_label, "Output %i", output + 1);
      ui_padding(3, 10);
      slider(slider_index) = control_selector(slider(slider_index), #output_label, min(output + 1, 19), max(output - 1, 0));
      // Double-click to open output-selector dialog
      ui_click() && ui_clickcount() == 2 ? (
        ui_screen_open("output-selector");
        ui_screen_arg(0, slider_index);
        ui_screen_arg(1, left_channel);
      );
    ui_pop();

    // Left-side values might have changed - change right-side ones to match
    linked ? (
      slider(slider_start + 4) = slider(slider_start + 0);
      slider(slider_start + 5) = slider(slider_start + 1);
    );
  ui_pop();
  
  // Right-channel controls - draw to right of link switch
  ui_push_rightof(link_control_width);
    sprintf(#channel_display, "Channel %i", left_channel + 2);
    control_group(#channel_display);

    // Split into 3 even sections
    ui_split_leftratio(1/3);
      ui_split_topratio(0.5);
        // Top half: display gain, or "off"
        right_on ? (
          // Left gain display
          slider_index = slider_start + 4;
          slider(slider_index) = control_hidden_textnumber(slider(slider_index), "%.1fdB");
        ) : (
          ui_text("off");
        );
      ui_split_next();
        // Bottom half: on/off switch
        slider_index  = slider_start + 5;
        slider(slider_index) = control_switch(slider(slider_index));
      ui_pop();
    ui_split_next();
      // Left gain dial
      slider_index = slider_start + 4;
      right_on ? (
        ui_push_height(50); // Max dial height
          slider(slider_index) = control_dial(slider(slider_index), -60, 12, -3.2, 0);
        ui_pop();
      );
    ui_split_next();
      // Routing selector
      slider_index = slider_start + 6;
      output = slider(slider_index);
      // Format to temporary string
      sprintf(#output_label, "Output %i", output + 1);
      ui_padding(3, 10);
      slider(slider_index) = control_selector(slider(slider_index), #output_label, min(output + 1, 19), max(output - 1, 0));
      // Double-click to open output-selector dialog
      ui_click() && ui_clickcount() == 2 ? (
        ui_screen_open("output-selector");
        ui_screen_arg(0, slider_index);
        ui_screen_arg(1, left_channel + 1);
      );
    ui_pop();

    // Right-side values might have changed - change left-side ones to match
    linked ? (
      slider(slider_start + 0) = slider(slider_start + 4);
      slider(slider_start + 1) = slider(slider_start + 5);
    );
  ui_pop();
);

ui_screen() == "main" ? (
  control_navbar("18ch Router");
  
  ui_split_topratio(1/9);
    draw_row(0);
  ui_split_next();
    draw_row(1);
  ui_split_next();
    draw_row(2);
  ui_split_next();
    draw_row(3);
  ui_split_next();
    draw_row(4);
  ui_split_next();
    draw_row(5);
  ui_split_next();
    draw_row(6);
  ui_split_next();
    draw_row(7);
  ui_split_next();
    draw_row(8);
  ui_pop();
  
) : ui_screen() == "output-selector" ? (
  dialog_slider = ui_screen_arg(0);
  dialog_channel = ui_screen_arg(1);
  sprintf(#dialog_title, "Channel %i Output", dialog_channel + 1);
  control_dialog(#dialog_title, "done");
  
  ui_split_topratio(1/20);
    i = 0;
    loop(20, 
      ui_split_left(50);
        slider(dialog_slider) = control_radio(slider(dialog_slider), i); 
      ui_pop();
      ui_align(0, 0.5);
      ui_textnumber(i + 1, "Output %i");
  ui_split_next();
      i += 1;
    );
  ui_pop();
) : ui_system();
Here's what that looks like:



If you right-click on the decibel display, it gives you a text-entry box to edit the numerical value. If you double-click on the output selector, it opens up a dialog (which might be faster than using the arrows):



I did a bit of extra development this morning (undo/redo should now work, among other things), so it's worth grabbing the latest version.
__________________
JSFX set | Bandcamp | say thanks (donations)

Last edited by geraintluff; 05-15-2018 at 09:03 AM.
geraintluff is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 04:07 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.