# K4 Questions, Discoveries, etc



## kotori (Feb 24, 2011)

Big Bob @ Wed Feb 23 said:


> The same goes for all kinds of note/release functions such as change_note, change_vol, etc. IMHO this is most unfortunate and greatly reduces the value of user functions.


Generally speaking this is indeed unfortunate. However, these particular built-in functions that you mentioned here can actually be used inside functions. I think the general rule is: if, with the exception of the init callback, the built-in function can be used in any type of callback then it can be used within a "call"ed function. You can also use polyphonic variables inside such function definitions.

Cheers,
Nils


----------



## kotori (Feb 24, 2011)

Hmm... it seems change_vol can be used inside a function, but change_note cannot. I can't see any good reason for that. Can't remember if change_note changes the values of EVENT_NOTE. Maybe that could be something that makes it special. Or maybe it's just a mistake by NI. I would guess the latter.


----------



## Big Bob (Feb 24, 2011)

Hi Nils,

Now I'm really confused :? 



> Consider my rule of thumb above. The allow_group/disallow_group functions are not allowed inside the controller callback. Hence they cannot be used inside a function.



I can understand that functions containing allow_group can't be executed in a controller callback but that's not what I was trying to do. My confusion seems to be related to how or where functions are declared. I realize that KScript re-orders things but I'm refering to where does the function declaration need to be for the K4 compiler's sake (ie after KScript has finished with it)?

Let me put it this way. If I don't use the KScript Editor, how can I define a user function containing say *change_note *such that I can 'call' that function in the NCB and K4.2 will be happy with it? So far, I have not found a way to do this because as soon as I include change_note in a function declaration, K4.2 balks at it.

If what you say is true, and I'm sure it is, then I must be missing something very obvious.

Bob


----------



## Big Bob (Feb 24, 2011)

Hi Nils,

I guess some of our posts are crisscrossing. I now see that you are saying that change_note cannot be used in a function declaration.

Could it be that I did something so stupid like checking only change_note and assuming that it applied to others as well? If so, shame on me. Let me retry the other built-ins again also and I'll bounce back.

Bob


----------



## Big Bob (Feb 24, 2011)

Hi Nils,

My Bad :oops: I retried change_vol() in a function and K4 seems happy with it.

I can't believe I did somethiing so dumb as to extrapolate the change_vol behavior without actually checking it out but apparently I did :shock: 

Have you actually tried all the built-ins or did you perhaps extrapolate a few yourself(since you seem to have missed the change_note problem)? If we don't know for sure, maybe I should take the time to check all the built-ins and compile a list of what is and isn't allowed in a function? Then we can perhaps tighten your 'rule of thumb' :lol: 

In any case, I guess the essence of what I posted may still have some merit (at least for allow_group and change_note) so having a list of equivalent set_event_par constructs that are allowed in functions might be of some value?

Rejoice,

Bob


----------



## Big Bob (Feb 24, 2011)

Hi Nils,

I finally got the time to recheck the whole series of change event functions, namely:
change_note, change_pan, change_tune, change_velo, and change_vol.

I'm pleased to report that only change_note cannot be used in a function. At first I thought that maybe your rule of thumb could still hold up but change_velo breaks it. I don't think that change_velo can be used in a CCB (and probably not in UICBs either) but K4.2 allows it in a user function.

One might think that it has to do with whether the function affects the note from the get go or not. You can't change the note or its velocity after it starts to sound (and neither can you change the group containing its sample). Therefore, it make some sense that you can't use those functions other than in the NCB. And, one can alter the volume, panning, and tuning after the note is started so those functions should be useable in other callbacks.

But then, if the rule is to not allow such built-ins in user functions either, why is change_velo allowed? Maybe NI didn't intend it to be allowed but it just slipped under the radar?

I haven't checked for other built-in functions that might not be allowed in user functions, but at least change_note and disallow_group/allow_group aren't. Therefore, the following equivalent constructs might still be handy to know since they perform the same function and they can be embedded in user functions.

*function* set_group
``_{ This code is equivalent to: disallow_group(ALL_GROUPS), allow_group(n)
and it can be included in user functions }_
``set_event_par_arr(id,EVENT_PAR_ALLOW_GROUP,0,ALL_GROUPS)
``set_event_par_arr(id,EVENT_PAR_ALLOW_GROUP,1,n)```
*end function*

*function* set_note
``_{ This code is equivalent to: change_note(id,note)
and it can be included in user functions }_
``set_event_par(id,EVENT_PAR_NOTE*,note*)
*end function*

Rejoice,

Bob


----------



## kotori (Feb 24, 2011)

Oh, I had completely missed the $EVENT_PAR_ALLOW_GROUP constant :shock: 
Thanks so much for bringing this to my attention Bob.  
I have only on very rare occasions needed to use the change_note function, so now I don't have any problem with built-in functions inside functions anymore.

Btw. did you forget to write a parameter list for your functions?


----------



## Big Bob (Feb 25, 2011)

Hi Nils,



> Oh, I had completely missed the $EVENT_PAR_ALLOW_GROUP constant
> Thanks so much for bringing this to my attention Bob.



When you first told me that we couldn't use the normal group control built-ins in user functions, I was really bummed out about it. Then, the next thing I tried was change_note and it wasn't allowed either so I jumped to the conclusion that none of the functions in that class would be useable in user functions.

But then I really perked up when I found these alternate constructs would work, *especially the group control stuff*. Maybe I should have highlighted that a little more in my post but remember I'm new at this :lol: 

And speaking of being a newby, I'm a bit puzzled by this question :roll: 



> Btw. did you forget to write a parameter list for your functions?



I guess I must really be slipping, but, could you clarify this question? What are 'my functions' that I should have written a parameter list for?? :? 

Rejoice,

Bob


----------



## kotori (Feb 25, 2011)

Big Bob @ Fri Feb 25 said:


> > Btw. did you forget to write a parameter list for your functions?
> 
> 
> I guess I must really be slipping, but, could you clarify this question? What are 'my functions' that I should have written a parameter list for?? :?



Oh, it's less mysterious than you think - I just wondered why you didn't add any parameters to the set_group and set_note functions above. I would do it like this:

*function* set_group(id, group)
``_{ This code is equivalent to: disallow_group(ALL_GROUPS), allow_group(n) and it can be included in user functions }_
``set_event_par_arr(id,EVENT_PAR_ALLOW_GROUP,0,ALL_GROUPS)
``set_event_par_arr(id,EVENT_PAR_ALLOW_GROUP,1,group)```
*end function*

*function* set_note(id, note)
``_{ This code is equivalent to: change_note(id,note) and it can be included in user functions }_
``set_event_par(id,EVENT_PAR_NOTE,note)
*end function*


----------



## Big Bob (Feb 25, 2011)

Oh now I see what you meant :idea: 

The reason is that I didn't really intend them to be functions in and of themselves. I was assuming that these constructs would be embedded in other code and then put in the body of a ksp user function. So I just showed them by themselves as a ksp function (not a KScript function) just to illustrate that these constructs can be used inside of a ksp user function.

However, I guess there would be no harm in writing them as mini KScript user functions which could of course then be invoked inside of a ksp function declaration. That certainly will make things more modular and readable and probably is the way I should have illustrated it.

I'm still bumbling around but one of these days I'll get the hang of it again :lol: 

You have a lovely day my friend,

Bob


----------



## Big Bob (Mar 1, 2011)

OK, I think I've got almost all the new K4 stuff tucked away in the little grey cells except for all the fun and games with the new UI stuff.

I've read the K4 Player's Guide and several little tutorials by Blake. I've also read a lot of the UI stuff posted on this forum over the last 6 months. So, I'm finally ready to jump in and get my feet wet but, it didn't take too long before I hit my first puzzlement :lol: 

Could one of you UI gurus illustrate by example what to add to a script to get a ui_slider to display its value. For example, the NI sliders seem to display the value in a cartoon baloon over the control but I'm sure there are other ways to display the value. 

Do I need to create a label or is there some way to utilize $CONTROL_PAR_LABEL for instance. I have tried using $CONTROL_PAR_LABEL but nothing ever seems to get displayed (BTW I tried it both with set_control_par and set_control_par_str). Perhaps $CONTROL_PAR_LABEL only works with knobs? 

As usual, I'm just kind of bumbling around for now trying this and that so any kind of helpful input you guys can provide for a UI newby would be appreciated.

Thanks,

Bob


----------



## chimuelo (Mar 1, 2011)

I really appreciate you guys sharing your discoveries and ideas in threads here.
I know nothing of this nor have the time to really dig into the scripts, but everytime I have a month off you have given me plenty to read about.
I would really love some Kontakt 4 scripting videos, until then we have you guys.

Thanks So Much..


----------



## EvilDragon (Mar 1, 2011)

$CONTROL_PAR_LABEL is only applicable on ui_knobs, and you use it with set_control_par_str  (For all parameters which expect a text string, you use _str variant of set_control_par!)

You'd use something like this (rudimentary example with a little extra - move the slider while Alt key is pressed, and Tune will be changed in semitones!):


```
on init
	make_perfview

	declare ui_slider $Tune (0,1000000)
	declare ui_label $text(1,1)

	declare $last_time
	declare %values[73] := (0, 13820, 27709, 41598, 55487, 69376, 83264, 97153, 111042, 124931, 138820, 152709, 166598, 180487, 194376, 208264, 222153, 236042, 249931, 263820, 277709, 291598, 305487, 319375, 333264, 347153, 361042, 374931, 388820, 402709, 416598, 430487, 444375, 458264, 472153, 486042, 500000, 513820, 527709, 541598, 555487, 569376, 583264, 597153, 611042, 624931, 638820, 652709, 666598, 680487, 694376, 708264, 722153, 736042, 749931, 763820, 777709, 791598, 805487, 819376, 833264, 847153, 861042, 874931, 888820, 902709, 916598, 930487, 944376, 958264, 972153, 986042, 999931)

	set_control_par(get_ui_id($Tune),$CONTROL_PAR_DEFAULT_VALUE,500000)
	set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_PART_BG)
	set_control_par(get_ui_id($text),$CONTROL_PAR_TEXT_ALIGNMENT,1)
	set_control_par(get_ui_id($text),$CONTROL_PAR_FONT_TYPE,22)

	move_control($text,1,1)
	move_control($Tune,1,2)

	set_text($text,"Tune")

	$Tune := get_engine_par($ENGINE_PAR_TUNE,-1,-1,-1)

	message("")
end on

on ui_control($Tune)
	if (get_control_par(get_ui_id($Tune),$CONTROL_PAR_KEY_ALT) = 1)
		set_engine_par($ENGINE_PAR_TUNE,%values[$Tune/13888],-1,-1,-1)
	else
	    set_engine_par($ENGINE_PAR_TUNE,$Tune,-1,-1,-1)
	end if
	set_text($text,get_engine_par_disp($ENGINE_PAR_TUNE,-1,-1,-1) & " semi")

	$last_time := $ENGINE_UPTIME
	wait(1000000)
	if($ENGINE_UPTIME - $last_time > 990)
		set_text ($text,"Tune")
	end if
end on
```

The caveat here is the $last_time variable - if you have several controls, it is shared between them, which means that if you start twiddling another knob while the first one is already displaying the value on the label, the value will stick and the parameter title won't be restored until you click the first knob again. (By "knob" I mean ui_slider, which can be made to look as a knob, along with $CONTROL_PAR_MOUSE_BEHAVIOUR set to negative value it will even behave like a knob).

The solution is changing $last_time to %last_time[$NUM_CONTROLS], naturally - $NUM_CONTROLS being user-defined constant, set to the total number of controls that need this kind of visual feedback.


----------



## Big Bob (Mar 1, 2011)

Hi Mario,

Thanks for the sample script. I gather from your statements and the script example itself that some of the things I hypothesized were true then. 

1. $CONTROL_PAR_LABEL (in conjunction with set_control_par_str of course) only works with knobs (sort of the counterpart of set_knob_label).

2. To display a slider's value (or for that matter to give it a name that can be seen), we *do* need to create some sort of label (in addition to the slider itself).

3. Do I presume correctly then that to display a slider's value in a manner similar to NI, one would have to create a custom-skinned label (with a pix of the caption baloon) and dynamically move it with the slider (using move_control_px I guess)?

Finally, regarding your scripting to revert the label back to displaying "Tune" when the slider becomes static, wouldn't the wait(1000000) alone be sufficient? I'm kind of puzzled why you would want to embed the one second wait *inside* of a 'watchdog timer' set to 990ms. 

Normally, unless the wait() timing or the engine uptime goes haywire, won't the *if($ENGINE_UPTIME - $last_time > 990) * conditional always be true? In fact, if it isn't true after the last movement made, won't the value be displayed until the next time the user touches the slider again? I'm probably missing something here but what was your rationale for using a watchdog?

BTW I realize you have probably gone off to bed by now, so pleasant dreams and I'll see you tomorrow.

Rejoice,

Bob


----------



## EvilDragon (Mar 1, 2011)

The idea is to go back to the "Tune" text exactly one second after releasing the slider. If the user moves the knob in that one second time, the old wait would've been carried out and things wouldn't work correctly. By adding the timer, it functions exactly like I wanted it to.

#2 - alternatively the parameter name can be done graphically by using a PNG image for instrument background. In this case, it's a good idea to have one shared ui_label for ALL parameters, thus only showing the currently tweaked parameter value.

#3 - nope, you don't need to create a custom skinned label, you can do it just like I did it here (well, that's basically how NI did it too, psssst :lol - using an ui_label with hidden background, centered text, and appropriate font out of 25 fonts which NI offers. There's no need to dynamically move the label - that's why I used $CONTROL_PAR_TEXT_ALIGNMENT set to 1, it centers the text 

Oh, while I'm at it, when you're using centered text with ui_buttons and ui_menus, make sure you add an additional space at the end of the text string, otherwise it won't center well (strange, I know!)


----------



## Big Bob (Mar 1, 2011)

My Goodness, you're still up? :shock: 

I don't know about you, but I'm going to quit for the day so I'll respond to your latest post in the morning when I can think clearly :lol: 

But, next time you get a chance, take a look at one of NI's Intensity sliders because I must be smoking something I shouldn't :? 

See you in the morning, whenever that is for you :roll: 

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

Haha. :lol: I usually go to bed around 4 am. Yesterday, that is, today, was a bit different, I didn't _want_ to go to sleep yet. It's all fine, I'm a night person. :lol:

What about the NI intensity sliders, care to elaborate?  Do you perhaps think of Pitch bend up and down knobs on Options pages of instruments in Kontakt factory library?

If so, yes, that was most unnecessarily convoluted way to do that.


----------



## kotori (Mar 2, 2011)

Big Bob @ Wed Mar 02 said:


> 1. $CONTROL_PAR_LABEL (in conjunction with set_control_par_str of course) only works with knobs (sort of the counterpart of set_knob_label).


It depends on what one means by "works". There is no native support for showing the value of a slider. However, in many cases it's still good to use $CONTROL_PAR_LABEL since that's the value shown within the host in case the user chooses to automate the slider.

Cheers,
Nils


----------



## Big Bob (Mar 2, 2011)

> It depends on what one means by "works". There is no native support for showing the value of a slider. However, in many cases it's still good to use $CONTROL_PAR_LABEL since that's the value shown within the host in case the user chooses to automate the slider.



Thanks for pointing that out Nils. Since I always run standalone, I doubt if I would ever have tumbled to that.

Good Morning Mario,



> #3 - nope, you don't need to create a custom skinned label, you can do it just like I did it here (well, that's basically how NI did it too, psssst ) - using an ui_label with hidden background, centered text, and appropriate font out of 25 fonts which NI offers. There's no need to dynamically move the label - that's why I used $CONTROL_PAR_TEXT_ALIGNMENT set to 1, it centers the text



I'm not talking about centering the text in the label but rather centering the label over the slider knob/handle (or whatever you call the thing you drag). For example, the modulation intensity sliders that NI uses display the setting with 'moving caption baloon'. That always remains approximately centered over the 'handle'.

Your illustrative code simply displays the value in the center of a fixed label. So, what I was saying is that if we want to mimic the behaviour of the NI slider, wouldn't we have to dynamically position the label?



> The idea is to go back to the "Tune" text exactly one second after releasing the slider. If the user moves the knob in that one second time, the old wait would've been carried out and things wouldn't work correctly. By adding the timer, it functions exactly like I wanted it to.



I think I see what you were concerned about. I guess you are thinking that because the ui callback will be re-entered multiple times as the slider is moved, that the last value displayed (before reverting to the "Tune" display) may not really be the final setting since some prior thread may time out while the last value is being displayed and it may not show long enough to be seen.

While I guess that could happen, as a practical matter, I think it is very unlikely. I tried your code with and without the 'watchdog' and I couldn't produce a situation in which the last value displayed in the label differed from NI's final tune display.

I also remember that with K2/K3, the 'rep rate' of most callbacks was throttled to somewhere around 100/sec. ie the shortest interval between callbacks, regardless of how rapidly the data is changing, was on the order of 10 msec. But, since K4 may behave differently, I added some test code to examine the situation. Here is the test script I used (it's basically your script with the watchdog commented out and some data gathering code. The %time array collects successive ksp_timer values when you move the slider. Then, depressing the Show button will display the time interval between each pass through the tune callback (in msec).

*on init* 
```make_perfview 

```*declare* *const* $num := 40

```*declare* %time[$num] := (0)
```*declare* $bin
```*declare* ui_button $show
```*declare* @str

```*declare* ui_slider $Tune (0,1000000) 
```*declare* ui_label $text(1,1) 

```*declare* $last_time 

```set_control_par(get_ui_id($Tune),$CONTROL_PAR_DEFAULT_VALUE,500000) 
```set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_PART_BG) 
```set_control_par(get_ui_id($text),$CONTROL_PAR_TEXT_ALIGNMENT,1) 
```set_control_par(get_ui_id($text),$CONTROL_PAR_FONT_TYPE,22) 

```move_control($text,1,1) 
```move_control($Tune,1,2) 

```set_text($text,"Tune") 

```$Tune := get_engine_par($ENGINE_PAR_TUNE,-1,-1,1) 

```message("") 
*end on* 

*on ui_control*($Tune) 
```set_engine_par($ENGINE_PAR_TUNE,$Tune,-1,-1,-1) 
```set_text($text,get_engine_par_disp($ENGINE_PAR_TUNE,-1,-1,1) & " semi") 
```*if* ($bin < $num)
`````%time[$bin] := $KSP_TIMER
```*end if*
```inc($bin)
```
```$last_time := $ENGINE_UPTIME 
```wait(1000000) 
```set_text($text,"Tune") 

_{ if($ENGINE_UPTIME - $last_time > 990) 
set_text ($text,"Tune") 
end if }_
*end on*

*on ui_control*($show)
``$show := 0
``$bin := 2
``@str := (%time[1] - %time[0] + 500)/1000
``*while* ($bin < $num *and* %time[$bin] # 0) 
````@str := @str & ", " & (%time[$bin] - %time[$bin-1] + 500)/1000
````inc($bin)
``*end while*
``$bin := 0
``*while* ($bin < $num)
````%time[$bin] := 0
````inc($bin)
``*end while*
``$bin := 0
``message (@str)
*end on*




I notice that the typical minimum interval is around 12 msec on my computer but I do occasionally see a zero. If that's real, it means that once in a while the interval is shorter than 1 msec.

My conclusion is that it won't hurt to use your 'watchdog' and it may, on very rare occassions, prevent an incorrect 'final' displayed value. However, I think we are sort of 'guilding the lily' :lol: 

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

Big Bob @ 2.3.2011 said:


> I'm not talking about centering the text in the label but rather centering the label over the slider knob/handle (or whatever you call the thing you drag). For example, the modulation intensity sliders that NI uses display the setting with 'moving caption baloon'. That always remains approximately centered over the 'handle'.
> 
> Your illustrative code simply displays the value in the center of a fixed label. So, what I was saying is that if we want to mimic the behaviour of the NI slider, wouldn't we have to dynamically position the label?



Ah, you mean THAT. Yes, in that case you'd need to dynamically position the label. But that might add some CPU drain. I prefer fixed labels, myself.


----------



## Big Bob (Mar 2, 2011)

> Ah, you mean THAT. Yes, in that case you'd need to dynamically position the label. But that might add some CPU drain. I prefer fixed labels, myself.



Yes indeed, a fixed label may be just fine generally. But, remember, I'm in the newby learning mode and I'm just trying to come up to speed by examining things and pondering how they are done.

Examining NI's slider behavior a little more, I see other things that are kind of clever, and perhaps tricky to implement (either that or they have the advantage of additional fire power that we don't have :lol: ). In any case, I think I will make trying to mimic NI's slider behavior a learning case study. The process may prove to be most instructive and yet may even have a useful result. If nothing else, it will probably be great fun :wink: .

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

Oh, goodie! While you're learning, I'm just gonna leave this here... :lol:


----------



## Big Bob (Mar 2, 2011)

Wow! I haven't even had a chance to clear my desk of all the in process stuff that I need to deal with before thinking about 'The Big NI Slider Project', and here you are with an implementation. o-[][]-o 

I can't be sure from your animation but, does your implementation also display the value continuously as long as the mouse remains down? Looks like it does and if so, then I would say you have implemented NI's slider display quite well. The only difference would appear to be the cartoon-like label skin that NI uses and that should be easy to do.

Maybe I should just ask you to post your code for everyone's benefit, since you have already done it (unless you want to keep it secret). Or, maybe you would rather hold it back just to see if I can duplicate what you have done (at least functionally) and then we can compare implementations; that might be fun. But maybe I should dream up another case study for myself rather than try to duplicate your effort.

What's your preference? I'm game either way 8) 

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

I'm feeling a bit evil, so I just might let you do the whole thing yourself. But I respect the elderly, so here's the code! It's not exactly rocket science either! :lol:

http://pastebin.com/raw.php?i=15zLNtr8


Cheers! o-[][]-o


----------



## polypx (Mar 2, 2011)

Mario, 

That moving label is brilliant! I hadn't thought of doing that before. 

cheers
Dan


----------



## EvilDragon (Mar 2, 2011)

Well, it was all Bob's idea. :lol:


----------



## Big Bob (Mar 2, 2011)

I can't take the credit, it was NI's idea. I just pointed it out :lol: 

BTW I just downloaded your code but I haven't had time to use it or digest it yet and my wife just called me for lunch. So, I'll be back later.

However, I'll mention that as I was thinking about the implementation, I concluded that the most difficult part would be displaying on mouse down and not displaying on mouse up. Since there doesn't seem to be any function provided for us to read the mouse state, it means we have to do it based strictly on the callback logic. To do that reliably might be tricky :roll: so that's why I asked if you had conquered that part of it. 

Well, I'll be back after lunch.

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

Big Bob @ 2.3.2011 said:


> However, I'll mention that as I was thinking about the implementation, I concluded that the most difficult part would be displaying on mouse down and not displaying on mouse up. Since there doesn't seem to be any function provided for us to read the mouse state, it means we have to do it based strictly on the callback logic. To do that reliably might be tricky :roll: so that's why I asked if you had conquered that part of it.



Remember the watchdog timer? That's how it's done. Except instead of set_text(), it does "hide the label".


----------



## Big Bob (Mar 2, 2011)

Hi Mario,

I loaded your code into into K4 and ran it. And, I'll give you 'A' for effort, but, as I suspected, it doesn't completely mimic NI's slider. With NI's implementation, if you click the slider and hold the mouse down, the label continues to display (ie doesn't time out) whether or not you drag the slider handle. And as soon as you release the mouse, the label vanishes (with no time delay).

This behavior is the part that I think we might have difficulty in reliably duplicating. NI no doubt has more 'fire-power' available to them (such as mouse position and condition information) that they haven't provided us with. At least I haven't found any such functions in my docs. If anyone knows about any such functions, please let me know.

To mimic NI's slider behavior with only the callback logic will be tricky. For example, here's a quick attempt I made (by modifying your code) that mostly works, but, it's not perfectly reliable because you can drag the slider quickly and sometimes (while the mouse is still down) it will revert to inactive. Then, when you release the mouse, the label will be active. And, of course that's not what we want.

*on init*
make_perfview
*declare* ui_slider $Tune(0, 1000000) 
*declare* ui_label $text(1, 1) 
*declare* ui_label $title(1, 1) 
*declare* $last_time
```*declare* last_val
```*declare* active
*declare* %values[73]``:= (0, 13820, 27709, 41598, 55487, 69376, 83264, 97153, 111042, 124931, 138820, 152709, 166598, 180487, 194376, 208264, 222153, 236042, 249931, 263820, 277709, 291598, 305487, 319375, 333264, 347153, 361042, 374931, 388820, 402709, 416598, 430487, 444375, 458264, 472153, 486042, 500000, 513820, 527709, 541598, 555487, ...
569376, 583264, 597153, 611042, 624931, 638820, 652709, 666598, 680487, 694376, 708264, 722153, 736042, 749931, 763820, 777709, 791598, 805487, 819376, 833264, 847153, 861042, 874931, 888820, 902709, 916598, 930487, 944376, 958264, 972153, 986042, 999931)
set_control_par(get_ui_id($Tune),$CONTROL_PAR_DEFAULT_VALUE,500000)
set_control_par(get_ui_id($text),$CONTROL_PAR_TEXT_ALIGNMENT,1)
set_control_par(get_ui_id($text),$CONTROL_PAR_FONT_TYPE,3)
set_control_par(get_ui_id($text),$CONTROL_PAR_WIDTH,56)
set_control_par(get_ui_id($text),$CONTROL_PAR_HEIGHT,17)
set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_WHOLE_CONTROL)
set_control_par(get_ui_id($title),$CONTROL_PAR_WIDTH,38 )
set_control_par(get_ui_id($title),$CONTROL_PAR_FONT_TYPE,12)
set_control_par(get_ui_id($title),$CONTROL_PAR_TEXT_ALIGNMENT,1)
set_control_par(get_ui_id($title),$CONTROL_PAR_TEXTPOS_Y,3)
set_control_par(get_ui_id($title),$CONTROL_PAR_HIDE,$HIDE_PART_BG)
move_control($Tune,2,2)
move_control_px($title,118,23)
set_text($title,"Tune:")
$Tune := get_engine_par($ENGINE_PAR_TUNE,-1,-1,-1)

``last_val := Tune
message("")
*end on*

*on ui_control*($Tune)
``*if* Tune = last_val
````Active := 1 - Active
``*else*
````Active := 1
``*end if* 

set_engine_par($ENGINE_PAR_TUNE,$Tune,-1,-1,-1)
set_text($text,get_engine_par_disp($ENGINE_PAR_TUNE,-1,-1,-1) & " st")
move_control_px($text,138+($Tune/14000),5)
``last_val := Tune
```*if* Active = 0
`````set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_WHOLE_CONTROL)``````````
```*end if*
*end on*




To make this more reliable may be tricky to impossible. Let's ponder it a bit and see if we can come up with some brilliant way to make a bullet-proof version of this :lol: 

Rejoice,

Bob

EDIT: Whoops, I see that your line ending in 38 ) got changed to a 3 smiley. I'll try to fix it but if you already copied the code you'll have to fix this before it will compile.


----------



## EvilDragon (Mar 2, 2011)

Now you're pushing it!  That does seem quite difficult to do.


BTW, use

```
tags for posting... well, code. ;)
```


----------



## Big Bob (Mar 2, 2011)

> Now you're pushing it! That does seem quite difficult to do.



I haven't had a chance to fully test this yet, but, it may be as simple as replacing the value of Tune with it's picture state. I'll get back to you in a bit.



> BTW, use
> 
> ```
> tags for posting... well, code. [/quote]
> ...


----------



## Big Bob (Mar 2, 2011)

Checking for a change in the picture state does seem to improve the performance but I can still mess it up with certain movements. I'll post this version (with code tags) just in case someone wants to play around with it.


```
on init 
make_perfview 
declare ui_slider $Tune(0, 1000000) 
declare ui_label $text(1, 1) 
declare ui_label $title(1, 1) 
declare $last_time 
   declare last_val 
   declare active 
declare %values[73]  := (0, 13820, 27709, 41598, 55487, 69376, 83264, 97153, 111042, 124931, 138820, 152709, 166598, 180487, 194376, 208264, 222153, 236042, 249931, 263820, 277709, 291598, 305487, 319375, 333264, 347153, 361042, 374931, 388820, 402709, 416598, 430487, 444375, 458264, 472153, 486042, 500000, 513820, 527709, 541598, 555487, ... 
569376, 583264, 597153, 611042, 624931, 638820, 652709, 666598, 680487, 694376, 708264, 722153, 736042, 749931, 763820, 777709, 791598, 805487, 819376, 833264, 847153, 861042, 874931, 888820, 902709, 916598, 930487, 944376, 958264, 972153, 986042, 999931) 
set_control_par(get_ui_id($Tune),$CONTROL_PAR_DEFAULT_VALUE,500000) 
set_control_par(get_ui_id($text),$CONTROL_PAR_TEXT_ALIGNMENT,1) 
set_control_par(get_ui_id($text),$CONTROL_PAR_FONT_TYPE,3) 
set_control_par(get_ui_id($text),$CONTROL_PAR_WIDTH,56) 
set_control_par(get_ui_id($text),$CONTROL_PAR_HEIGHT,17) 
set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_WHOLE_CONTROL) 
set_control_par(get_ui_id($title),$CONTROL_PAR_WIDTH,38 ) 
set_control_par(get_ui_id($title),$CONTROL_PAR_FONT_TYPE,12) 
set_control_par(get_ui_id($title),$CONTROL_PAR_TEXT_ALIGNMENT,1) 
set_control_par(get_ui_id($title),$CONTROL_PAR_TEXTPOS_Y,3) 
set_control_par(get_ui_id($title),$CONTROL_PAR_HIDE,$HIDE_PART_BG) 
move_control($Tune,2,2) 
move_control_px($title,118,23) 
set_text($title,"Tune:") 
$Tune := get_engine_par($ENGINE_PAR_TUNE,-1,-1,-1) 

  last_val := get_control_par(get_ui_id($Tune),$CONTROL_PAR_PICTURE_STATE) 
message("") 
end on 

on ui_control($Tune) 
  if get_control_par(get_ui_id($Tune),$CONTROL_PAR_PICTURE_STATE) = last_val 
    Active := 1 - Active 
  else 
    Active := 1 
  end if 

set_engine_par($ENGINE_PAR_TUNE,$Tune,-1,-1,-1) 
set_text($text,get_engine_par_disp($ENGINE_PAR_TUNE,-1,-1,-1) & " st") 
move_control_px($text,138+($Tune/14000),5) 
  last_val := get_control_par(get_ui_id($Tune),$CONTROL_PAR_PICTURE_STATE) 
   if Active = 0 
     set_control_par(get_ui_id($text),$CONTROL_PAR_HIDE,$HIDE_WHOLE_CONTROL)            
   end if 
end on
```

Perhaps some clever combination of picture state and value change or by utilizing the new timer interrupt capabilities of the on listerner callback? Food for thought :roll: 

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

Big Bob @ 3.3.2011 said:


> > BTW, use
> >
> > ```
> > tags for posting... well, code. [/quote]
> > ...


----------



## Big Bob (Mar 2, 2011)

Hi Blake,

Oh darn! When I saw there was a post from you I thought you were going to step in with some elegant solution and win the prize :( 



> Argh! Painful memories of trying to get drag/drop logic working the other night using a slider and a bag of tricks. I gave up in the end - sliders just aren't reliable enough. Lets hope NI improves the UI capabilities in K5 - I'd love to see proper UI callbacks where it passes parameters and events.



Amen to that! But, on the other hand, compared with K2, K4.2 is a dream :mrgreen: 



> Oh, and tsk tsk - shame on you for removing type identifiers from your variables when they're not loosely typed



Huh! :?

OK come on guys, put on your thinking caps and let's see some clever solutions here :roll: . I was thinking about offering a first prize of a refrigerator and a trip around the world, but, Rosie says we can't afford to take the chance because someone just might do it :lol: 

Rejoice,

Bob


----------



## EvilDragon (Mar 2, 2011)

I really think without some commands to detect mouse up and mouse down on an UI control, this is gonna be impossible. The watchdog thingies is about as far as it gets, I'm pretty sure...


----------



## Big Bob (Mar 2, 2011)

> I really think without some commands to detect mouse up and mouse down on an UI control, this is gonna be impossible. The watchdog thingies is about as far as it gets, I'm pretty sure...



Yes, I'm pretty sure you're right Mario. And, since Blake seems to have wrestled with it a bit also, the prognosis is getting worse :( Still it's been a lot of fun trying and it sort of forced me to get really better aquainted with what is and isn't available to work with in K4.2.

I'm not totally ready to give up yet but, I am going to move it to the back burner for now. And, if it can't be done, the watchdog implementation is a close second. So, onward and upward ~o) 

Rejoice,

Bob

EDIT: Hey Blake, I guess you slipped one in while I was typing the above. Very cute as always but maybe not too practical?  I'm quitting for the night guys, sweet dreams.

EDIT SOME MORE. Whoops, what happened to the 'roulette wheel'? :shock:


----------



## Big Bob (Mar 3, 2011)

Hey Guys,

I may have some good news. I have a technique that mimics NI's Slider value display and it may be pretty bulletproof :roll: I need to do more extensive testing but, so far, I haven't been able to make it fail.

If it survives additional 'torture' testing, I'll post my code and you guys can beat on it. On the other hand, if I do eventually make it fail before that, I'll put my tail between my legs and post my regrets :oops: 

Hey Nils,

Since I never run K4 other than in standalone mode (via MIDI), I want to be sure I understand correctly that what you are saying applies only to what the DAW host sees when operating K4 as a plugin? If this also somehow affects standalone performance, then I need to better understand what you are saying. If not, I won't concern myself about it much until I have to cross that bridge :wink: 

Rejoice,

Bob


----------



## EvilDragon (Mar 3, 2011)

Yep, Nils' code only influences DAWs the most. Well, apart from $CONTROL_PAR_ALLOW_AUTOMATION - this one basically disables right-click MIDI learn on a control, so this works in standalone as well. That one was a recent K4.2 addition, as well.


----------



## Big Bob (Mar 3, 2011)

> Yep, Nils' code only influences DAWs the most. Well, apart from $CONTROL_PAR_ALLOW_AUTOMATION - this one basically disables right-click MIDI learn on a control, so this works in standalone as well. That one was a recent K4.2 addition, as well.



I am aware of $CONTROL_PAR_ALLOW_AUTOMATION, I was just referring to the automation name and label stuff as it applies to sliders.

BTW So far so good with my slider technique but I still have more testing I want to subject it to 8) .

Rejoice,

Bob


----------



## Tod (Mar 6, 2011)

*find_mod, find_target, (Variables)?*

Is there anything wrong with getting the variables for find_mod, find_target and then useing those variables in the script?

For instance I used this code to get "$FndTarg := 0 and Find Mod = 1".


```
on init
  declare $FndTarg
  declare $FndMod
  $FndTarg := find_target(0,find_mod(0,"ENV_AHDSR_EQ"),"ENV_AHDSR_EQ_GAIN_1")
  $FndMod := find_mod(0,"ENV_AHDSR_EQ")
  message (" $FndTarg :=" & $FndTarg & "    " & "Find Mod = " & $FndMod)  
end on
```

Is there any reason I can't use these variables in this?

set_knob_label($EnvAmt,get_engine_par_disp($ENGINE_PAR_INTMOD_INTENSITY,0, *$FndMod*,*$FndTarg*))

This not only saves real estate but is much easier to read and understand.

Tod


----------



## EvilDragon (Mar 6, 2011)

Nothing wrong in doing so, Tod.


----------



## Tod (Mar 6, 2011)

EvilDragon @ Sun Mar 06 said:


> Nothing wrong in doing so, Tod.



Thanks Mario, this will make life much easier. :D


----------



## Big Bob (Mar 7, 2011)

HI guys,

The other day I was in the process of writing down the image-level or priority ordering of the ui controls. I know that menu is the highest and button is the 2nd highest for example, but I never completed the tests required to finish the list. Today I was about to finish the job when I discovered that I misplaced my worksheet and so now I'd have to do it from scratch again.

Before I do that, I'm sure at least one of you must have already done this (I'll bet Mario has it tatooed on his arm :lol: ) so, if someone would kindly post the control priority list for me I would really appreciate it.

Also, to be sure I fully understand this, I'll enumerate how I think this goes.

When two or more controls are overlayed, there is:

(1) A priority or hierarchy of the control types that determines which one will be on top.

(2) When multiple controls of the same type are overlayed, the last one declared will be on top.

It's the hierarchy in (1) I am interested in.

Thanks,

Bob


----------



## kotori (Mar 7, 2011)

Hi Bob,

In decreasing z-order: ui_menu, ui_switch, ui_slider, ui_label

I don't know about ui_knob and ui_table, but I assume that ui_label should have the lowest z-order in any case.

Cheers,
Nils


----------



## Big Bob (Mar 7, 2011)

Hi Nils,

Thanks, but I'm hoping someone has the entire list put in Z order. BTW if I remember correctly, switch is actually lower than button. So, if you are correct, my memory must be faulty again (happens way too often these days :lol: ) 

I guess if no one posts the complete list, I'll have to re-discover it all over again :( 
and if I do that, I'll post the list afterwards.

Rejoice,

Bob

EDIT: I'm sorry Nils, somehow when I read your post I thought you were saying a switch was higher in order than a button but now I see that you never even mentioned a button,


----------



## EvilDragon (Mar 7, 2011)

There's also ui_waveform, which is very weird - its display section and display frame have DIFFERENT z-orders!

So, the list would be (as tested):

ui_menu
ui_button
ui_switch
ui_slider
ui_table (frame goes BEHIND ui_slider but ABOVE ui_knob, and the table values go ABOVE ui_menu even!)
ui_knob
ui_value_edit
ui_label (background and text go behind everything listed till here, except when superimposed with ui_table - the label text goes even above table values - DEPENDS EVEN ON THE FONT!)
ui_waveform (frame goes BEHIND ui_label background, but ABOVE labels on ui_knob, but waveform display goes ABOVE the ui_label background, below ui_label text!)


```
on init
set_ui_height(3)

pgs_create_key(INIT,1)
pgs_set_key_val(INIT,0,0)

declare $i

declare ui_menu $1
declare ui_button $2
declare ui_switch $3
declare ui_slider $4 (0,1)
declare ui_table %5[2] (1,1,1)
declare ui_knob $6 (0,1,1)
declare ui_value_edit $7 (0,1,1)
declare ui_label $8 (1,1)
declare ui_waveform $9 (1,1)

declare ui_table %10[2] (1,1,1)
declare ui_label $11 (1,1)
declare ui_value_edit $12 (0,1,1)

move_control_px($1,65,5)
move_control_px($2,50,10)
move_control_px($3,62,18)
move_control_px($4,80,25)
move_control_px(%5,90,30)
move_control_px($6,100,40)
move_control_px($7,110,65)
move_control_px($8,115,70)
move_control_px($9,125,80)

move_control_px(%10,300,30)
move_control_px($11,350,25)
move_control_px($12,350,70)

set_control_par(get_ui_id(%10),$CONTROL_PAR_WIDTH,200)
set_control_par(get_ui_id(%10),$CONTROL_PAR_HEIGHT,50)

set_text($11,"test test test test")

message("")
end on

on pgs_changed
	while (1=1)
		if (%10[0] = 0)
			%10[0] := 1
			%10[1] := 0
			set_control_par(get_ui_id($11),$CONTROL_PAR_FONT_TYPE,$i mod 24)
			set_control_par(get_ui_id($12),$CONTROL_PAR_FONT_TYPE,$i mod 24)
		else
			%10[0] := 0
			%10[1] := 1
		end if
		inc($i)
		wait(1000000)
	end while
end on
```


----------



## Big Bob (Mar 7, 2011)

Thanks Mario,

Somehow I just knew you would have this information right at your fingertips :lol: 

Rejoice,

Bob


----------



## EvilDragon (Mar 7, 2011)

Forgot to put ui_value_edit in the list. Corrected previous post. Added fancy test code for ui_label and ui_value_edit fonts bleeding over ui_table. :lol:


o-[][]-o


----------



## Dynamitec (Mar 7, 2011)

Big Bob @ Mon Mar 07 said:


> BTW I want to thank you for posting your pixel chart and photoshop template (I know it was a long time ago) but I grabbed it and put it aside for the day when I could get back in the game and now that I am, I find it very useful indeed (as I knew I would).



I second that! Very useful. Comes in quite handy when working on new skins


----------



## Lindon (Mar 7, 2011)

> When two or more controls are overlayed, there is:
> 
> (1) A priority or hierarchy of the control types that determines which one will be on top.
> 
> (2) When multiple controls of the same type are overlayed, the last one declared will be on top.



Whilst (not) on the subject of (2) above here's something I've found different in K4.2 vs k4.1....

If you overlay two buttons in V4.1 you get the behaviours outlined by Bob above; *even if you dont define the size (WIDTH and HEIGHT) of the top-most button*.

However in 4.2 to get any reasonable behaviour you *MUST* define at least the width of your top-most button, otherwise behaviours on click get a bit random...


----------



## Big Bob (Mar 7, 2011)

Hi Lindon,



> However in 4.2 to get any reasonable behaviour you *MUST* define at least the width of your top-most button, otherwise behaviours on click get a bit random...



Could you elaborate a bit? When you say on click do you mean erratic callback triggering or picture state display or reaching through the top layer or what?

BTW I don't know if everyone has picked up on this or not but buttons trigger the callback on the release whereas switches trigger it on depression. Might be useful to know, no? :lol: 

Rejoice,

Bob


----------



## Lindon (Mar 7, 2011)

Bob, 

Basically its affecting callback, but looks more like the top-most button cant decide what its screen real estate really is. An example might help..here's a video...
[youtube]
http://www.youtube.com/user/ChannelR0b0 ... OyiqTraFLo
[/youtube]

The fx tabs are about 11mins in I'm afraid(and its the 4.1 version of the app so it all works fine...). 

You will see there are tabs, each tab is named for an FX and has on it a red on/off button....under 4.1 these work fine, click on the name and the tab opens up, click on the red on/off and the FX is turned on(or off), however under 4.2 if you click on the *name* then the on/off callback is fired the first time you click, BUT click again and the (correct) tab functionality is fired... if (in 4.2) I define the width of the on/off buttons in my code then behaviours return to normal...so its not a big deal but its a bit of additional work to do...


----------



## Big Bob (Mar 7, 2011)

How strange, have you reported this to NI?


----------

