Does SetAnimationEndActionFunction work on IBSwitchControl?

I’m making a synth plugin by adapting from IPlugInstrument.

I want to keep the tempo sync function, but when I replace the IVSlideSwitchControl with a IBSwitchControl, SetAnimationEndActionFunction stops working.

In fact, I tried putting a breakpoint in the bool sync declaration (commented below) and even the breakpoint doesn’t work in my version.

Does SetAnimationEndActionFunction only work on some controls?

pGraphics->AttachControl(new IBKnobControl(500, 79, purpleBitmap, kParamLFORateHz), kNoTag, "LFO")->Hide(true);
    pGraphics->AttachControl(new IBKnobControl(500, 79, orangeBitmap, kParamLFORateTempo), kNoTag, "LFO")->DisablePrompt(false);
      // my version
    pGraphics->AttachControl(new IBSwitchControl(519., 189., pGraphics->LoadBitmap(BOOL_FN, 2), kParamLFORateMode), kNoTag, "LFO")->SetAnimationEndActionFunction([pGraphics](IControl* pControl) {
      bool sync = pControl->GetValue() > 0.5; //breakpoint here
      pGraphics->HideControl(kParamLFORateHz, !sync);
      pGraphics->HideControl(kParamLFORateTempo, sync);
      });
      // IPlugInstrument version
    pGraphics->AttachControl(new IVSlideSwitchControl(lfoPanel, kParamLFORateMode, "Sync", DEFAULT_STYLE, false), kNoTag, "LFO")->SetAnimationEndActionFunction([pGraphics](IControl* pControl) {
      bool sync = pControl->GetValue() > 0.5;
      pGraphics->HideControl(kParamLFORateHz, sync);
      pGraphics->HideControl(kParamLFORateTempo, !sync);
      });

Thanks for the help!

Welcome!

IBSwitchControl doesn’t have a constructor that takes an IActionFunction, but you can set one. If a control has an IActionFunction, that function is triggered when the control is SetDirty(true). For a control that you want to animate, you can make an IActionFunction that sets an IAnimationFunction. As long as the IControl::mAnimationFunc is not null, it will get triggered at the UI refresh. In your animation function, you check the progress of the animation and call IControl::OnEndAnimation() when it is > 1. If IControl::mEndAnimationActionFunc is set, then that IActionFunction is called.

These std::functions IActionFunction and IAnimationFunction which both have the same signature have been mainly designed for the IVControls, which have constructors that can take an action function, and the default action function is triggering the animation function. The aim being that you can create a custom animation behaviour with a tiny bit of code.

I’ll consider if IBSwitchControl needs an extra CTor, but for now, to animate an IBSwitchControl you could do something like this in your layout function…

IControl* pControl = nullptr;
  pGraphics->AttachControl(pControl = new IBSwitchControl(bounds, switchBitmap));
  pControl->SetActionFunction([](IControl* pCaller) {
    pCaller->SetValue(1.); // Set the control ON when clicked
    pCaller->SetAnimation([](IControl* pCaller){
      auto progress = pCaller->GetAnimationProgress();
      if(progress > 1.) {
        pCaller->OnEndAnimation(); // triggers IControl::mAnimationEndActionFunc
        return;
      }
    }, 500); // Animation duration of 500ms
  });
  pControl->SetAnimationEndActionFunction([](IControl* pCaller) {
    pCaller->SetValue(0.); // Set the control OFF when the animation function is cleared
  });
2 Likes

Thanks, it worked! I just had to remove the value setting functions because i want it to stay on or off, after clicking.

    IControl* pControl = nullptr;
    pGraphics->AttachControl(pControl = new IBSwitchControl(519., 189., pGraphics->LoadBitmap(BOOL_FN, 2), kParamLFORateMode));
    pControl->SetActionFunction([](IControl* pCaller) {
      pCaller->SetAnimation([](IControl* pCaller) {
        auto progress = pCaller->GetAnimationProgress();
        if (progress > 1.) {
          pCaller->OnEndAnimation(); // triggers IControl::mAnimationEndActionFunc
          return;
        }
        }, 500); // Animation duration of 500ms
      });
    pControl->SetAnimationEndActionFunction([pGraphics](IControl* pCaller) {
      bool sync = pCaller->GetValue();
      pGraphics->HideControl(kParamLFORateHz, sync);
      pGraphics->HideControl(kParamLFORateTempo, !sync);
      });