beamgrid/Source/BeamgridLookAndFeel.h
2026-08-14 01:33:20 +02:00

60 lines
2.5 KiB
C++

#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));
}
};