What's new

How to skin menus [SOLVED]

It is always a better idea to use picture state changing as much as possible rather than on the fly swapping the image. Just FYI. :)
 
It is always a better idea to use picture state changing as much as possible rather than on the fly swapping the image. Just FYI. :)

Was that in response to the example? It's using picture state...
There's just an optional situation where the user could swap the menu's image (not the label) on the fly to accomodate a more graphically pleasing result. That's it... ;)

(Imagine if i had posted an animated menu... :D)
 
There's just an optional situation where the user could swap the menu's image (not the label) on the fly to accomodate a more graphically pleasing result. That's it... ;)

Yes, that's what I was referring to. You can still do the same thing with picture state and a label.
 
Yes, that's what I was referring to. You can still do the same thing with picture state and a label.

It's not the same thing, ED. The second scenario with the on-the-fly dynamic images means that the mouse over functionality for the menu remains coherent with the selected entry images.
It's really just the icing on the cake, nothing else.

Please try the example as it shows this in action.

In this case, the label could be completely ignored/removed (though it could still be kept in case of an animated menu...)

I'm just trying to show options to make the GUI prettier/more flexible. :)
 
Ok guys, thanks a lot !

I've got a lot to do today, and assimilating the lessons from P.N.'s example will probably take me part of the afternoon, but I'll get back here ASAP with feedback (and possibly more questions ;) )]
 
Last edited:
Ok I'm back.

@P.N.: First of all, your example was very clear. Thank you.

Here's what I understand from it (which I believe is about everything). Please correct me if I'm wrong :

- The picture state is the frame index in an animation strip. For example, if a picture file has its Number of Animations set to 6, then there are 6 picture states, numbered from 0 to 5.

- The graphic for a menu must always have 6 states, of which only states 0, 2 and 4 (that is the 1st, 3rd and 5th ones) are used, for mouse over and mouse down effects, as EvilDragon explained earlier.

The reason for this is that menus use the same state scheme as buttons, but only off states are used, because menus aren't binary on/off controls.

- Since the 'animatability' of the menu's graphic is already taken by mouse effects, an underlying label must contain the actual menu's graphics, of which each state corresponds to each possible menu item.

I still don't get why this is better than swapping whole picture files, but I find it actually convenient, so ok.

- The menu doesn't need to be hidden in order to reveal the underlying label. It only needs a mostly transparent picture, and its text content moved away via an intentionally excessive pixel offset.

That was a very educative example, aimed right at my expertise level ;)

Just one remark, in case you didn't realize : I had to update from Kontakt 5.2 to 6.0 in order to open your example. The only reason I can see for that is your use of the persistence_changed callback. Anyway, I'm glad I updated.
 
Last edited:
I don't get why this is better than swapping whole picture files, but I find it actually convenient, so ok.

Imagine you have 30 entries - you'd need 30 different images for the menu instead of 1 single pixel strip with image states.

The reason i included the "dynamic mouse over" version was just to show you the 2 different methods.
If the image swapping method makes sense for you, or improves your presentation, that's up to you.

The reason for not doing it would be efficiency and resources management - but please don't take my word on this as i never ran tests that could show a palpable decrease in performance.

Again, if you are happy with the menu's fixed mouse over interactivity (or if you don't even need graphics for that), stick with the label and picture state approach as that's the fastest/easiest way.

Just one thing (though this is probably just a detail) : what is the persistence_changed callback ? I couldn't find it in KSP5's reference. Is it KSP6 ? (I had to update my Kontakt version in order to run your example)

It's in the K5 reference manual, yes. It could be summarized as... an extension of the init portion of the script, or even a "kind of special function" that is automatically called upon after "on init".
 
It's in the K5 reference manual, yes. It could be summarized as... an extension of the init portion of the script, or even a "kind of special function" that is automatically called upon after "on init".

Seems like they introduced it in version 5.7, or sometime between 5.2 and 5.7 anyway. However, in your exemple, I believe it would make the menu_update function be executed twice each time once is needed. Not a big deal in this case, of course.
 
Just one remark, in case you didn't realize : I had to update from Kontakt 5.2 to 6.0 in order to open your example. The only reason I can see for that is your use of the persistence_changed callback. Anyway, I'm glad I updated.

Oh, that. Sorry about that. It was not related to the persistence callback.
I made the nki in 5.7.0. which is the oldest version i use for examples.

You needed the update! :D
 
The nki wouldn't work because it was a more recent version, but did you try the code directly in 5.2? I'm almost sure persistence changed arrived with the first release of K5...
 
I just copypasted your script in Kontakt 5.2, and there are two things it can't parse : command set_ui_color and callback persistence_changed. After confronting different versions of the reference manual, it seems they were both added in 5.7. Or some time in between.

set_ui_color is a fine addition btw (could become that new command I can't live without :P ).
 
Last edited:
I could swear persistence changed came with vanilla k5...
But i only started scripting in 5.5 or something...
Thank you for the information. :)

You should check out other useful commands and controls that were added.
XY pad, increased width, etc. Too much stuff to remember... :)
 
You should check out other useful commands and controls that were added.
XY pad, increased width, etc. Too much stuff to remember... :)

Sounds appealing !

But do you know which portion of the user base still uses older versions ? I arbitrarily chose version 5.2 because that's the one I have... but are still many people using versions 3 or 4, for example ? Or is everybody at least on version 5.7 ? I should aim at the best possible compromise between language maturity (if we can ever call it that !) and customer base.

And I really don't know the versographics (that's my portmanteau of version and demographics) of Kontakt because I actually never use it to make music (not nerdy enough for me - I am more of a Renoise guy), I just use it to make commercial libraries, of which I hope to release the first soon.
 
Last edited:
I'm almost sure persistence changed arrived with the first release of K5...

persistence_changed was added along with snapshots in Kontakt 5.4.

But do you know which portion of the user base still uses older versions ?

Here's a related thread: https://vi-control.net/community/th...t-version-of-kontakt-you-primarily-use.77799/

Looks like at least in this sample of users, most are on latest versions. You don't have to worry about going too far back. Certainly not to K5.2 (or did you mean K5.5.2?).
 
I read they added the $CONTROL_PAR_TEXTPOS_Y for value_edits, which is very welcome, so.. who knows?

Since we're overflowing with graphical and technical discussion, I wonder about the practical utility of this function of shifting the whole text on the Value edit ..?
 
In K5, if you don't use the default font, your text won't align properly with the arrows, for example.
Since value edit doesn't support textpos in K5, you're stuck with this offset...
 
Looks like at least in this sample of users, most are on latest versions. You don't have to worry about going too far back. Certainly not to K5.2 (or did you mean K5.5.2?).

No, I really meant 5.2 ;) - I did't realize I was being so backwards !

Maybe I could aim at 5.7, which seems to be some kind of milestone (I'm not sure but I think it's the oldest updatable one to 6.0). Or maybe 5.8, which seems to be almost everybody's version.
 
Last edited:
Ok guys... As you know I implemented P.N.'s example (which was the solution everybody was trying to explain to me) with success.

Then I wanted to devise a way of customizing the drop-down part of the menu as well. It took me a while, and the code is much, much longer :

Code:
on init
  declare $mn_unison := 0
  declare ui_button $mbt_unison
  declare ui_button $mbt_unison_analog
  declare ui_button $mbt_unison_digital
  declare ui_button $mbt_unison_hybrid
  declare ui_label  $mlb_unison (1,1)
  set_control_par_str (get_ui_id ($mbt_unison), $CONTROL_PAR_PICTURE, "mn-unison--")
  set_control_par_str (get_ui_id ($mlb_unison), $CONTROL_PAR_PICTURE, "mn-unison")
  set_control_par_str (get_ui_id ($mbt_unison), $CONTROL_PAR_TEXT, "")
  set_control_par_str (get_ui_id ($mlb_unison), $CONTROL_PAR_TEXT, "")
  set_control_par (get_ui_id ($mbt_unison), $CONTROL_PAR_POS_X, 388)
  set_control_par (get_ui_id ($mbt_unison), $CONTROL_PAR_POS_Y, 72)
  set_control_par (get_ui_id ($mlb_unison), $CONTROL_PAR_POS_X, 393)
  set_control_par (get_ui_id ($mlb_unison), $CONTROL_PAR_POS_Y, 75)
  set_control_par (get_ui_id ($mbt_unison), $CONTROL_PAR_WIDTH,  99)
  set_control_par (get_ui_id ($mbt_unison), $CONTROL_PAR_HEIGHT, 14)
  set_control_par (get_ui_id ($mlb_unison), $CONTROL_PAR_WIDTH,  91)
  set_control_par (get_ui_id ($mlb_unison), $CONTROL_PAR_HEIGHT, 12)
  set_control_par_str (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_PICTURE, "mn-unison--analog")
  set_control_par_str (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_PICTURE, "mn-unison--digital")
  set_control_par_str (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_PICTURE, "mn-unison--hybrid")
  set_control_par_str (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_TEXT, "")
  set_control_par_str (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_TEXT, "")
  set_control_par_str (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_TEXT, "")
  set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_POS_X, 388)
  set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_POS_X, 388)
  set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_POS_X, 388)
  set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_POS_Y,  74)
  set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_POS_Y,  86)
  set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_POS_Y,  98)
  set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_WIDTH,  99)
  set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_HEIGHT, 16)
  set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_WIDTH,  99)
  set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_HEIGHT, 16)
  set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_WIDTH,  99)
  set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_HEIGHT, 16)
  set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
  set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
  set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
end on

function mn_unison
  if ($mbt_unison = 1)
    set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_HIDE, $HIDE_PART_NOTHING)
    set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_HIDE, $HIDE_PART_NOTHING)
    set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_HIDE, $HIDE_PART_NOTHING)
  else
    set_control_par (get_ui_id ($mlb_unison), $CONTROL_PAR_PICTURE_STATE, $mn_unison)
    set_control_par (get_ui_id ($mbt_unison_analog),  $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
    set_control_par (get_ui_id ($mbt_unison_digital), $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
    set_control_par (get_ui_id ($mbt_unison_hybrid),  $CONTROL_PAR_HIDE, $HIDE_WHOLE_CONTROL)
  end if
  $mbt_unison_analog := 0
  $mbt_unison_digital := 0
  $mbt_unison_hybrid := 0
  select ($mn_unison)
   case 0
    $mbt_unison_analog := 1
   case 1
    $mbt_unison_digital := 1
   case 2
    $mbt_unison_hybrid := 1
  end select
end function
on ui_control ($mbt_unison)
  call mn_unison
end on
on ui_control ($mbt_unison_analog)
  $mn_unison := 0
  $mbt_unison := 0
  call mn_unison
end on
on ui_control ($mbt_unison_digital)
  $mn_unison := 1
  $mbt_unison := 0
  call mn_unison
end on
on ui_control ($mbt_unison_hybrid)
  $mn_unison := 2
  $mbt_unison := 0
  call mn_unison
end on

It displays a menu I call "unison", containing 3 items: "analog", "digital" and "hybrid", by simulating a menu's behaviour using only labels and buttons.

The result looks gorgeous of course. But you can basically multiply the code's length by the number of items... And the example here is for only 3 items !

So now the question is: does it add too much complexity to my script ? I mean I haven't started the serious coding yet, and when I do, I hope my code won't get so convoluted that I get lost in it.
So I have a choice to make... But I'm glad I tried anyway.

Thanks everybody for getting me going !
I needed this conversation in order to know the strenghts and limitations of KSP in regard to what I'm trying to do, and also to teach me the few concepts I was missing (like picture states etc.)

NOTE TO PEOPLE COMING TO THIS THREAD BECAUSE OF THE [SOLVED] TAG : Go read P.N.'s solution a few posts earlier, it's much simpler than this one - and probably the proper way to do it.
 
Last edited:
Top Bottom