Cabbage Logo
Back to Cabbage Site

Idea: snapback(BOOL)

This would be for any widget types other than widgets with preset/static values (such as checkbox/button/combobox/etc). I’m mostly considering this for “slider” widgets, but I honestly didn’t consider all options yet. :wink:

snapback() would be a way to tell cabbage that when mouse input ceases on a widget, it should return to the widget’s default value. This behavior essentially mimics the common “pitchwheel” style behavior, but still allows for an arbitrary (non-center/assymetric) value to return to via the default set in the widget’s range().

For example, this widget should return to 50 when released:
range(0,100,50), snapback(1)

And this widget should return to 0:
range(0,100,0), snapback(1)

I used a commercial plugin that uses a widget in this fashion, and it seemed particularly useful in their specific use case… It had essentially an rslider snapped to 0, any negative values would pull an LPF down from 20k or the ceiling, and positive values pull a HPF up from 20hz or the floor… releasing the knob returns it to 0, aka no filtering).

Could be done already coudln’t it? Give me a sec…

How about this:

<Cabbage>
form caption("dsfg") size(300, 100), colour(58, 110, 182), pluginID("def1")
rslider bounds(16, 20, 60, 60) range(100, 1000, 400, 1, 0.001), channel("slider")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1.0

instr 1
kMouseDown chnget "MOUSE_DOWN_LEFT"
kFreq init 400
if kMouseDown == 1 then
    kFreq = chnget:k("slider")
else
    chnset k(400), "slider"
    kFreq = 400
endif   

a1 oscili .5, kFreq
outs a1, a1
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

That’s great, thanks! It will definitely work for what I had in mind.

But csound code has no idea about the widget’s default value, which I do think would be really useful. It would also require different instruments (or at least calls with different p4s etc) to allow widgets that snap to different values. I just think it’d just be much simpler for end users if being added to large projects, imported widget groups, etc etc… Maybe I’m just big on feature creep :wink:

But yes, it’s by no means a priority since it’s pretty easy to workaround, and in my particular case it will probably be a straightforward use of it.

That’s a new phrase for me, but I reckon you’re already the master! :joy:

Speaking of feature creep… :innocent:

For portability and flexibility I turned this into a pair of UDOs that outputs either k or a rate values, and added an optional “hold” channel that can be used to turn off snapping on the fly. This can be used in place of a channel read to get a value, for example:
opcode SnapBack,k,iS iDefaultValue,SChanName xin kMouseDown chnget "MOUSE_DOWN_LEFT" kHold chnget strcat(SChanName,"hold") kValue init iDefaultValue if kMouseDown == 1 || kHold == 1 then kValue = chnget:k(SChanName) else chnset k(iDefaultValue), SChanName kValue = iDefaultValue endif xout kValue endop opcode SnapBack,a,iS iDefaultValue,SChanName xin kMouseDown chnget "MOUSE_DOWN_LEFT" kHold chnget strcat(SChanName,"hold") aValue init iDefaultValue if kMouseDown == 1 || kHold == 1 then aValue = chnget:a(SChanName) else chnset k(iDefaultValue), SChanName aValue = iDefaultValue endif xout aValue endop instr 1 kFlex SnapBack 0, "flex" printk2 kFlex endin
That will read the channel “flex” into a krate value named kFlex, snapping back to 0. Setting “flexhold” to 1 (via another widget or otherwise) would stop the snap back behavior.

Cool. I was also thinking one could use the port opcode to have it slide back instead of snap :wink:

So… oops. The a-rate version both doesn’t work, and shouldn’t be bothered to fix. It wouldn’t really make sense to use anyway I wouldn’t think. :blush:

Here’s a version that outputs nothing… useful if you want to set the snap completely independent of any actual channel reads…

opcode SnapBack,0,iS
  iDefaultValue,SChanName xin
  kMouseDown chnget "MOUSE_DOWN_LEFT"
  kHold chnget strcat(SChanName,"hold")
  if changed(kMouseDown,kHold)==1 && kMouseDown==0 && kHold==0 then
      chnset k(iDefaultValue), SChanName
  endif
endop

I was already considering port and how to integrate is as “optional”… I’m using this to control freq of two filters, as described before… and an immediate snap that large can create some distortions with certain filters. I’ll probably take a crack at that next.