Vital
Loading...
Searching...
No Matches
synth_section.cpp
Go to the documentation of this file.
1#include "synth_section.h"
2
3#include "skin.h"
4#include "fonts.h"
5#include "full_interface.h"
6#include "modulation_button.h"
7#include "open_gl_component.h"
9#include "synth_slider.h"
10
11SynthSection::SynthSection(const String& name) : Component(name), parent_(nullptr), activator_(nullptr),
12 preset_selector_(nullptr), preset_selector_half_width_(false),
13 skin_override_(Skin::kNone), size_ratio_(1.0f),
14 active_(true), sideways_heading_(true) {
15 setWantsKeyboardFocus(true);
16}
17
19 if (value_lookup_.count(value_id)) {
20 if (Skin::shouldScaleValue(value_id))
21 return size_ratio_ * value_lookup_.at(value_id);
22 return value_lookup_.at(value_id);
23 }
24 if (parent_)
25 return parent_->findValue(value_id);
26
27 return 0.0f;
28}
29
31 for (auto& sub_section : sub_sections_)
32 sub_section->reset();
33}
34
36 Component::resized();
37 if (off_overlay_) {
38 off_overlay_->setBounds(getLocalBounds());
39 off_overlay_->setColor(findColour(Skin::kBackground, true).withMultipliedAlpha(0.8f));
40 }
41 if (activator_)
42 activator_->setBounds(getPowerButtonBounds());
43 if (preset_selector_) {
46 }
47}
48
49void SynthSection::paint(Graphics& g) { }
50
52 int title_width = findValue(Skin::kTitleWidth);
53 g.setColour(findColour(Skin::kHeadingText, true));
54 g.setFont(Fonts::instance()->proportional_light().withPointHeight(size_ratio_ * 14.0f));
55 g.saveState();
56 g.setOrigin(Point<int>(0, getHeight()));
57 g.addTransform(AffineTransform::rotation(-vital::kPi / 2.0f));
58 int height = getHeight();
59 if (activator_)
60 height = getHeight() - title_width / 2;
61
62 g.drawText(getName(), Rectangle<int>(0, 0, height, title_width), Justification::centred, false);
63 g.restoreState();
64}
65
69 return;
70 }
71
72 g.setColour(findColour(Skin::kHeadingText, true));
73 g.setFont(Fonts::instance()->proportional_light().withPointHeight(size_ratio_ * 14.0f));
74 g.drawText(TRANS(getName()), getTitleBounds(), Justification::centred, false);
75}
76
85
86void SynthSection::setSkinValues(const Skin& skin, bool top_level) {
87 skin.setComponentColors(this, skin_override_, top_level);
88 skin.setComponentValues(this, skin_override_, top_level);
89 for (auto& sub_section : sub_sections_)
90 sub_section->setSkinValues(skin, false);
91
92 for (auto& open_gl_component : open_gl_components_)
93 open_gl_component->setSkinValues(skin);
94}
95
97 if (!isShowing())
98 return;
99
100 FullInterface* parent = findParentComponentOfClass<FullInterface>();
101 if (parent)
102 parent->repaintChildBackground(this);
103}
104
105void SynthSection::showPopupBrowser(SynthSection* owner, Rectangle<int> bounds, std::vector<File> directories,
106 String extensions, std::string passthrough_name,
107 std::string additional_folders_name) {
108 FullInterface* parent = findParentComponentOfClass<FullInterface>();
109 if (parent)
110 parent->popupBrowser(owner, bounds, directories, extensions, passthrough_name, additional_folders_name);
111}
112
114 FullInterface* parent = findParentComponentOfClass<FullInterface>();
115 if (parent)
116 parent->popupBrowserUpdate(owner);
117}
118
119void SynthSection::showPopupSelector(Component* source, Point<int> position, const PopupItems& options,
120 std::function<void(int)> callback, std::function<void()> cancel) {
121 FullInterface* parent = findParentComponentOfClass<FullInterface>();
122 if (parent)
123 parent->popupSelector(source, position, options, callback, cancel);
124}
125
126void SynthSection::showDualPopupSelector(Component* source, Point<int> position, int width,
127 const PopupItems& options, std::function<void(int)> callback) {
128 FullInterface* parent = findParentComponentOfClass<FullInterface>();
129 if (parent)
130 parent->dualPopupSelector(source, position, width, options, callback);
131}
132
133void SynthSection::showPopupDisplay(Component* source, const std::string& text,
134 BubbleComponent::BubblePlacement placement, bool primary) {
135 FullInterface* parent = findParentComponentOfClass<FullInterface>();
136 if (parent)
137 parent->popupDisplay(source, text, placement, primary);
138}
139
141 FullInterface* parent = findParentComponentOfClass<FullInterface>();
142 if (parent)
143 parent->hideDisplay(primary);
144}
145
147 paintBody(g);
148
149 g.saveState();
150 if (sideways_heading_) {
151 int title_width = findValue(Skin::kTitleWidth);
152 g.reduceClipRegion(0, 0, title_width, getHeight());
153 g.setColour(findColour(Skin::kBodyHeading, true));
154 g.fillRoundedRectangle(0, 0, title_width * 2, getHeight(), findValue(Skin::kBodyRounding));
155 }
156 else {
157 g.reduceClipRegion(0, 0, getWidth(), getTitleWidth());
158 g.setColour(findColour(Skin::kBodyHeading, true));
159 g.fillRoundedRectangle(0, 0, getWidth(), getHeight(), findValue(Skin::kBodyRounding));
160 }
161
162 g.restoreState();
163}
164
165void SynthSection::paintBody(Graphics& g, Rectangle<int> bounds) {
166 g.setColour(findColour(Skin::kBody, true));
167 g.fillRoundedRectangle(bounds.toFloat(), findValue(Skin::kBodyRounding));
168}
169
170void SynthSection::paintBorder(Graphics& g, Rectangle<int> bounds) {
171 int body_rounding = findValue(Skin::kBodyRounding);
172 g.setColour(findColour(Skin::kBorder, true));
173 g.drawRoundedRectangle(bounds.toFloat().reduced(0.5f), body_rounding, 1.0f);
174}
175
176void SynthSection::paintBody(Graphics& g) {
177 paintBody(g, getLocalBounds());
178}
179
180void SynthSection::paintBorder(Graphics& g) {
181 paintBorder(g, getLocalBounds());
182}
183
185 return std::round(size_ratio_ * 2.0f);
186}
187
189 paintTabShadow(g, getLocalBounds());
190}
191
192void SynthSection::paintTabShadow(Graphics& g, Rectangle<int> bounds) {
193 static constexpr float kCornerScale = 0.70710678119f;
194 int corner_size = findValue(Skin::kBodyRounding);
195 int shadow_size = getComponentShadowWidth();
196 int corner_and_shadow = corner_size + shadow_size;
197
198 float corner_shadow_offset = corner_size - corner_and_shadow * kCornerScale;
199 float corner_ratio = corner_size * 1.0f / corner_and_shadow;
200
201 Colour shadow_color = findColour(Skin::kShadow, true);
202 Colour transparent = shadow_color.withAlpha(0.0f);
203
204 int left = bounds.getX();
205 int top = bounds.getY();
206 int right = bounds.getRight();
207 int bottom = bounds.getBottom();
208
209 g.setGradientFill(ColourGradient(shadow_color, left, 0, transparent, left - shadow_size, 0, false));
210 g.fillRect(left - shadow_size, top + corner_size, shadow_size, bottom - top - corner_size * 2);
211
212 g.setGradientFill(ColourGradient(shadow_color, right, 0, transparent, right + shadow_size, 0, false));
213 g.fillRect(right, top + corner_size, shadow_size, bottom - top - corner_size * 2);
214
215 g.setGradientFill(ColourGradient(shadow_color, 0, top, transparent, 0, top - shadow_size, false));
216 g.fillRect(left + corner_size, top - shadow_size, right - left - corner_size * 2, shadow_size);
217
218 g.setGradientFill(ColourGradient(shadow_color, 0, bottom, transparent, 0, bottom + shadow_size, false));
219 g.fillRect(left + corner_size, bottom, right - left - corner_size * 2, shadow_size);
220
221 ColourGradient top_left_corner(shadow_color, left + corner_size, top + corner_size,
222 transparent, left + corner_shadow_offset, top + corner_shadow_offset, true);
223 top_left_corner.addColour(corner_ratio, shadow_color);
224 g.setGradientFill(top_left_corner);
225 g.fillRect(left - shadow_size, top - shadow_size, corner_and_shadow, corner_and_shadow);
226
227 ColourGradient top_right_corner(shadow_color, right - corner_size, top + corner_size,
228 transparent, right - corner_shadow_offset, top + corner_shadow_offset, true);
229 top_right_corner.addColour(corner_ratio, shadow_color);
230 g.setGradientFill(top_right_corner);
231 g.fillRect(right - corner_size, top - shadow_size, corner_and_shadow, corner_and_shadow);
232
233 ColourGradient bottom_left_corner(shadow_color, left + corner_size, bottom - corner_size,
234 transparent, left + corner_shadow_offset, bottom - corner_shadow_offset, true);
235 bottom_left_corner.addColour(corner_ratio, shadow_color);
236 g.setGradientFill(bottom_left_corner);
237 g.fillRect(left - shadow_size, bottom - corner_size, corner_and_shadow, corner_and_shadow);
238
239 ColourGradient bottom_right_corner(shadow_color, right - corner_size, bottom - corner_size,
240 transparent, right - corner_shadow_offset, bottom - corner_shadow_offset, true);
241 bottom_right_corner.addColour(corner_ratio, shadow_color);
242 g.setGradientFill(bottom_right_corner);
243 g.fillRect(right - corner_size, bottom - corner_size, corner_and_shadow, corner_and_shadow);
244}
245
246void SynthSection::setSizeRatio(float ratio) {
247 size_ratio_ = ratio;
248
249 for (auto& sub_section : sub_sections_)
250 sub_section->setSizeRatio(ratio);
251}
252
254 for (auto& slider : slider_lookup_) {
255 if (slider.second->isVisible() && slider.second->getWidth() && slider.second->getHeight())
256 slider.second->drawShadow(g);
257 }
258}
259
261 for (auto& sub_section : sub_sections_) {
262 if (sub_section->isVisible())
263 paintChildShadow(g, sub_section);
264 }
265}
266
268 for (auto& open_gl_component : open_gl_components_) {
269 if (open_gl_component->isVisible())
270 paintOpenGlBackground(g, open_gl_component);
271 }
272}
273
275 for (auto& sub_section : sub_sections_) {
276 if (sub_section->isVisible())
277 paintChildBackground(g, sub_section);
278 }
279
281
282 if (preset_selector_) {
283 g.saveState();
284 Rectangle<int> bounds = getLocalArea(preset_selector_, preset_selector_->getLocalBounds());
285 g.reduceClipRegion(bounds);
286 g.setOrigin(bounds.getTopLeft());
288 g.restoreState();
289 }
290}
291
293 g.saveState();
294 Rectangle<int> bounds = getLocalArea(child, child->getLocalBounds());
295 g.reduceClipRegion(bounds);
296 g.setOrigin(bounds.getTopLeft());
297 child->paintBackground(g);
298 g.restoreState();
299}
300
302 g.saveState();
303 Rectangle<int> bounds = getLocalArea(child, child->getLocalBounds());
304 g.setOrigin(bounds.getTopLeft());
305 child->paintBackgroundShadow(g);
306 child->paintChildrenShadows(g);
307 g.restoreState();
308}
309
310void SynthSection::paintOpenGlBackground(Graphics &g, OpenGlComponent* open_gl_component) {
311 g.saveState();
312 Rectangle<int> bounds = getLocalArea(open_gl_component, open_gl_component->getLocalBounds());
313 g.reduceClipRegion(bounds);
314 g.setOrigin(bounds.getTopLeft());
315 open_gl_component->paintBackground(g);
316 g.restoreState();
317}
318
319void SynthSection::drawTextComponentBackground(Graphics& g, Rectangle<int> bounds, bool extend_to_label) {
320 if (bounds.getWidth() <= 0 || bounds.getHeight() <= 0)
321 return;
322
323 g.setColour(findColour(Skin::kTextComponentBackground, true));
324 int y = bounds.getY();
325 int rounding = bounds.getHeight() / 2;
326
327 if (extend_to_label) {
328 int label_bottom = bounds.getBottom() + findValue(Skin::kTextComponentLabelOffset);
330 g.fillRoundedRectangle(bounds.toFloat(), rounding);
331
332 int extend_y = y + bounds.getHeight() / 2;
333 g.fillRect(bounds.getX(), extend_y, bounds.getWidth(), label_bottom - extend_y - rounding);
334 }
335 else
336 g.fillRoundedRectangle(bounds.toFloat(), rounding);
337}
338
339void SynthSection::drawTempoDivider(Graphics& g, Component* sync) {
340 static constexpr float kLineRatio = 0.5f;
341
342 g.setColour(findColour(Skin::kLightenScreen, true));
343 int height = sync->getHeight();
344 int line_height = height * kLineRatio;
345 int y = sync->getY() + (height - line_height) / 2;
346 g.drawRect(sync->getX(), y, 1, line_height);
347}
348
350 for (auto& open_gl_component : open_gl_components_)
351 open_gl_component->init(open_gl);
352
353 for (auto& sub_section : sub_sections_)
354 sub_section->initOpenGlComponents(open_gl);
355}
356
358 for (auto& sub_section : sub_sections_) {
359 if (sub_section->isVisible() && !sub_section->isAlwaysOnTop())
360 sub_section->renderOpenGlComponents(open_gl, animate);
361 }
362
363 for (auto& open_gl_component : open_gl_components_) {
364 if (open_gl_component->isVisible() && !open_gl_component->isAlwaysOnTop()) {
365 open_gl_component->render(open_gl, animate);
366 VITAL_ASSERT(glGetError() == GL_NO_ERROR);
367 }
368 }
369
370 for (auto& sub_section : sub_sections_) {
371 if (sub_section->isVisible() && sub_section->isAlwaysOnTop())
372 sub_section->renderOpenGlComponents(open_gl, animate);
373 }
374
375 for (auto& open_gl_component : open_gl_components_) {
376 if (open_gl_component->isVisible() && open_gl_component->isAlwaysOnTop()) {
377 open_gl_component->render(open_gl, animate);
378 VITAL_ASSERT(glGetError() == GL_NO_ERROR);
379 }
380 }
381}
382
384 for (auto& open_gl_component : open_gl_components_)
385 open_gl_component->destroy(open_gl);
386
387 for (auto& sub_section : sub_sections_)
388 sub_section->destroyOpenGlComponents(open_gl);
389}
390
391void SynthSection::sliderValueChanged(Slider* moved_slider) {
392 std::string name = moved_slider->getName().toStdString();
393 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
394 if (parent)
395 parent->getSynth()->valueChangedInternal(name, moved_slider->getValue());
396}
397
398void SynthSection::buttonClicked(juce::Button *clicked_button) {
399 std::string name = clicked_button->getName().toStdString();
400 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
401 if (parent)
402 parent->getSynth()->valueChangedInternal(name, clicked_button->getToggleState() ? 1.0 : 0.0);
403}
404
406 if (button == activator_)
407 setActive(activator_->getToggleStateValue().getValue());
408}
409
411 vital::ValueDetails hz_details = *slider->getDisplayDetails();
413 hz_details.post_offset = 0.0f;
414 hz_details.display_units = " Hz";
416 slider->setAlternateDisplay(Skin::kFrequencyDisplay, 1.0f, hz_details);
417 slider->setDisplayExponentialBase(pow(2.0f, 1.0f / 12.0f));
418}
419
420void SynthSection::addToggleButton(ToggleButton* button, bool show) {
421 button_lookup_[button->getName().toStdString()] = button;
422 all_buttons_[button->getName().toStdString()] = button;
423 button->addListener(this);
424 if (show)
425 addAndMakeVisible(button);
426}
427
429 addToggleButton(button, show);
431}
432
434 addToggleButton(button, show);
436}
437
439 modulation_buttons_[button->getName().toStdString()] = button;
440 all_modulation_buttons_[button->getName().toStdString()] = button;
441 if (show)
442 addOpenGlComponent(button);
443}
444
445void SynthSection::addSlider(SynthSlider* slider, bool show, bool listen) {
446 slider_lookup_[slider->getName().toStdString()] = slider;
447 all_sliders_[slider->getName().toStdString()] = slider;
448 if (listen)
449 slider->addListener(this);
450 if (show)
451 addAndMakeVisible(slider);
455}
456
457void SynthSection::addSubSection(SynthSection* sub_section, bool show) {
458 sub_section->setParent(this);
459
460 if (show)
461 addAndMakeVisible(sub_section);
462
463 sub_sections_.push_back(sub_section);
464
465 std::map<std::string, SynthSlider*> sub_sliders = sub_section->getAllSliders();
466 all_sliders_.insert(sub_sliders.begin(), sub_sliders.end());
467
468 std::map<std::string, ToggleButton*> sub_buttons = sub_section->getAllButtons();
469 all_buttons_.insert(sub_buttons.begin(), sub_buttons.end());
470
471 std::map<std::string, ModulationButton*> sub_mod_buttons = sub_section->getAllModulationButtons();
472 all_modulation_buttons_.insert(sub_mod_buttons.begin(), sub_mod_buttons.end());
473}
474
476 auto location = std::find(sub_sections_.begin(), sub_sections_.end(), section);
477 if (location != sub_sections_.end())
478 sub_sections_.erase(location);
479}
480
482 for (auto& slider : slider_lookup_)
483 slider.second->setScrollEnabled(enabled);
484
485 for (auto& sub_section : sub_sections_)
486 sub_section->setScrollWheelEnabled(enabled);
487}
488
489void SynthSection::addOpenGlComponent(OpenGlComponent* open_gl_component, bool to_beginning) {
490 if (open_gl_component == nullptr)
491 return;
492
494 open_gl_component) == open_gl_components_.end());
495
496 open_gl_component->setParent(this);
497 if (to_beginning)
498 open_gl_components_.insert(open_gl_components_.begin(), open_gl_component);
499 else
500 open_gl_components_.push_back(open_gl_component);
501 addAndMakeVisible(open_gl_component);
502}
503
506
508 activator->setPowerButton();
509 activator_->getGlComponent()->setAlwaysOnTop(true);
510 activator->addButtonListener(this);
511 setActive(activator_->getToggleStateValue().getValue());
512}
513
515 if (off_overlay_)
516 return;
517
518 off_overlay_ = std::make_unique<OffOverlay>();
519 addOpenGlComponent(off_overlay_.get(), true);
520 off_overlay_->setVisible(false);
521 off_overlay_->setAlwaysOnTop(true);
522 off_overlay_->setInterceptsMouseClicks(false, false);
523}
524
525void SynthSection::paintJointControlSliderBackground(Graphics& g, int x, int y, int width, int height) {
527 g.setColour(findColour(Skin::kTextComponentBackground, true));
528 int widget_margin = findValue(Skin::kWidgetMargin);
529 int width1 = width / 2;
530 int width1_half = width1 / 2;
531
532 g.fillRoundedRectangle(x, y, width1, height, rounding);
533 g.fillRect(x + width1 - width1_half, y, width1_half, height);
534
535 g.fillRoundedRectangle(x + width1, y, width1, height, rounding);
536 g.fillRect(x + width1, y, width1_half, height);
537
538 g.setColour(findColour(Skin::kLightenScreen, true));
539 g.fillRect(x + width1, y + widget_margin, 1, height - 2 * widget_margin);
540}
541
542void SynthSection::paintJointControlBackground(Graphics& g, int x, int y, int width, int height) {
544 g.setColour(findColour(Skin::kLabelBackground, true));
545 g.fillRect(x + rounding, y * 1.0f, width - 2.0f * rounding, height / 2.0f);
546
547 int label_height = findValue(Skin::kLabelBackgroundHeight);
548 int half_label_height = label_height / 2;
549 int side_width = height;
550 g.setColour(findColour(Skin::kTextComponentBackground, true));
551 g.fillRoundedRectangle(x, y + half_label_height, width, height - half_label_height, rounding);
552 g.fillRoundedRectangle(x, y, side_width, height, rounding);
553 g.fillRoundedRectangle(x + width - side_width, y, side_width, height, rounding);
554
555 Colour label_color = findColour(Skin::kLabelBackground, true);
556 if (label_color.getAlpha() == 0)
557 label_color = findColour(Skin::kBody, true);
558 g.setColour(label_color);
559 int rect_width = std::max(width - 2 * side_width, 0);
560 g.fillRect(x + side_width, y, rect_width, half_label_height);
561 g.fillRoundedRectangle(x + side_width, y, rect_width, label_height, rounding);
562}
563
564void SynthSection::paintJointControl(Graphics& g, int x, int y, int width, int height, const std::string& name) {
565 paintJointControlBackground(g, x, y, width, height);
566
567 setLabelFont(g);
568 g.setColour(findColour(Skin::kBodyText, true));
569 g.drawText(name, x, y, width, findValue(Skin::kLabelBackgroundHeight), Justification::centred, false);
570}
571
572void SynthSection::placeJointControls(int x, int y, int width, int height,
573 SynthSlider* left, SynthSlider* right, Component* widget) {
574 int width_control = height;
575 left->setBounds(x, y, width_control, height);
576
577 if (widget) {
578 int label_height = findValue(Skin::kLabelBackgroundHeight);
579 widget->setBounds(x + width_control, y + label_height, width - 2 * width_control, height - label_height);
580 }
581 right->setBounds(x + width - width_control, y, width_control, height);
582}
583
584void SynthSection::placeTempoControls(int x, int y, int width, int height, SynthSlider* tempo, SynthSlider* sync) {
585 static constexpr float kMaxSyncWidthRatio = 0.35f;
586 int sync_width = std::min(width * kMaxSyncWidthRatio, findValue(Skin::kTextComponentHeight));
587 int sync_y = y + (height - sync_width) / 2.0f + findValue(Skin::kTextComponentOffset);
588 sync->setBounds(x + width - sync_width, sync_y, sync_width, sync_width);
589 tempo->setBounds(x, y, width - sync_width, height);
590 tempo->setModulationArea(Rectangle<int>(0, sync_y - y, tempo->getWidth(), sync_width));
591}
592
593void SynthSection::placeRotaryOption(Component* option, SynthSlider* rotary) {
595 int offset_x = findValue(Skin::kRotaryOptionXOffset) - width / 2;
596 int offset_y = findValue(Skin::kRotaryOptionYOffset) - width / 2;
597 Point<int> point = rotary->getBounds().getCentre() + Point<int>(offset_x, offset_y);
598 option->setBounds(point.x, point.y, width, width);
599}
600
601void SynthSection::placeKnobsInArea(Rectangle<int> area, std::vector<Component*> knobs) {
602 int widget_margin = findValue(Skin::kWidgetMargin);
603 float component_width = (area.getWidth() - (knobs.size() + 1) * widget_margin) / (1.0f * knobs.size());
604
605 int y = area.getY();
606 int height = area.getHeight() - widget_margin;
607 float x = area.getX() + widget_margin;
608 for (Component* knob : knobs) {
609 int left = std::round(x);
610 int right = std::round(x + component_width);
611 if (knob)
612 knob->setBounds(left, y, right - left, height);
613 x += component_width + widget_margin;
614 }
615}
616
618 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
619 if (parent)
620 parent->getSynth()->getCriticalSection().enter();
621}
622
624 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
625 if (parent)
626 parent->getSynth()->getCriticalSection().exit();
627}
628
632
636
640
642 int total_width = getSliderWidth();
643 int extra = total_width % 2;
644 int slider_width = std::floor(SynthSlider::kLinearWidthPercent * total_width * 0.5f) * 2.0f + extra;
645 return (total_width - slider_width) / 2;
646}
647
651
655
659
663
667
671
675
679
683
685 static constexpr float kXPercent = 0.4f;
686 int title_width = getTitleWidth();
687 int widget_margin = getWidgetMargin();
688 int width = getWidth();
689 int x = width * kXPercent;
691 x = width * 0.7f + findValue(Skin::kWidgetMargin);
692 return Rectangle<int>(x, widget_margin, width - x - widget_margin, title_width - 2 * widget_margin);
693}
694
696 if (preset_selector_ == nullptr)
697 return getWidth();
698
700 return getWidth() * 0.2f;
701 return getPresetBrowserBounds().getX();
702}
703
705 int title_width = getTitleWidth();
706 return Rectangle<int>(getPowerButtonOffset(), 0, title_width, title_width);
707}
708
710 int title_width = getTitleWidth();
711 int from = 0;
712 if (activator_)
713 from = getPowerButtonBounds().getRight() - title_width * kPowerButtonPaddingPercent;
714
715 int to = getTitleTextRight();
716 return Rectangle<int>(from, 0, to - from, title_width);
717}
718
720 if (getWidth() <= 0)
721 return 1.0f;
722
723 Component* top_level = getTopLevelComponent();
724 Rectangle<int> global_bounds = top_level->getLocalArea(this, getLocalBounds());
725 float display_scale = Desktop::getInstance().getDisplays().getDisplayForRect(top_level->getScreenBounds())->scale;
726 return display_scale * (1.0f * global_bounds.getWidth()) / getWidth();
727}
728
730 if (parent_)
731 return parent_->getPixelMultiple();
732 return 1.0f;
733}
734
736 float height = findValue(Skin::kLabelHeight);
737 return Fonts::instance()->proportional_regular().withPointHeight(height);
738}
739
740void SynthSection::setLabelFont(Graphics& g) {
741 g.setColour(findColour(Skin::kBodyText, true));
742 g.setFont(getLabelFont());
743}
744
745void SynthSection::drawLabelConnectionForComponents(Graphics& g, Component* left, Component* right) {
746 int label_offset = findValue(Skin::kLabelOffset);
747 int background_height = findValue(Skin::kLabelBackgroundHeight);
748 g.setColour(findColour(Skin::kLabelConnection, true));
749 int background_y = left->getBounds().getBottom() - background_height + label_offset;
750
751 int rect_width = right->getBounds().getCentreX() - left->getBounds().getCentreX();
752 g.fillRect(left->getBounds().getCentreX(), background_y, rect_width, background_height);
753}
754
755void SynthSection::drawLabelBackground(Graphics& g, Rectangle<int> bounds, bool text_component) {
756 int background_rounding = findValue(Skin::kLabelBackgroundRounding);
757 g.setColour(findColour(Skin::kLabelBackground, true));
758 Rectangle<float> label_bounds = getLabelBackgroundBounds(bounds, text_component).toFloat();
759 g.fillRoundedRectangle(label_bounds, background_rounding);
760 if (text_component && !findColour(Skin::kTextComponentBackground, true).isTransparent())
761 g.fillRect(label_bounds.withHeight(label_bounds.getHeight() / 2));
762}
763
764void SynthSection::drawLabelBackgroundForComponent(Graphics& g, Component* component) {
765 drawLabelBackground(g, component->getBounds());
766}
767
768Rectangle<int> SynthSection::getDividedAreaUnbuffered(Rectangle<int> full_area, int num_sections,
769 int section, int buffer) {
770 float component_width = (full_area.getWidth() - (num_sections + 1) * buffer) / (1.0f * num_sections);
771 int x = full_area.getX() + std::round(section * (component_width + buffer) + buffer);
772 int right = full_area.getX() + std::round((section + 1.0f) * (component_width + buffer));
773 return Rectangle<int>(x, full_area.getY(), right - x, full_area.getHeight());
774}
775
776Rectangle<int> SynthSection::getDividedAreaBuffered(Rectangle<int> full_area, int num_sections,
777 int section, int buffer) {
778 Rectangle<int> area = getDividedAreaUnbuffered(full_area, num_sections, section, buffer);
779 return area.expanded(buffer, 0);
780}
781
782Rectangle<int> SynthSection::getLabelBackgroundBounds(Rectangle<int> bounds, bool text_component) {
783 int background_height = findValue(Skin::kLabelBackgroundHeight);
784 int label_offset = text_component ? findValue(Skin::kTextComponentLabelOffset) : findValue(Skin::kLabelOffset);
785 int background_y = bounds.getBottom() - background_height + label_offset;
786 return Rectangle<int>(bounds.getX(), background_y, bounds.getWidth(), background_height);
787}
788
789void SynthSection::drawLabel(Graphics& g, String text, Rectangle<int> component_bounds, bool text_component) {
790 if (component_bounds.getWidth() <= 0 || component_bounds.getHeight() <= 0)
791 return;
792
793 drawLabelBackground(g, component_bounds, text_component);
794 g.setColour(findColour(Skin::kBodyText, true));
795 Rectangle<int> background_bounds = getLabelBackgroundBounds(component_bounds, text_component);
796 g.drawText(text, component_bounds.getX(), background_bounds.getY(),
797 component_bounds.getWidth(), background_bounds.getHeight(), Justification::centred, false);
798}
799
800void SynthSection::drawTextBelowComponent(Graphics& g, String text, Component* component, int space, int padding) {
802 g.drawText(text, component->getX() - padding, component->getBottom() + space,
803 component->getWidth() + 2 * padding, height, Justification::centred, false);
804}
805
806void SynthSection::setActive(bool active) {
807 if (active_ == active)
808 return;
809
810 if (off_overlay_)
811 off_overlay_->setVisible(!active);
812
813 active_ = active;
814 for (auto& slider : slider_lookup_)
815 slider.second->setActive(active);
816 for (auto& sub_section : sub_sections_)
817 sub_section->setActive(active);
818
820}
821
822void SynthSection::animate(bool animate) {
823 for (auto& sub_section : sub_sections_)
824 sub_section->animate(animate);
825}
826
828 for (auto& slider : all_sliders_) {
829 if (controls.count(slider.first)) {
830 slider.second->setValue(controls[slider.first]->value(), NotificationType::dontSendNotification);
831 slider.second->valueChanged();
832 }
833 }
834
835 for (auto& button : all_buttons_) {
836 if (controls.count(button.first)) {
837 bool toggle = controls[button.first]->value();
838 button.second->setToggleState(toggle, NotificationType::sendNotificationSync);
839 }
840 }
841
842 for (auto& sub_section : sub_sections_)
843 sub_section->setAllValues(controls);
844}
845
846void SynthSection::setValue(const std::string& name, vital::mono_float value, NotificationType notification) {
847 if (all_sliders_.count(name)) {
848 all_sliders_[name]->setValue(value, notification);
849 if (notification == dontSendNotification)
850 all_sliders_[name]->redoImage();
851 all_sliders_[name]->notifyGuis();
852 }
853 if (all_buttons_.count(name))
854 all_buttons_[name]->setToggleState(value, notification);
855}
Font & proportional_regular()
Returns a reference to the proportional regular font.
Definition fonts.h:22
static Fonts * instance()
Gets the singleton instance of the Fonts class.
Definition fonts.h:52
The main GUI container for the entire synthesizer interface.
Definition full_interface.h:61
void hideDisplay(bool primary)
Hides a previously shown popup display.
Definition full_interface.cpp:914
void dualPopupSelector(Component *source, Point< int > position, int width, const PopupItems &options, std::function< void(int)> callback)
Opens a dual popup selector for choosing from a hierarchical list of items.
Definition full_interface.cpp:898
void repaintChildBackground(SynthSection *child)
Repaints the background of a child section.
Definition full_interface.cpp:303
void popupBrowser(SynthSection *owner, Rectangle< int > bounds, std::vector< File > directories, String extensions, std::string passthrough_name, std::string additional_folders_name)
Opens a popup browser for file browsing.
Definition full_interface.cpp:872
void popupDisplay(Component *source, const std::string &text, BubbleComponent::BubblePlacement placement, bool primary)
Shows a popup display (a tooltip-like bubble) with provided text.
Definition full_interface.cpp:907
void popupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel)
Opens a popup selector for choosing from a list of items.
Definition full_interface.cpp:888
void popupBrowserUpdate(SynthSection *owner)
Updates the popup browser's ownership, useful if the owner changed.
Definition full_interface.cpp:883
A component representing a modulation source or connection button.
Definition modulation_button.h:21
A base component class that integrates JUCE's Component with OpenGL rendering.
Definition open_gl_component.h:20
void setParent(const SynthSection *parent)
Sets a pointer to the parent SynthSection for skin value lookups.
Definition open_gl_component.h:178
virtual void paintBackground(Graphics &g)
Paints a standard background for the component.
Definition open_gl_component.cpp:105
A ToggleButton that uses an OpenGlShapeButtonComponent for its rendering.
Definition synth_button.h:110
OpenGlComponent * getGlComponent()
Definition synth_button.h:120
OpenGlComponent * getImageComponent()
Definition synth_slider.h:135
OpenGlComponent * getQuadComponent()
Definition synth_slider.h:141
A ToggleButton that uses an OpenGlButtonComponent for its rendering.
Definition synth_button.h:342
OpenGlButtonComponent * getGlComponent()
Definition synth_button.h:350
void setRoundAmount(float round_amount)
Definition preset_selector.h:97
void paintBackground(Graphics &g) override
Definition preset_selector.cpp:55
Manages the overall color and value theme (or "skin") of the user interface.
Definition skin.h:24
ValueId
Identifiers for various UI scaling/spacing values and configuration constants.
Definition skin.h:70
@ kRotaryOptionYOffset
Definition skin.h:78
@ kWidgetMargin
Definition skin.h:103
@ kLabelBackgroundHeight
Definition skin.h:73
@ kRotaryOptionXOffset
Definition skin.h:77
@ kLabelHeight
Definition skin.h:72
@ kBodyRounding
Definition skin.h:71
@ kKnobArcSize
Definition skin.h:89
@ kLabelOffset
Definition skin.h:75
@ kTitleWidth
Definition skin.h:80
@ kTextComponentOffset
Definition skin.h:85
@ kKnobSectionHeight
Definition skin.h:98
@ kModulationButtonWidth
Definition skin.h:101
@ kPadding
Definition skin.h:81
@ kModulationFontSize
Definition skin.h:102
@ kTextComponentLabelOffset
Definition skin.h:76
@ kLabelBackgroundRounding
Definition skin.h:74
@ kFrequencyDisplay
Definition skin.h:116
@ kSliderWidth
Definition skin.h:83
@ kWidgetRoundedCorner
Definition skin.h:104
@ kTextComponentHeight
Definition skin.h:84
@ kRotaryOptionWidth
Definition skin.h:79
@ kBackground
Definition skin.h:128
@ kBorder
Definition skin.h:134
@ kBodyText
Definition skin.h:133
@ kLightenScreen
Definition skin.h:141
@ kTextComponentBackground
Definition skin.h:147
@ kBodyHeading
Definition skin.h:130
@ kShadow
Definition skin.h:142
@ kHeadingText
Definition skin.h:131
@ kLabelConnection
Definition skin.h:136
@ kLabelBackground
Definition skin.h:135
@ kBody
Definition skin.h:129
static bool shouldScaleValue(ValueId value_id)
Checks if a certain ValueId should be scaled by the display ratio.
Definition skin.cpp:169
void setComponentValues(SynthSection *component) const
Applies all default values to a SynthSection.
Definition skin.cpp:228
void setComponentColors(Component *component) const
Applies all component colors to a given component.
Definition skin.cpp:207
void valueChangedInternal(const std::string &name, vital::mono_float value)
Handles internal value changes, updating the parameter and optionally notifying the host.
Definition synth_base.cpp:54
virtual const CriticalSection & getCriticalSection()=0
Provides access to the synth’s internal CriticalSection for thread safety.
A specialized OpenGlToggleButton with additional functionality for the Vital synth.
Definition synth_button.h:450
An interface class linking the Vital synthesizer backend (SynthBase) with a GUI.
Definition synth_gui_interface.h:56
SynthBase * getSynth()
Returns the SynthBase instance this interface is managing.
Definition synth_gui_interface.h:85
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
Rectangle< int > getDividedAreaBuffered(Rectangle< int > full_area, int num_sections, int section, int buffer)
Divides an area into equal sections with buffering, returns the specified section.
Definition synth_section.cpp:776
std::map< std::string, ModulationButton * > modulation_buttons_
Definition synth_section.h:808
void drawTextComponentBackground(Graphics &g, Rectangle< int > bounds, bool extend_to_label)
Draws a background for a text component area.
Definition synth_section.cpp:319
virtual void guiChanged(SynthButton *button) override
Called when a SynthButton state changes (GUI interaction).
Definition synth_section.cpp:405
bool sideways_heading_
Definition synth_section.h:823
float getModFontSize()
Definition synth_section.cpp:672
virtual void buttonClicked(Button *clicked_button) override
Called when a button is clicked. Updates the synth parameter accordingly.
Definition synth_section.cpp:398
virtual void renderOpenGlComponents(OpenGlWrapper &open_gl, bool animate)
Renders all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:357
float getPadding()
Definition synth_section.cpp:660
std::vector< OpenGlComponent * > open_gl_components_
Definition synth_section.h:804
void drawLabelConnectionForComponents(Graphics &g, Component *left, Component *right)
Draws a rectangular connection between labels of two components.
Definition synth_section.cpp:745
void drawLabelBackground(Graphics &g, Rectangle< int > bounds, bool text_component=false)
Draws a background for a label area.
Definition synth_section.cpp:755
float getSliderWidth()
Definition synth_section.cpp:637
void placeKnobsInArea(Rectangle< int > area, std::vector< Component * > knobs)
Definition synth_section.cpp:601
virtual void paintBackgroundShadow(Graphics &g)
Stub for painting background shadows. Overridden by subclasses if needed.
Definition synth_section.h:445
void addSlider(SynthSlider *slider, bool show=true, bool listen=true)
Definition synth_section.cpp:445
PresetSelector * preset_selector_
Definition synth_section.h:816
void paintJointControl(Graphics &g, int x, int y, int width, int height, const std::string &name)
Definition synth_section.cpp:564
void createOffOverlay()
Definition synth_section.cpp:514
float getModButtonWidth()
Definition synth_section.cpp:668
virtual void animate(bool animate)
Triggers animation state change in sub-sections if needed.
Definition synth_section.cpp:822
void addSubSection(SynthSection *section, bool show=true)
Adds a subsection (another SynthSection) as a child.
Definition synth_section.cpp:457
void paintOpenGlChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all OpenGL child components.
Definition synth_section.cpp:267
void paintJointControlSliderBackground(Graphics &g, int x, int y, int width, int height)
Definition synth_section.cpp:525
void addToggleButton(ToggleButton *button, bool show)
Definition synth_section.cpp:420
void drawLabel(Graphics &g, String text, Rectangle< int > component_bounds, bool text_component=false)
Draws a label text below a component.
Definition synth_section.cpp:789
bool active_
Definition synth_section.h:822
virtual void setSkinValues(const Skin &skin, bool top_level)
Sets skin values (colors, sizes) and applies them to sub-sections.
Definition synth_section.cpp:86
void drawTempoDivider(Graphics &g, Component *sync)
Draws a divider line for tempo-related controls.
Definition synth_section.cpp:339
void drawTextBelowComponent(Graphics &g, String text, Component *component, int space, int padding=0)
Draws text below a component with optional padding.
Definition synth_section.cpp:800
void hidePopupDisplay(bool primary)
Hides the currently shown popup display.
Definition synth_section.cpp:140
int getComponentShadowWidth()
Gets the width of shadow around components.
Definition synth_section.cpp:184
virtual void paint(Graphics &g) override
Called when the component should paint itself.
Definition synth_section.cpp:49
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
void placeTempoControls(int x, int y, int width, int height, SynthSlider *tempo, SynthSlider *sync)
Definition synth_section.cpp:584
ToggleButton * activator() const
Gets the activator toggle button if any.
Definition synth_section.h:735
std::map< std::string, Button * > button_lookup_
Definition synth_section.h:807
virtual void paintBody(Graphics &g, Rectangle< int > bounds)
Paints the body background within given bounds.
Definition synth_section.cpp:165
std::map< std::string, ModulationButton * > getAllModulationButtons()
Gets all modulation buttons registered in this section.
Definition synth_section.h:669
std::vector< SynthSection * > sub_sections_
Definition synth_section.h:803
Rectangle< int > getTitleBounds()
Definition synth_section.cpp:709
float getWidgetRounding()
Definition synth_section.cpp:680
void paintChildBackground(Graphics &g, SynthSection *child)
Paints a child's background specifically.
Definition synth_section.cpp:292
void paintChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all child sections.
Definition synth_section.cpp:274
void updatePopupBrowser(SynthSection *owner)
Updates the currently visible popup browser if any.
Definition synth_section.cpp:113
virtual void paintChildrenShadows(Graphics &g)
Paints shadows for child sections.
Definition synth_section.cpp:260
void paintKnobShadows(Graphics &g)
Paints knob shadows for all sliders.
Definition synth_section.cpp:253
Font getLabelFont()
Gets a suitable font for label text.
Definition synth_section.cpp:735
virtual void setActive(bool active)
Sets the active state of this section and sub-sections.
Definition synth_section.cpp:806
virtual int getPixelMultiple() const
Definition synth_section.cpp:729
void drawLabelBackgroundForComponent(Graphics &g, Component *component)
Draws label background for a specific component.
Definition synth_section.cpp:764
static constexpr float kPowerButtonPaddingPercent
Definition synth_section.h:197
void addModulationButton(ModulationButton *button, bool show=true)
Adds a modulation button to this section.
Definition synth_section.cpp:438
void setLabelFont(Graphics &g)
Sets the Graphics context font and color for labels.
Definition synth_section.cpp:740
virtual void destroyOpenGlComponents(OpenGlWrapper &open_gl)
Destroys all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:383
float getSliderOverlap()
Definition synth_section.cpp:641
virtual void setSizeRatio(float ratio)
Sets the size ratio for scaling UI elements.
Definition synth_section.cpp:246
virtual void paintSidewaysHeadingText(Graphics &g)
Paints the section name heading text vertically if sideways_heading_ is true.
Definition synth_section.cpp:51
virtual void paintHeadingText(Graphics &g)
Paints the heading text for this section, either sideways or horizontally.
Definition synth_section.cpp:66
void unlockCriticalSection()
Definition synth_section.cpp:623
void showPopupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel={ })
Shows a popup selector with options.
Definition synth_section.cpp:119
float size_ratio_
Definition synth_section.h:821
void addButton(OpenGlToggleButton *button, bool show=true)
Definition synth_section.cpp:428
Rectangle< int > getLabelBackgroundBounds(Rectangle< int > bounds, bool text_component=false)
Gets the background bounds for a label.
Definition synth_section.cpp:782
SynthButton * activator_
Definition synth_section.h:815
std::map< Skin::ValueId, float > value_lookup_
Definition synth_section.h:801
float findValue(Skin::ValueId value_id) const
Finds a value in the skin overrides or from the parent if not found locally.
Definition synth_section.cpp:18
virtual void paintBorder(Graphics &g, Rectangle< int > bounds)
Paints the border around given bounds.
Definition synth_section.cpp:170
Skin::SectionOverride skin_override_
Definition synth_section.h:820
int getTitleTextRight()
Definition synth_section.cpp:695
virtual void paintBackground(Graphics &g)
Paints the background of the section. Calls paintContainer, heading, knobs, children.
Definition synth_section.cpp:77
float getKnobSectionHeight()
Definition synth_section.cpp:633
void setActivator(SynthButton *activator)
Definition synth_section.cpp:504
SynthSection(const String &name)
Constructs a SynthSection with a given name.
Definition synth_section.cpp:11
void showDualPopupSelector(Component *source, Point< int > position, int width, const PopupItems &options, std::function< void(int)> callback)
Shows a dual popup selector for hierarchical selection.
Definition synth_section.cpp:126
void paintChildShadow(Graphics &g, SynthSection *child)
Paints a child's shadow specifically.
Definition synth_section.cpp:301
float getStandardKnobSize()
Definition synth_section.cpp:656
std::map< std::string, SynthSlider * > getAllSliders()
Gets all sliders registered in this section.
Definition synth_section.h:657
Rectangle< int > getPowerButtonBounds()
Definition synth_section.cpp:704
std::map< std::string, SynthSlider * > slider_lookup_
Definition synth_section.h:806
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
std::map< std::string, ToggleButton * > all_buttons_
Definition synth_section.h:811
void paintJointControlBackground(Graphics &g, int x, int y, int width, int height)
Definition synth_section.cpp:542
std::map< std::string, ToggleButton * > getAllButtons()
Gets all toggle buttons registered in this section.
Definition synth_section.h:663
bool preset_selector_half_width_
Definition synth_section.h:817
virtual void sliderValueChanged(Slider *moved_slider) override
Called when a slider value changes. Updates the synth parameter accordingly.
Definition synth_section.cpp:391
float getTextComponentHeight()
Definition synth_section.cpp:652
virtual void setAllValues(vital::control_map &controls)
Sets values for all known parameters from a control map.
Definition synth_section.cpp:827
void placeRotaryOption(Component *option, SynthSlider *rotary)
Definition synth_section.cpp:593
Rectangle< int > getDividedAreaUnbuffered(Rectangle< int > full_area, int num_sections, int section, int buffer)
Divides an area into equal sections without extra buffering, returns the specified section.
Definition synth_section.cpp:768
virtual void reset()
Resets the section and all sub-sections.
Definition synth_section.cpp:30
void showPopupDisplay(Component *source, const std::string &text, BubbleComponent::BubblePlacement placement, bool primary)
Shows a brief popup display (like a tooltip).
Definition synth_section.cpp:133
void lockCriticalSection()
Definition synth_section.cpp:617
const SynthSection * parent_
Definition synth_section.h:814
float getTextSectionYOffset()
Definition synth_section.cpp:664
virtual void setValue(const std::string &name, vital::mono_float value, NotificationType notification)
Sets a single parameter value for a known control.
Definition synth_section.cpp:846
float getSliderOverlapWithSpace()
Definition synth_section.cpp:648
void setSliderHasHzAlternateDisplay(SynthSlider *slider)
Definition synth_section.cpp:410
float getTitleWidth()
Definition synth_section.cpp:629
virtual void setScrollWheelEnabled(bool enabled)
Enables or disables scroll wheel support for this section and sub-sections.
Definition synth_section.cpp:481
void setParent(const SynthSection *parent)
Sets the parent SynthSection.
Definition synth_section.h:253
std::map< std::string, ModulationButton * > all_modulation_buttons_
Definition synth_section.h:812
virtual void initOpenGlComponents(OpenGlWrapper &open_gl)
Initializes all OpenGL components in this section and sub-sections.
Definition synth_section.cpp:349
void removeSubSection(SynthSection *section)
Removes a previously added subsection.
Definition synth_section.cpp:475
float getDisplayScale() const
Definition synth_section.cpp:719
virtual void paintTabShadow(Graphics &g)
Paints a tab-like shadow effect around the component.
Definition synth_section.cpp:188
virtual void repaintBackground()
Requests a repaint of the background.
Definition synth_section.cpp:96
Rectangle< int > getPresetBrowserBounds()
Definition synth_section.cpp:684
void placeJointControls(int x, int y, int width, int height, SynthSlider *left, SynthSlider *right, Component *widget=nullptr)
Definition synth_section.cpp:572
float getPowerButtonOffset() const
Definition synth_section.h:752
virtual void paintContainer(Graphics &g)
Paints the container background, body, heading, etc.
Definition synth_section.cpp:146
void paintOpenGlBackground(Graphics &g, OpenGlComponent *child)
Paints the background of an OpenGlComponent child.
Definition synth_section.cpp:310
std::unique_ptr< OffOverlay > off_overlay_
Definition synth_section.h:818
void showPopupBrowser(SynthSection *owner, Rectangle< int > bounds, std::vector< File > directories, String extensions, std::string passthrough_name, std::string additional_folders_name)
Shows a file browser popup (e.g., for loading samples or wavetables).
Definition synth_section.cpp:105
std::map< std::string, SynthSlider * > all_sliders_
Definition synth_section.h:810
float getWidgetMargin()
Definition synth_section.cpp:676
A specialized slider with extended functionality for modulation, parameter control,...
Definition synth_slider.h:314
void setAlternateDisplay(Skin::ValueId id, float value, vital::ValueDetails details)
Definition synth_slider.h:691
vital::ValueDetails * getDisplayDetails()
Definition synth_slider.cpp:767
static constexpr float kLinearWidthPercent
Definition synth_slider.h:341
void setDisplayExponentialBase(float base)
Definition synth_slider.h:669
OpenGlComponent * getTextEditorComponent()
Definition synth_slider.h:702
void setModulationArea(Rectangle< int > area)
Definition synth_slider.h:568
#define VITAL_ASSERT(x)
Definition common.h:11
constexpr mono_float kMidi0Frequency
Frequency of MIDI note 0 (C-1).
Definition common.h:47
constexpr mono_float kPi
Pi constant.
Definition common.h:36
std::map< std::string, Value * > control_map
Maps parameter names to Value pointers representing synth control parameters.
Definition synth_types.h:214
float mono_float
Definition common.h:33
A helper struct containing references to OpenGL context, shaders, and display scale.
Definition shaders.h:174
A hierarchical structure of popup menu items for a selector component.
Definition synth_section.h:29
Holds metadata about a single parameter (control) in the Vital synthesizer.
Definition synth_parameters.h:23
mono_float display_multiply
Multiplier for converting internal values to display units.
Definition synth_parameters.h:44
mono_float post_offset
Offset applied after scaling (for certain scale types).
Definition synth_parameters.h:43
@ kExponential
Parameter value transformed by an exponential function.
Definition synth_parameters.h:35
ValueScale value_scale
The scaling mode of the parameter value.
Definition synth_parameters.h:45
std::string display_units
Units to display next to the parameter (e.g., "Hz", "dB").
Definition synth_parameters.h:47
Declares the SynthSlider and related classes, providing various slider styles and functionality in th...