# Script warning related to $control_par_default_value



## Chriss Ons (Mar 8, 2013)

KSP is again yelling something at my uncomprehending face, but I don't know what it is. 

In the _on_init_ section I set a default value for this slider:

```
declare ui_slider $SatKnob (1,1000000)
```
using:

```
set_control_par(get_ui_id($SatKnob),$CONTROL_PAR_DEFAULT_VALUE,523500)
```
Which works and, when Ctrl-clicked, sets the corresponding slider in the GUI at 4.7%, like I want it to.
I added an _on ui_update_ CB for this slider and the changes when setting the default value are also visible in the insert effect section. Everything works as expected, and when I update the script it says _(no errors)_ - but I do get the following script warning:


> SCRIPT WARNING: invalid slider value (clipped to min value)! Line: 562, Program: 0



...Not quite sure what to make of this?


----------



## Big Bob (Mar 8, 2013)

I notice that your min value for the slider is 1 and not 0. Possibly, the value is zero initially or somewhere along the way as your code runs?

Why not make the slider range from 0 to 1000000?

Rejoice,

Bob


----------



## mk282 (Mar 9, 2013)

Yep, always use 0 to 1000000 knob range if you want to cover the full value range of the parameter.


----------



## Chriss Ons (Mar 9, 2013)

Thanks heaps, this got rid of the script warning!

Two more questions if that's okay:

1) I understand that switches (as opposed to buttons) can be automated, but can they also have a default state, i.e. on/off when Ctrl-clicked? I tried this but it doesn't work and I can't seem to find it in the KSP manual. 

2) For some reason I can't get stepped sliders to work. For example, the S-compressor's _Attack_ knob has 6 possible/preset values when turned (although it's not a stepped knob in instrument edit mode): 

0.1, 0.3, 1, 3, 10 and 30 ms

Now,when I leave the minimum/maximum values of this slider in the GUI at (0,1000000) and want the default value to be 1 ms, using:


```
set_control_par_(get_ui_id($CompAttackKnob), $CONTROL_PAR_DEFAULT_VALUE,450000)
```
this gives the desired result - when you Ctrl-click the slider, it jumps to 1ms. But for the sake of convenience, it really should be a _stepped _knob/slider in the GUI. Now, when I change the min/max values in _declare ui_slider_, I do get a stepped knob with 6 positions, but _the corresponding value label stops working_ - it only displays the minimum value, in this case 0.1 ms, no matter what position the knob is on. :?
I tried different combinations for the min/max values, e.g. _(0,5)_, _(1,6)_ or even _(0,6) _ but the value label doesn't work anymore. Hmm... what now?

Thanks in advance.


----------



## Big Bob (Mar 9, 2013)

Hi Josquin,

Regarding (1), you can easily accomplish the same thing with some simple code in the callback handler for the button/switch. If you want I can post an example for you. *SEE NEXT POST*.  

Regarding (2), you didn't state how you are displaying the slider label value. But here's an example that just uses get_engine_par_disp.

*on init*
``message('')
``*declare* ui_slider Slider (0,1000000)
``*declare* ui_label SVal(1,1)
*end* on

*on ui_update*
``Slider := get_engine_par(ENGINE_PAR_SCOMP_ATTACK,0,0,1)
``set_text(SVal,get_engine_par_disp(ENGINE_PAR_SCOMP_ATTACK,0,0,1))
*end* on

*on ui_control* (Slider)
``set_engine_par(ENGINE_PAR_SCOMP_ATTACK,Slider,0,0,1)
``set_text(SVal,get_engine_par_disp(ENGINE_PAR_SCOMP_ATTACK,0,0,1))
*end* on

Is this what you wanted?

Rejoice,

Bob

BTW The above code snippet will have to be first compiled in Nils' Editor or you will have to manually add all the dollar signs, etc.


----------



## Big Bob (Mar 9, 2013)

Here's an example of using ctl-click to set a switch to a specified default state.

*on init*
``message('')
``*declare* *const* DEFAULT := 1
``*declare* ui_switch Test
*end* on

*on ui_control*(Test)
``*if* get_control_par(get_ui_id(Test),CONTROL_PAR_KEY_CONTROL) = 1
````Test := DEFAULT
``*end* *if*
*end* on

Rejoice,

Bob


----------



## mk282 (Mar 9, 2013)

I don't think one even needs a "default state" for a switch. It's just two states anyways!


Regarding your second question about the S-Comp... even though the knob is "stepped", ALL engine parameters are using the range of 0 to 1000000 internally, stepped or not. That's just how KSP is. If you really want just a stepped knob in the UI, then makeit a knob with the desired amount of steps that's going to read engine parameter values from an array. Example:


```
on init
    declare %values[6] := (0, 200000, 400000, 600000, 800000, 1000000)
    declare ui_knob $Knob (0,5,1)
    make_persistent($Knob)
end on

on ui_control ($Knob)
    set_engine_par(<some engine parameter you want>,%values[$Knob],<group>,<slot>,<generic>)
end on
```


----------



## Chriss Ons (Mar 9, 2013)

@ Bob: thanks heaps for the example, that's really what I've been using when declaring value labels and in the corresponding CB - it works fine everywhere in the instrument - it's only when I start to change the min/max values for the slider, that it stops working. I guess it has to do with what mk282 explained.
And thanks a lot for that switch example, I'll see if I can implement it that way!

@ mk282: thanks for explaining, makes sense. But if I turn that slider into a _knob_ with an array, will I still be able to skin it?
(and as for the reason to give a switch a default value, you're totally right but I figured that if you use _make_persistent_ and the user saves the nki, he/she can never know the original state of the switch afterwards - and I wanted to give the user the chance to recall all the aspects of a preset - e.g. if there are two choruses in the fx module, were they both on by default? Or just one? Or none for this preset? )

But if I can't get Bob's example to work, I still have the info text which appears on mouseover, for the name labels of the effect names. There I could include 'default: on'. But I guess that would be just... lazy :lol:

Thanks again.


----------



## mk282 (Mar 9, 2013)

Yeah, instead of ui_knob just use ui_slider with the same range (0,5), since ui_sliders are skinnable and ui_knobs are not.


----------



## Big Bob (Mar 9, 2013)

> it works fine everywhere in the instrument - it's only when I start to change the min/max values for the slider, that it stops working. I guess it has to do with what mk282 explained.



I'm not sure what you mean by the above. If you are talking about using a range other than 0 to 1000000, then of course it will no longer work correctly. However, since the way it is in my example, the only settable and displayed values are the same steps as the Edit knob so why do you want to change the slider's range? 

But, if for some reason you need to have the pseudo-knob only cover the range from 0 to 5, then MK's suggestion would be the way to go. But, I'm rather puzzled by why you need to change the slider's range to anything other than 0 to 1000000? :? 

Rejoice,

Bob


----------



## mk282 (Mar 9, 2013)

Depends on the parameter, Bob. Let's say I don't need the full 0% to 800% range of the Speed knob in Time Machine modes. You wouldn't use 0 to 1000000 then. Same goes for EQ - in my opinion the range of Gain knobs (+/- 18 dB) is far too large, so I usually reduce the range to +/- 12 or +/- 9 dB by reducing the knob range from the usual 0 to 1000000 range.


----------



## Big Bob (Mar 9, 2013)

Hi Mario,

Yes, I guess there might be situations where one would want a reduced range.

However, in that case, couldn't one just find the min and max ep values required and make that the range? I mean instead of trying to find 5 or more ep values for the in-between stuff and then using a table lookup?

Of course I suppose there also might be other reasons for using the table idea, such as when the function is highly non-linear but one wants the slider positions to be more or less uniformly spaced and one wants to avoid using a Math Library function to linearize it.

In any case, I guess there's often more than one way to skin a cat, no?. :lol: 

Rejoice,

Bob


----------



## mk282 (Mar 9, 2013)

Big Bob @ 10.3.2013 said:


> In any case, I guess there's often more than one way to skin a cat, no?. :lol:




Very true! :lol:


----------



## Big Bob (Mar 10, 2013)

Hey Josquin, 

I should probably mention that if you restrict the range of your slider on either or both ends, it will somewhat complicate the on ui_update callback routines. You will have to allow for the possibility that the user turns the Edit knob to a position outside of the the restricted range. So you will need some limit checking and overide code to prevent this.

Also, if you use Mario's array technique, you will have to use something like a case statement with multiple ranges to convert backwards from ep to your mapped knob values. You probably already know all this but I thought I would mention it just in case.

Rejoice,

Bob


----------



## Chriss Ons (Mar 10, 2013)

Bob/Mario, thanks for the insight. In conclusion, is it correct then to say that I have two options here:

- leave it the way it is - i.e. a skinned slider, albeit not stepped
- turn the control into a knob (which can't be skinned), and make it stepped / use an array

...?


----------



## Big Bob (Mar 10, 2013)

Actually, it doesn't matter whether you use a slider or a knob. Maybe you should define just what you mean by a stepped control. All sliders and knobs have more or less smooth graphics which will display on the order of 100 positions or so over their full range of travel.

I have been assuming that by stepped you simply mean the displayed value will change in discrete steps. For example, if you have a slider that takes on only 6 values, each value change will represent about 1/6th the total travel.

Are you saying that you want the slider to sort of 'snap' so that it never occupies the 'in-between' physical positions?

Maybe you could clarify just what your end objective is :? 

Rejoice,

Bob


----------



## Chriss Ons (Mar 10, 2013)

Big Bob @ Sun 10 Mar said:


> Are you saying that you want the slider to sort of 'snap' so that it never occupies the 'in-between' physical positions?


Exactly. It's when I change the slider's minimum/maximum and default values from

```
declare ui_slider $CompAttackKnob (0,1000000)
	set_control_par(get_ui_id($CompAttackKnob),$CONTROL_PAR_DEFAULT_VALUE,450000)
```

to this:

```
declare ui_slider $CompAttackKnob (0,5)
	set_control_par(get_ui_id($CompAttackKnob),$CONTROL_PAR_DEFAULT_VALUE,2)
```

in order to make it a stepped slider with only 6 possible values - which the slider also snaps to - that the value label stops working properly: it now shows the first possible value of the SCOMP's Attack knob (i.e. 0.1 ms) - no matter what position the slider is put in - and the changes are no longer updated in the compressor fx module either (the knob there doesn't move).

The only thing that does work, is that Ctrl-clicking the slider will put it at the third value (because here it's set to "2" in a range of 0-5). 

Yet, when I turn the _Attack_ knob in the Kontakt effect module itself (not on the GUI), the value label on the GUI _does_ update correctly (it displays the engine parameter because this is defined in the on_ui update callback, I guess?) but the slider in the GUI _doesn't move accordingly_ - which I suppose is due to what Mario explained, about all engine parameters using the range of 0 to 1000000 internally, stepped or not? And that the way around this would be to declare a knob, make it stepped, and use an array?

Or am I still totally not getting it? (it wouldn't surprise me :lol: )


----------



## mk282 (Mar 10, 2013)

Check this out:


```
on init
	declare %values[6] := (10, 166677, 333343, 500010, 666677, 833343)

	declare ui_knob $Attack (0,5,1)

	set_knob_defval($Attack,2)
	set_knob_unit($Attack,$KNOB_UNIT_MS)

	make_persistent($Attack)

	set_knob_label($Attack,get_engine_par_disp($ENGINE_PAR_SCOMP_ATTACK,-1,0,1))

	message("")
end on

on ui_control ($Attack)
	set_engine_par($ENGINE_PAR_SCOMP_ATTACK,%values[$Attack],-1,0,1)
	set_knob_label($Attack,get_engine_par_disp($ENGINE_PAR_SCOMP_ATTACK,-1,0,1))
end on

on ui_update
	$Attack := search(%values,get_engine_par($ENGINE_PAR_SCOMP_ATTACK,-1,0,1) + 1)
	set_knob_label($Attack,get_engine_par_disp($ENGINE_PAR_SCOMP_ATTACK,-1,0,1))
end on
```

The "Attack" knob of S-Comp only uses these engine parameter values: 0, 166667, 333333, 500000, 666667, 833333. However, I noticed that sending exactly those values to this control via KSP does not work for all positions (I guess a bug?), so I had to do a tiny workaround - increase all those values by 10, so it would DEFINITELY switch to those positions that are needed. Then in ui_update callback do the nifty thing to search the %values array for the current engine parameter value PLUS 10 (to compensate), which will set the knob to correct position, and also refresh the value label.


Neat, isn't it?


----------



## Big Bob (Mar 10, 2013)

> Or am I still totally not getting it? (it wouldn't surprise me )



Unfortunately, it's beginning to look that way :lol: 

Let me make one more attempt at clarifying this for you. You can't simply change the value range of your slider to some arbitrarily small range. Just because the actual parameter being controlled has only 5 or six values, the ep to control it must still cover the range from 0 to 1000000. That's just fundamental to the way the KSP has been organized.

Suppose that you have a Kontakt parameter that has only 5 possible values like 5Hz, 25Hz, 125Hz, 625Hz, and 3125Hz. The engine parameter to control this parameter will still cover the numerical range from 0 to 1000000 (where 0 will correspond with 5 Hz and 1000000 will correspond with 3125Hz). If you now want to have your panel slider only control the range from 25Hz to 625Hz, you would have to find the ep values that correspond with 25Hz and 625Hz. For example, if the functional relationship between ep and frequency was linear in frequency ratios, these ep values might be around 250000 and 750000. ** 

Once the ep values for 25Hz and 625Hz are found, you would then make your slider range to be from 250000 to 750000. Then, as you moved the slider from min to max, the actual parameter knob (or whatever you are controlling) would set itself to 25Hz, 125Hz, or 625Hz. With your slider in the lower 35% or so of its range, the frequency setting would remain at 25Hz. With your slider somewhere in the middle 1/3 of its range, the frequency displayed would be 125Hz and in the last 35% or so of the slider's position, the value displayed would be 625Hz.

Now, you will never see values displayed in-between 25Hz and 125Hz but yet the slider graphics will show in-between positions. If you don't want to see those in-between positions, then you have at least two choices.

(1) You can do custom graphics with only 3 animation states.
(2) You can override the actual position some way in the callback handler so that the slider will always jump to one of the 3 designated positions. This can be tricky to implement because you will have to use waits and such to avoid giving the user the feeling that he can't properly set the slider where he wanted it. But, it can be done.

Now, the same graphics problem applies also to Mario's idea with the array. For the above example, if you use Mario's method, you might define the knob to have a range from 0 to 2. You would then declare an array containing the values of 250000, 500000, and 750000. Let's call this array FEP[3] := (250000,500000,750000).

Now in your callback handler for the slider, you would send FEP[Slider] as the engine parameter instead of just sending the value of Slider. Notice that either way, the actual eps sent will be 250000, 500000, and 750000. Whereas, without the array, when you move the slider from min to max, all the integers between 250000 and 750000 might be sent as the ep. However, the receiving control itself and therefore the displayed value will only be one of the three possible frequencies.

Finally, let me clarify the reverse part of the problem. I believe you originally stated that you also wanted to have your panel slider reflect any changes the user might make to the actual controlled parameter. There are two potential problems associated with this.

(1) If your slider's range covers less than the actual parameter range, you will have to override when the user tries to set something outside of your narrower range.

(2) The 2nd problem occurs with using the array method. The ep given to you might be something like 286179 for example. To reverse convert this to the corresponding array index, you will have to determine what the nearest useable value to this is (in this case that would be 250000 and so your index should be 0). In other words, you will have to construct something like a N-way case statement to perform the 'reverse' conversion.

If this still isn't clear to you, it might be easier for me to simply post a specific example script if you would tell me exactly what you want illustrated. Just pick one of your sliders, tell me what parameter it is to control and what sub-range you want it to cover, etc.


** This is oversimplified because the ep to actual parameter relationship is often non-linear in quite complex ways.


Rejoice,

Bob

*EDIT:

Whoops I see that while I was typing, Mario posted just such an illustration. Perhaps between his example and my discussion above, the light bulb will go on :lol: *


----------



## Chriss Ons (Mar 11, 2013)

Guys, the light bulb is starting to go on. Thanks so much for taking the time to explain/illustrate this in depth the way you did - I'm sure others are going to learn from this as well!


----------

