Make our own knob
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
570d8bc2da
commit
77ce5cc701
1 changed files with 182 additions and 1 deletions
|
|
@ -21,6 +21,187 @@
|
||||||
|
|
||||||
USE_NAMESPACE_DISTRHO;
|
USE_NAMESPACE_DISTRHO;
|
||||||
|
|
||||||
|
struct NanoKnob : Knob {
|
||||||
|
static const int ringSize = 4;
|
||||||
|
|
||||||
|
std::string displayLabel;
|
||||||
|
std::string displayString;
|
||||||
|
float normalizedValue = 0.0f;
|
||||||
|
|
||||||
|
NanoKnob()
|
||||||
|
{
|
||||||
|
box.size = Vec(100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawLayer(const DrawArgs& args, int layer) override
|
||||||
|
{
|
||||||
|
if (layer != 1)
|
||||||
|
return Knob::drawLayer(args, layer);
|
||||||
|
|
||||||
|
const float w = box.size.x;
|
||||||
|
const float h = box.size.y;
|
||||||
|
|
||||||
|
const int knobSize = std::min(w, h - BND_WIDGET_HEIGHT * 2) - ringSize;
|
||||||
|
|
||||||
|
const int knobStartX = w / 2 - knobSize / 2;
|
||||||
|
const int knobStartY = BND_WIDGET_HEIGHT + ringSize;
|
||||||
|
const int knobCenterX = knobStartX + knobSize / 2;
|
||||||
|
const int knobCenterY = knobStartY + knobSize / 2;
|
||||||
|
|
||||||
|
const NVGcolor testing = nvgRGBf(0.76f, 0.11f, 0.22f);
|
||||||
|
|
||||||
|
nvgLineCap(args.vg, NVG_ROUND);
|
||||||
|
|
||||||
|
// outer ring value
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgArc(args.vg,
|
||||||
|
knobCenterX,
|
||||||
|
knobCenterY,
|
||||||
|
knobSize / 2 + ringSize / 2 + 1,
|
||||||
|
nvgDegToRad(135.0f),
|
||||||
|
nvgDegToRad(135.0f) + nvgDegToRad(270.0f * normalizedValue),
|
||||||
|
NVG_CW);
|
||||||
|
nvgStrokeWidth(args.vg, ringSize);
|
||||||
|
nvgStrokeColor(args.vg, testing);
|
||||||
|
nvgStroke(args.vg);
|
||||||
|
|
||||||
|
// simulate color bleeding
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgArc(args.vg,
|
||||||
|
knobCenterX,
|
||||||
|
knobCenterY,
|
||||||
|
knobSize / 2 - 3,
|
||||||
|
nvgDegToRad(135.0f),
|
||||||
|
nvgDegToRad(135.0f) + nvgDegToRad(270.0f * normalizedValue),
|
||||||
|
NVG_CW);
|
||||||
|
nvgStrokeWidth(args.vg, 5);
|
||||||
|
nvgStrokeColor(args.vg, nvgRGBAf(testing.r, testing.g, testing.b, 0.1f));
|
||||||
|
nvgStroke(args.vg);
|
||||||
|
|
||||||
|
// adjusted from VCVRack's LightWidget.cpp
|
||||||
|
if (const float halo = settings::haloBrightness)
|
||||||
|
{
|
||||||
|
float radius = knobSize * 0.5f;
|
||||||
|
float oradius = radius + std::min(radius * 4.f, 15.f);
|
||||||
|
|
||||||
|
NVGcolor icol = color::mult(nvgRGBAf(testing.r, testing.g, testing.b, 0.2f), halo);
|
||||||
|
NVGcolor ocol = nvgRGBA(0, 0, 0, 0);
|
||||||
|
NVGpaint paint = nvgRadialGradient(args.vg, knobCenterX, knobCenterY, radius, oradius, icol, ocol);
|
||||||
|
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgRect(args.vg, knobCenterX - oradius, knobCenterY - oradius, 2 * oradius, 2 * oradius);
|
||||||
|
nvgFillPaint(args.vg, paint);
|
||||||
|
nvgFill(args.vg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom label (value)
|
||||||
|
bndIconLabelValue(args.vg, 0, BND_WIDGET_HEIGHT + knobSize + ringSize, w, BND_WIDGET_HEIGHT, -1,
|
||||||
|
testing, BND_CENTER,
|
||||||
|
BND_LABEL_FONT_SIZE, displayString.c_str(), nullptr);
|
||||||
|
|
||||||
|
Knob::drawLayer(args, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(const DrawArgs& args) override
|
||||||
|
{
|
||||||
|
if (engine::ParamQuantity* const pq = getParamQuantity())
|
||||||
|
normalizedValue = pq->getScaledValue();
|
||||||
|
|
||||||
|
const float w = box.size.x;
|
||||||
|
const float h = box.size.y;
|
||||||
|
|
||||||
|
const int knobSize = std::min(w, h - BND_WIDGET_HEIGHT * 2) - ringSize;
|
||||||
|
|
||||||
|
const int knobStartX = w / 2 - knobSize / 2;
|
||||||
|
const int knobStartY = BND_WIDGET_HEIGHT + ringSize;
|
||||||
|
const int knobCenterX = knobStartX + knobSize / 2;
|
||||||
|
const int knobCenterY = knobStartY + knobSize / 2;
|
||||||
|
|
||||||
|
// top label (name)
|
||||||
|
bndIconLabelValue(args.vg, 0, 0, w, BND_WIDGET_HEIGHT, -1,
|
||||||
|
SCHEME_WHITE, BND_CENTER,
|
||||||
|
BND_LABEL_FONT_SIZE, displayLabel.c_str(), nullptr);
|
||||||
|
|
||||||
|
// knob
|
||||||
|
NVGcolor shade_top;
|
||||||
|
NVGcolor shade_down;
|
||||||
|
BNDwidgetState state;
|
||||||
|
if (APP->event->getDraggedWidget() == this)
|
||||||
|
state = BND_ACTIVE;
|
||||||
|
else if (APP->event->getHoveredWidget() == this)
|
||||||
|
state = BND_HOVER;
|
||||||
|
else
|
||||||
|
state = BND_DEFAULT;
|
||||||
|
bndInnerColors(&shade_top, &shade_down, &bndGetTheme()->optionTheme, state, 0);
|
||||||
|
|
||||||
|
// inner fill
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgCircle(args.vg, knobCenterX, knobCenterY, knobSize / 2);
|
||||||
|
nvgFillPaint(args.vg, nvgLinearGradient(args.vg,
|
||||||
|
knobStartX,
|
||||||
|
knobStartY,
|
||||||
|
knobStartX,
|
||||||
|
knobStartY + knobSize,
|
||||||
|
shade_top,
|
||||||
|
shade_down));
|
||||||
|
nvgFill(args.vg);
|
||||||
|
|
||||||
|
// inner fill border (inner)
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgArc(args.vg, knobCenterX, knobCenterY, knobSize / 2 - 1, nvgDegToRad(0.0f), nvgDegToRad(360.0f), NVG_CCW);
|
||||||
|
nvgClosePath(args.vg);
|
||||||
|
nvgStrokeWidth(args.vg, 1);
|
||||||
|
nvgStrokeColor(args.vg, nvgRGBAf(0.5f, 0.5f, 0.5f, 0.4f));
|
||||||
|
nvgStroke(args.vg);
|
||||||
|
|
||||||
|
// inner fill border (outer)
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgArc(args.vg, knobCenterX, knobCenterY, knobSize / 2, nvgDegToRad(0.0f), nvgDegToRad(360.0f), NVG_CCW);
|
||||||
|
nvgClosePath(args.vg);
|
||||||
|
nvgStrokeWidth(args.vg, 1);
|
||||||
|
nvgStrokeColor(args.vg, nvgRGBAf(0.0f, 0.0f, 0.0f, 0.4f));
|
||||||
|
nvgStroke(args.vg);
|
||||||
|
|
||||||
|
nvgLineCap(args.vg, NVG_ROUND);
|
||||||
|
|
||||||
|
// line indicator
|
||||||
|
nvgStrokeWidth(args.vg, 2);
|
||||||
|
nvgSave(args.vg);
|
||||||
|
nvgTranslate(args.vg, knobCenterX, knobCenterY);
|
||||||
|
nvgRotate(args.vg, nvgDegToRad(45.0f) + normalizedValue * nvgDegToRad(270.0f));
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgRoundedRect(args.vg, -2, knobSize / 2 - 9, 2, 6, 1);
|
||||||
|
nvgClosePath(args.vg);
|
||||||
|
nvgFillColor(args.vg, nvgRGBf(1.0f, 1.0f, 1.0f));
|
||||||
|
nvgFill(args.vg);
|
||||||
|
nvgRestore(args.vg);
|
||||||
|
|
||||||
|
// outer ring background
|
||||||
|
nvgBeginPath(args.vg);
|
||||||
|
nvgArc(args.vg,
|
||||||
|
knobCenterX,
|
||||||
|
knobCenterY,
|
||||||
|
knobSize / 2 + ringSize / 2 + 1,
|
||||||
|
nvgDegToRad(135.0f),
|
||||||
|
nvgDegToRad(45.0f),
|
||||||
|
NVG_CW);
|
||||||
|
nvgStrokeWidth(args.vg, ringSize);
|
||||||
|
nvgStrokeColor(args.vg, nvgRGBf(0.5f, 0.5f, 0.5f));
|
||||||
|
nvgStroke(args.vg);
|
||||||
|
|
||||||
|
Knob::draw(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onChange(const ChangeEvent&) override
|
||||||
|
{
|
||||||
|
engine::ParamQuantity* const pq = getParamQuantity();
|
||||||
|
DISTRHO_SAFE_ASSERT_RETURN(pq != nullptr,);
|
||||||
|
|
||||||
|
displayLabel = pq->getLabel();
|
||||||
|
displayString = pq->getDisplayValueString() + pq->getUnit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<int numIO>
|
template<int numIO>
|
||||||
struct HostAudio : Module {
|
struct HostAudio : Module {
|
||||||
CardinalPluginContext* const pcontext;
|
CardinalPluginContext* const pcontext;
|
||||||
|
|
@ -155,7 +336,7 @@ struct HostAudioWidget : ModuleWidget {
|
||||||
|
|
||||||
if (numIO == 2)
|
if (numIO == 2)
|
||||||
{
|
{
|
||||||
addParam(createParamCentered<RoundLargeBlackKnob>(Vec(middleX, 290.0f), m, 0));
|
addParam(createParamCentered<NanoKnob>(Vec(middleX, 290.0f), m, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue