Step Pad |
A step pad lets you step through the values of a parameter by click dragging vertically or horizontally with the mouse. This control behaves very similarly to a knob with the difference that the visual representation is like a button (held or released).
This view works for any parameter (both Vst and Jmb) that is (or can be interpreted as) a discrete parameter.
In addition to the attributes exposed by CustomDiscreteControlView
, this class exposes the following attributes:
Attribute | Description |
---|---|
step-increment |
Value by which this pad will increment (positive) or decrement (negative) the parameter. |
shift-step-increment |
Value by which this pad will increment (positive) or decrement (negative) the parameter when the shift key modifier is being held. This allows to have bigger steps (or smaller steps) when shift is used. |
drag-factor |
Defines how many pixels the mouse needs to move to go through the range of values. The bigger this number the “slower” the value will change. |
shift-drag-factor |
Defines how many pixels the mouse needs to move to go through the range of values when shift is being held. The bigger this number the “slower” the value will change. |
held-color |
Color to use when the pad is held and no image is provided (note that the “released” color is simply the back color). |
disabled-color |
When no image is provided and the control is disabled, this color is used instead. |
pad-image |
The image to use to draw the pad (2 or 3 frames). |
pad-image-has-disabled-state |
Flag to determine whether the image contains a disabled state (3 frames) or not (2 frames). |
inverse |
Inverses the meaning of “held” and “released” in regards to drawing the view/image. |
wrap |
Defines what happens when the value reaches its end of range after being incremented (resp. decremented). When set to true it will wrap around, otherwise it will remain at its max (resp. min) |
positive-direction |
Defines the direction (up, down, left or right) in which the mouse needs to be dragged in order to increase the value. The opposite direction will decrease. |
The image above shows an example of a vst parameter representing a number of slices which can vary between 1.0 and 64.0. A ParamDisplayView shows the actual number. Since a ParamDisplayView
does not do anything on its own, a StepPadView
is layered on top of it to add the click and drag behavior. The back-color
is set to fully transparent so that when not clicked, the ParamDisplayView
is shown, thus revealing the number of slices. The held-color
is set to a transparent shade of the green used by the LCD screen so that, a) you can still see the number below, and b) there is a visual feedback that something is happening when you click.
The json defining the display (number) and transparent pad (Source)
"jamba::ParamDisplay": {
"attributes": {
"back-color": "~ TransparentCColor",
"background-offset": "0, 0",
"class": "jamba::ParamDisplay",
"control-tag": "Param_NumSlices",
"default-value": "0.238095",
"editor-mode": "false",
"font": "~ NormalFontSmaller",
"font-antialias": "true",
"font-color": "LCD Foreground",
"frame-color": "~ TransparentCColor",
"frame-width": "1",
"max-value": "1",
"min-value": "0",
"mouse-enabled": "true",
"opacity": "1",
"origin": "533, 18",
"precision-override": "-1",
"round-rect-radius": "6",
"shadow-color": "~ TransparentCColor",
"size": "39, 18",
"style-3D-in": "false",
"style-3D-out": "false",
"style-no-draw": "false",
"style-no-frame": "false",
"style-no-text": "false",
"style-round-rect": "false",
"style-shadow-text": "false",
"text-alignment": "center",
"text-inset": "0, 0",
"text-rotation": "0",
"text-shadow-offset": "1, 1",
"transparent": "false",
"value-precision": "2",
"wants-focus": "false",
"wheel-inc-value": "0.1"
}
},
"jamba::StepPad": {
"attributes": {
"back-color": "~ TransparentCColor",
"class": "jamba::StepPad",
"control-tag": "Param_NumSlices",
"disabled-color": "Slice_Line_Color",
"drag-factor": "100",
"editor-mode": "false",
"held-color": "LCD Active",
"inverse": "false",
"mouse-enabled": "true",
"opacity": "1",
"origin": "531, 18",
"pad-image-has-disabled-state": "false",
"positive-direction": "up",
"shift-drag-factor": "10000",
"shift-step-increment": "1",
"size": "40, 18",
"step-count": "63000",
"step-increment": "125",
"transparent": "false",
"wants-focus": "false",
"wrap": "false"
}
},
origin
and size
overlapping).The vst param is defined this way (Source)
struct NumSlice
{
using real_type = double;
using int_type = int32;
NumSlice() = default;
explicit NumSlice(real_type iValue) : fRealValue{iValue}, fIntValue{static_cast<int_type>(std::ceil(iValue))} {}
constexpr explicit NumSlice(int_type iValue) : fRealValue{static_cast<real_type>(iValue)}, fIntValue{iValue} {}
constexpr real_type realValue() const { return fRealValue; }
constexpr int_type intValue() const { return fIntValue; }
private:
real_type fRealValue{};
int_type fIntValue{};
};
//------------------------------------------------------------------------
// NumSlicesParamConverter: Number of slices is between 1 and NUM_SLICES
// mapping [0.0, 1.0] to [1.0, NUM_SLICES]
//------------------------------------------------------------------------
class NumSlicesParamConverter : public IParamConverter<NumSlice>
{
public:
inline ParamValue normalize(ParamType const &iValue) const override
{
return Utils::mapValueDP(iValue.realValue(), 1, NUM_SLICES, 0.0, 1.0);
}
inline ParamType denormalize(ParamValue iNormalizedValue) const override
{
return NumSlice{Utils::mapValueDP(iNormalizedValue, 0.0, 1.0, 1.0, NUM_SLICES)};
}
inline void toString(ParamType const &iValue, String128 oString, int32 /* iPrecision */) const override
{
Steinberg::UString wrapper(oString, str16BufferSize (String128));
wrapper.printFloat(iValue.realValue(), 2);
}
};
The vst param is initialized this way (Source)
// the number of slices the sample will be split into
fNumSlices =
vst<NumSlicesParamConverter>(ESampleSplitterParamID::kNumSlices, STR16("Num Slices"))
.defaultValue(DEFAULT_NUM_SLICES)
.shortTitle(STR16("Slices"))
.add();