1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Is there a more efficient way to make ui_menus?

Discussion in 'KONTAKT: Sampling, Programming & Scripting' started by Mike Greene, Mar 21, 2016.

  1. Mike Greene

    Mike Greene Administrator

    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:
    Code:
    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?
     
  2. OP
    OP
    Mike Greene

    Mike Greene Administrator

    I did more digging in the manual and realize I forgot about this method:
    Code:
       $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.
     
  3. gregjazz

    gregjazz Senior Member

    1,266
    382
    Jul 10, 2005
    California
    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.
     
  4. neblix

    neblix Music, Math, Cats

    217
    193
    Jul 22, 2010
    Philadelphia, PA
    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.
     
  5. andreasOL

    andreasOL Senior Member

    258
    19
    Jan 9, 2010
    Hesel
    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
     
  6. EvilDragon

    EvilDragon KSP Wizard

    4,655
    2,524
    May 25, 2010
    Croatia
    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.

    Code:
    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.
     
    Last edited: Mar 22, 2016
    Levitanus likes this.
  7. Lindon

    Lindon KSP Developer

    567
    173
    Jul 27, 2010
    Republic of Yorkshire
    What Mario said, but I used a MIDI Learn button instead of the of a second drop-down/knob, slightly nicer(maybe).
     
  8. EvilDragon

    EvilDragon KSP Wizard

    4,655
    2,524
    May 25, 2010
    Croatia
    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.
     
  9. OP
    OP
    Mike Greene

    Mike Greene Administrator

    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! :grin:
     
  10. 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...
     
    Last edited: Jun 23, 2018
  11. EvilDragon

    EvilDragon KSP Wizard

    4,655
    2,524
    May 25, 2010
    Croatia
    You can work around that by placing blocks of code around if (1=1) statement.
     
  12. 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
     
    Last edited: Jun 24, 2018
  13. OP
    OP
    Mike Greene

    Mike Greene Administrator

    Lets suppose this is your current code in the init callback:
    Code:
    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:
    Code:
    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.
     
  14. so this method cut 50%?
    it mean 1 equal to "true" (very very weird..) o_O
    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.
     
    Last edited: Jun 24, 2018
  15. Tod

    Tod Old Fart

    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.
     
  16. Levitanus

    Levitanus Senior Member

    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
     
  17. 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 :thumbsup:
     
    Levitanus likes this.
  18. Levitanus

    Levitanus Senior Member

    generally, I compiled script to the file, and then pressed ctrl+f5 while it's opened. and save, of course
     
  19. 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 :)
     
  20. EvilDragon

    EvilDragon KSP Wizard

    4,655
    2,524
    May 25, 2010
    Croatia
    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 :)
     

Share This Page