hide/show widgets live?

Hi,

on a OSC I’m making, I’ve a sort of “LFO Mode” switch, which will enable the user to use a different rate and some other settings.

Thus, on process(), due to the switch value, I’d like to access to the target widgets and hide/show them due to selection.

How can I access widget’s param due to paramId from process()? Or what’s the best way to do this?

Thanks

You should not modify the UI directly from DSP code.

However, you could modify the UI from UI code, based on a state controlled by the DSP code. Add a bool Module::lfoMode variable and set it from DSP code. Override ModuleWidget::step() and in it, call the superclass method and hide/show the desired ParamWidget based on the value of Module::lfoMode.

1 Like

It seems to works perfectly (if that’s what you meant):

void step() override {
	ModuleWidget::step();

	if (pModule != NULL) {
		if (mLFOMode != pModule->mLFOMode) {
			mLFOMode = pModule->mLFOMode;

			if (mLFOMode) {
				pKnobRateOsc->hide();
			} else {
				pKnobRateOsc->show();
			}
		}
	}
}
1 Like

Looks great. This would be a bit more elegant to me because it uses the “minimize state data” principle, but either works.

ModuleWidget::step();

MyModule* module = dynamic_cast<MyModule*>(this->module);
if (!module)
	return;

ParamWidget* myParam = getParam(MyModule::MY_PARAM);
if (module->lfoMode) {
	myParam->hide();
}
else {
	myParam->show();
}

I’m curious, I know we should not use dynamic_cast in DSP code. Even if the UI thread is not time critical doesn’t a dynamic_cast in step() still need more CPU cycles for every frame than accessing a pointer?

2 Likes

Depending on what you have in mind and their visual appearance, please note that it’s generally considered non-idiomatic to conceal UI widgets that appear to be physical elements, rather than drawn on an interactive display.

1 Like

You’re right that it shouldn’t be called in DSP code, but it should be fine in UI code. I can’t imagine it taking more than 100ns, and in this case it’s only called once every 1/60 seconds, so it’ll only contribute to 0.0005% CPU. If you’re nervous about using it, use reinterpret_cast, since that takes zero cycles and you know the derived type is a MyModule.

Also this. There are tons of disadvantages in automatically hiding widgets. I prefer my panels to not change, and I’m sure most users agree.

2 Likes

Thanks for clarifying, helpful as always :slightly_smiling_face:

Yes. In this case, its just a “trick” to change the scale of a knob. I mean: Osc mode => Rate 10-22khz, LFO mode => Rate 0.01-20hz.

Its not “changing”, just rescaling, using the hide/show trick.

Is there any other way? It seems the faster…

You shouldn’t ever change the range of the knob. Just change the base frequency of the oscillator, i.e. f_0 in https://vcvrack.com/manual/VoltageStandards#pitch-and-frequencies

What about the Widget tooltip? It should display the correct Hz value while dragging the knob :open_mouth:

Dynamically update displayBase in a custom ParamQuantity subclass.

1 Like

Curious: why this would be “idiomatic”? I could see the knob change position (due to different range). So basically, would be “unreal” in both case in a real-hardware scenario, isn’t?

Changing param ranges isn’t really supported by VCV. You shouldn’t rely on unsupported behavior. You also shouldn’t really be touching ParamQuantity with DSP code. It belongs more to the UI.

1 Like
  1. That question is off-topic in this thread. You need to start a new thread for each unrelated question.
  2. When copying samples of code, please specify the source of the code so people can understand the context of what you’re talking about.

I did. You can remove your last reply, to have a clean discussion :slight_smile: Thanks

is now on v2 possible to change param range? in my specific case, i need to change the hardness of a filter’s resonance, q.

this way (min, max) soft: std::log2(0.24f), std::log2(4.318f)

hard: std::log2(0.1f), std::log2(60.0f)

Why do you want to do this on the parameter level? Just let the parameter run from 0.0 to 1.0 (or any other meaningful range) and handle the different modes internally in the process routine.

2 Likes

so in this way i need to rewrite the display helpers. 0.1/1.0 to display its bad.

so in any way you need to insert non-native code…

Changing the configuration of the knob label (using the optional parameters of configParam) would be a lot less disruptive than actually changing the min and Max values.

You shouldn’t need any non-native code.

If you change the min and Max, its difficult to have a consistent behaviour for the knob when you change the range. The knob position might or might not shift. I’ve seen it done and the code is messy and unsatisfying.

Personally I’d keep a single range and just change the display rules, and the internal interpretation.

1 Like