# Is there a more efficient way to make ui_menus?



## Mike Greene (Mar 21, 2016)

I'm running into "parser stack overflow" errors in my script, which I assume is because my init callback is past the 5,000 line limit. (Or whatever the limit is for Kontakt 5.2.)

What's making the init callback so big are all the ui_menus that I have. I'm giving the user the ability to assign their own choice of drums, keyswitches and fills to each of the 88 keys on a keyboard. That's 88 keys times 98 choices = 8,624 add_menu_item lines. Each of the 88 keys' menus looks this:

```
declare ui_menu $Keyswitch_Assign_21
add_menu_item($Keyswitch_Assign_21,"Kick",1)
add_menu_item($Keyswitch_Assign_21,"Snare",2)
add_menu_item($Keyswitch_Assign_21,"SnareAlt",3)
add_menu_item($Keyswitch_Assign_21,"HHClosed",4)
...
add_menu_item($Keyswitch_Assign_21,"Fill 53",97)
add_menu_item($Keyswitch_Assign_21,"Fill 54",98)
```

Normally, I can be more efficient by assigning array id's, like this:
%Keyswitch_Assign_ID_Array[21] := $Keyswitch_Assign_21
Then do all my assignments in a while loop. But unlike $CONTROL_PAR_PICTURE or $CONTROL_PAR_FONT_TYPE, I don't see a way to add menu items in a set_control_par(...) command.

Any advice?


----------



## Mike Greene (Mar 21, 2016)

I did more digging in the manual and realize I forgot about this method:

```
$count := 1
   while($count < 99)
       add_menu_item($Keyswitch_Assign_21, !String_Array[$count], $count)
       inc($count)
   end while
```

At least I *think* that should work. This still eats up almost 500 lines, though, and my init callback is already reeeeally long, so if there's an even slicker method, I'm all ears.


----------



## gregjazz (Mar 21, 2016)

Maybe handle as much of the initialization as you can in the "on listener" or better yet the "on persistence changed" callback? Anything that doesn't explicitly need to be in the on init callback (e.g. declaring variables, adding menu items, etc.) can be moved to this second "post initialization" section. Especially stuff like positioning and displaying interface controls. That should alleviate the parser stack overflow error you're running into.


----------



## neblix (Mar 21, 2016)

I would suggest an alternate solution to ui_menus for such a task. The line complexity of adding that many menu items is straight-up unreasonable.

You could for instance instead make an interface where you click a button and a "browser" of sorts opens up, where you can display a small portion of the items in the list "scroll" through the giant list by using a couple buttons that increment and decrement what portion of the list you're viewing.

Then you can simplify, fill your giant string arrays in post init (like the listener callback on the first tick) and then your "browser" will dynamically look at them to see what should be displayed to the user.


----------



## andreasOL (Mar 22, 2016)

Hi

IIRC one means of avoiding that Kontakt message is to wrap an arbitrary number of lines with something like this

if (1=1)
...
end if

You can even put this around declare statements which looks strange but works.

Of course, making the icb smaller is the preferable solution.

best,
Andreas


----------



## EvilDragon (Mar 22, 2016)

I would use ONE menu and an array that stores articulation selected for each key, along with a knob/slider for note selection. Have a "MIDI Select" button that listens to the last key pressed, which will read the current value from the articulation array, show it up in the menu, then any changes done in that menu will get stored to the array immediately.


```
on init
    declare ui_button MIDISelect
    declare ui_knob Note (0,127,1)
    declare ui_menu Articulation
    add_menu_item(Articulation,"- UNASSIGNED -",-1)
    { all the add_menu_item() lines here }
    declare art_list[128] := (-1)

    Note := 36

    make_persistent(Note)
    make_persistent(art_list)

    read_persistent_var(Note )
    read_persistent_var(art_list)

    Articulation := art_list[Note]

    message("")
end on

on note
    if MIDISelect = 1
        Note := EVENT_NOTE
        Articulation := art_list[Note]
    end if
end on

on ui_control (Articulation)
    art_list[Note] := Articulation
end on

on ui_control (Note)
    Articulation := art_list[Note]
end on
```


Simple enough, no? And no need for _if (1=1) _thing.


----------



## Lindon (Mar 22, 2016)

What Mario said, but I used a MIDI Learn button instead of the of a second drop-down/knob, slightly nicer(maybe).


----------



## EvilDragon (Mar 22, 2016)

That's exactly what MIDISelect button does here. Knob is there for manual editing, it enables you to map notes outside of 88 key range if need be.


----------



## Mike Greene (Mar 22, 2016)

This is all great stuff. Thank you very much, guys.

I think I'm going to do something similar to what Mario described, although since I already did the artwork for the keyboard, I'm going to still include the option of clicking the notes on that keyboard. (It used to be a separate menu for each key, but now I'll make it buttons on each key.) Probably overly redundant, but that artwork took me a long time, so I'm keepin' it no matter what!


----------



## Aviram Dayan Production (Jun 23, 2018)

also in this days and in the last version of KONTAKT 5.8,
you got the eror message "parser stack overflow",
in "on init" the maximum lines is 5324 and not 5000,
and that pretty much limits the all work,
this limitation should be expanded...


----------



## EvilDragon (Jun 24, 2018)

You can work around that by placing blocks of code around if (1=1) statement.


----------



## Aviram Dayan Production (Jun 24, 2018)

EvilDragon said:


> You can work around that by placing blocks of code around if (1=1) statement.



i know the general method of areas, to decrease the lines,
and insert the all statements into big area (like your example above)

but this one method
if (1=1)
...
end if
unclear to me

I'd love to little example, from this method
tnx


----------



## Mike Greene (Jun 24, 2018)

Lets suppose this is your current code in the init callback:

```
on it
   stuff
   more stuff
   more stuff
   more stuff
   more stuff
   more stuff
   more stuff
   more stuff
end on
```
That would be 10 lines. But if you change it to this:

```
on it
   stuff
   if (1 = 1)
      more stuff
      more stuff
      more stuff
      more stuff
      more stuff
      more stuff
      more stuff
   end if
end on
```
Then the parser only considers that to be 5 lines, because of a quirk that the parser doesn't seem to count lines that are inside "if" conditionals.


----------



## Aviram Dayan Production (Jun 24, 2018)

Mike Greene said:


> Lets suppose this is your current code in the init callback:
> 
> ```
> on it
> ...



so this method cut 50%?
it mean 1 equal to "true" (very very weird..) 
i tried it before I asked, and there is no success
i'll keep trying
tnx mike

edit:
it works, But in general should divide the if (1 = 1)
several times inside "on init" (Not enough once)
from 4000 lines I guess, Do another if (1 = 1)

It's very strange what's happening here
But somehow it works.


----------



## Tod (Jun 24, 2018)

Mike Greene said:


> Lets suppose this is your current code in the init callback:
> 
> ```
> on it
> ...



Wow Thanks Mike & Mario, I didn't know this. 

I don't think I've come anywhere close to 5000 lines in the init CB, but I do have a project coming up that has possibilities.


----------



## Levitanus (Jun 24, 2018)

Aviram Dayan Production said:


> it works, But in general should divide the if (1 = 1)
> several times inside "on init" (Not enough once)
> from 4000 lines I guess, Do another if (1 = 1)


or You can use this little sublime text plugin
https://bitbucket.org/Levitanus/stackoverflowplugin/src/master/
it's a little bit old, the new one was included in closed package, and it pasted if(1=1) to every callback, so, generally, i passed in tests above 2 000 000 lines into kontakt 
This works only on init


----------



## Aviram Dayan Production (Jun 24, 2018)

Levitanus said:


> or You can use this little sublime text plugin
> https://bitbucket.org/Levitanus/stackoverflowplugin/src/master/
> it's a little bit old, the new one was included in closed package, and it pasted if(1=1) to every callback, so, generally, i passed in tests above 2 000 000 lines into kontakt
> This works only on init



cool stuff i'll use that, at the end of the project
(my all total main script, will be close to 60,000 lines i believe)
tnx


----------



## Levitanus (Jun 24, 2018)

generally, I compiled script to the file, and then pressed ctrl+f5 while it's opened. and save, of course


----------



## Aviram Dayan Production (Jun 24, 2018)

Levitanus said:


> generally, I compiled script to the file, and then pressed ctrl+f5 while it's opened. and save, of course



yes,only at the end i prefer,
I like to keep my order with text help {Help}
To remember what I did, Believe me if I come to my big script after 4 months that I have not written KSP,
I tell to myself, Who the hell wrote it, was it me? (You get BlackOut)
I believe it happens to everyone


----------



## EvilDragon (Jun 25, 2018)

I wonder what the hell are you doing to have 4000-5000 lines of init callback. Sounds like a lot of inefficient UI initialization code


----------

