beamgrid/Source/BeamgridLookAndFeel.h

69 lines
2.9 KiB
C
Raw Normal View History

#pragma once
#include "JuceHeader.h"
// Visual styling for BEAMGRID: black UI with teal accents. A single HUE knob
// rotates the hue of every saturated colour on the UI via a shared LookAndFeel.
class BeamgridLookAndFeel : public juce::LookAndFeel_V4
{
public:
BeamgridLookAndFeel()
{
setColour (juce::Slider::rotarySliderFillColourId, tealBase);
setColour (juce::Slider::rotarySliderOutlineColourId, juce::Colours::black.brighter (0.18f));
setColour (juce::Slider::textBoxTextColourId, juce::Colours::lightgrey);
setColour (juce::Slider::textBoxOutlineColourId, juce::Colours::transparentBlack);
setColour (juce::Label::textColourId, juce::Colours::lightgrey);
}
// Base palette (used at 12 o'clock / zero hue rotation).
static const juce::Colour tealBase;
static const juce::Colour peakBase;
// Hue rotation in turns (-0.5 .. +0.5); 0 = original colours.
float hueTurns = 0.0f;
void setHueTurns (float turns) noexcept { hueTurns = turns; }
juce::Colour transform (juce::Colour c) const noexcept
{
return c.withRotatedHue (hueTurns);
}
juce::Colour getTeal() const noexcept { return transform (tealBase); }
juce::Colour getPeak() const noexcept { return transform (peakBase); }
void drawRotarySlider (juce::Graphics& g, int x, int y, int w, int h,
float pos, float startAngle, float endAngle,
juce::Slider& slider) override
{
const auto bounds = juce::Rectangle<int> (x, y, w, h).toFloat().reduced (6.0f);
const auto centre = bounds.getCentre();
const auto radius = juce::jmin (bounds.getWidth(), bounds.getHeight()) * 0.5f;
const float thickness = 5.0f;
// Background track arc.
juce::Path track;
track.addArc (centre.x - radius, centre.y - radius, radius * 2.0f, radius * 2.0f,
startAngle, endAngle, thickness);
g.setColour (slider.findColour (juce::Slider::rotarySliderOutlineColourId));
g.strokePath (track, juce::PathStrokeType (thickness));
// Filled value arc (teal, hue-rotated).
const float angle = startAngle + pos * (endAngle - startAngle);
juce::Path value;
value.addArc (centre.x - radius, centre.y - radius, radius * 2.0f, radius * 2.0f,
startAngle, angle, thickness);
g.setColour (getTeal());
g.strokePath (value, juce::PathStrokeType (thickness));
// Pointer line.
juce::Path pointer;
const float pointerLen = radius * 0.78f;
pointer.addLineSegment (juce::Line<float> (centre.x, centre.y,
centre.x + std::sin (angle) * pointerLen,
centre.y - std::cos (angle) * pointerLen), 2.0f);
g.setColour (juce::Colours::white);
g.strokePath (pointer, juce::PathStrokeType (2.5f));
}
};