Vital
Loading...
Searching...
No Matches
skin.cpp
Go to the documentation of this file.
1#include "skin.h"
3#include "full_interface.h"
4#include "synth_constants.h"
5#include "synth_section.h"
6#include "wavetable_3d.h"
7
8namespace {
9 const std::string kOverrideNames[Skin::kNumSectionOverrides] = {
10 "All",
11 "Logo",
12 "Header",
13 "Overlays",
14 "Oscillator",
15 "Sample",
16 "Sub",
17 "Filter",
18 "Envelope",
19 "Lfo",
20 "RandomLfo",
21 "Voice",
22 "Macro",
23 "Keyboard",
24 "All Effects",
25 "Chorus",
26 "Compressor",
27 "Delay",
28 "Distortion",
29 "Equalizer",
30 "Effects Filter",
31 "Flanger",
32 "Phaser",
33 "Reverb",
34 "Modulation Drag Drop",
35 "Modulation Matrix",
36 "Preset Browser",
37 "Popup Browser",
38 "Advanced",
39 "Wavetable Editor",
40 };
41
42 const std::string kValueNames[Skin::kNumSkinValueIds] = {
43 "Body Rounding",
44 "Label Height",
45 "Label Background Height",
46 "Label Rounding",
47 "Label Offset",
48 "Text Component Label Offset",
49 "Rotary Option X Offset",
50 "Rotary Option Y Offset",
51 "Rotary Option Width",
52 "Title Width",
53 "Padding",
54 "Large Padding",
55 "Slider Width",
56 "Text Component Height",
57 "Text Component Offset",
58 "Text Component Font Size",
59 "Text Button Height",
60 "Button Font Size",
61 "Knob Arc Size",
62 "Knob Arc Thickness",
63 "Knob Body Size",
64 "Knob Handle Length",
65 "Knob Mod Amount Arc Size",
66 "Knob Mod Amount Arc Thickness",
67 "Knob Mod Meter Arc Size",
68 "Knob Mod Meter Arc Thickness",
69 "Knob Offset",
70 "Knob Section Height",
71 "Knob Shadow Width",
72 "Knob Shadow Offset",
73 "Modulation Button Width",
74 "Modulation Font Size",
75 "Widget Margin",
76 "Widget Rounded Corner",
77 "Widget Line Width",
78 "Widget Line Boost",
79 "Widget Fill Center",
80 "Widget Fill Fade",
81 "Widget Fill Boost",
82 "Wavetable Horizontal Angle",
83 "Wavetable Vertical Angle",
84 "Wavetable Draw Width",
85 "Wavetable Draw Height",
86 "Wavetable Y Offset",
87 };
88
89 const std::string kColorNames[Skin::kNumColors] = {
90 "Background",
91 "Body",
92 "Body Heading Background",
93 "Heading Text",
94 "Preset Text",
95 "Body Text",
96 "Border",
97 "Label Background",
98 "Label Connection",
99 "Power Button On",
100 "Power Button Off",
101
102 "Overlay Screen",
103 "Lighten Screen",
104 "Shadow",
105 "Popup Selector Background",
106 "Popup Background",
107 "Popup Border",
108
109 "Text Component Background",
110 "Text Component Text",
111
112 "Rotary Arc",
113 "Rotary Arc Disabled",
114 "Rotary Arc Unselected",
115 "Rotary Arc Unselected Disabled",
116 "Rotary Hand",
117 "Rotary Body",
118 "Rotary Body Border",
119
120 "Linear Slider",
121 "Linear Slider Disabled",
122 "Linear Slider Unselected",
123 "Linear Slider Thumb",
124 "Linear Slider Thumb Disabled",
125
126 "Widget Center Line",
127 "Widget Primary 1",
128 "Widget Primary 2",
129 "Widget Primary Disabled",
130 "Widget Secondary 1",
131 "Widget Secondary 2",
132 "Widget Secondary Disabled",
133 "Widget Accent 1",
134 "Widget Accent 2",
135 "Widget Background",
136
137 "Modulation Meter",
138 "Modulation Meter Left",
139 "Modulation Meter Right",
140 "Modulation Meter Control",
141 "Modulation Button Selected",
142 "Modulation Button Dragging",
143 "Modulation Button Unselected",
144
145 "Icon Selector Icon",
146
147 "Icon Button Off",
148 "Icon Button Off Hover",
149 "Icon Button Off Pressed",
150 "Icon Button On",
151 "Icon Button On Hover",
152 "Icon Button On Pressed",
153
154 "UI Button",
155 "UI Button Text",
156 "UI Button Hover",
157 "UI Button Press",
158 "UI Action Button",
159 "UI Action Button Hover",
160 "UI Action Button Press",
161
162 "Text Editor Background",
163 "Text Editor Border",
164 "Text Editor Caret",
165 "Text Editor Selection"
166 };
167} // namespace
168
170 return value_id != kWidgetFillFade && value_id != kWidgetFillBoost &&
171 value_id != kWidgetLineBoost && value_id != kKnobHandleLength &&
172 value_id != kWidgetFillCenter && value_id != kFrequencyDisplay &&
173 value_id != kWavetableHorizontalAngle && value_id != kWavetableVerticalAngle;
174}
175
177 File default_skin = LoadSave::getDefaultSkin();
178 if (default_skin.exists()) {
179 if (!loadFromFile(default_skin))
181 }
182 else
184
186}
187
189 for (int i = 0; i < kNumSectionOverrides; ++i)
190 color_overrides_[i].clear();
191 for (int i = 0; i < kNumSectionOverrides; ++i)
192 value_overrides_[i].clear();
193}
194
196 MemoryInputStream skin((const void*)BinaryData::default_vitalskin, BinaryData::default_vitalskinSize, false);
197 std::string skin_string = skin.readEntireStreamAsString().toStdString();
198
199 try {
200 json data = json::parse(skin_string, nullptr, false);
201 jsonToState(data);
202 }
203 catch (const json::exception& e) {
204 }
205}
206
207void Skin::setComponentColors(Component* component) const {
208 for (int i = 0; i < Skin::kNumColors; ++i) {
209 int color_id = i + Skin::kInitialColor;
210 Colour color = getColor(static_cast<Skin::ColorId>(color_id));
211 component->setColour(color_id, color);
212 }
213}
214
215void Skin::setComponentColors(Component* component, SectionOverride section_override, bool top_level) const {
216 if (top_level) {
217 setComponentColors(component);
218 return;
219 }
220
221 for (int i = kInitialColor; i < kFinalColor; ++i)
222 component->removeColour(i);
223
224 for (const auto& color : color_overrides_[section_override])
225 component->setColour(color.first, color.second);
226}
227
229 std::map<ValueId, float> values;
230 for (int i = 0; i < kNumSkinValueIds; ++i)
231 values[(ValueId)i] = values_[i];
232
233 component->setSkinValues(values);
234}
235
236void Skin::setComponentValues(SynthSection* component, SectionOverride section_override, bool top_level) const {
237 if (top_level) {
238 setComponentValues(component);
239 return;
240 }
241 component->setSkinValues(value_overrides_[section_override]);
242}
243
244bool Skin::overridesColor(int section, ColorId color_id) const {
245 if (section == kNone)
246 return true;
247
248 return color_overrides_[section].count(color_id) > 0;
249}
250
251bool Skin::overridesValue(int section, ValueId value_id) const {
252 if (section == kNone)
253 return true;
254
255 return value_overrides_[section].count(value_id) > 0;
256}
257
258void Skin::copyValuesToLookAndFeel(LookAndFeel* look_and_feel) const {
259 look_and_feel->setColour(PopupMenu::backgroundColourId, getColor(Skin::kPopupBackground));
260 look_and_feel->setColour(PopupMenu::textColourId, getColor(Skin::kBodyText));
261 look_and_feel->setColour(TooltipWindow::textColourId, getColor(Skin::kBodyText));
262
263 look_and_feel->setColour(BubbleComponent::backgroundColourId, getColor(Skin::kPopupBackground));
264 look_and_feel->setColour(BubbleComponent::outlineColourId, getColor(Skin::kPopupBorder));
265
266 for (int i = kInitialColor; i < kFinalColor; ++i)
267 look_and_feel->setColour(i, getColor(static_cast<Skin::ColorId>(i)));
268}
269
270Colour Skin::getColor(int section, ColorId color_id) const {
271 if (section == kNone)
272 return getColor(color_id);
273
274 if (color_overrides_[section].count(color_id))
275 return color_overrides_[section].at(color_id);
276
277 return Colours::black;
278}
279
280float Skin::getValue(int section, ValueId value_id) const {
281 if (value_overrides_[section].count(value_id))
282 return value_overrides_[section].at(value_id);
283
284 return getValue(value_id);
285}
286
287void Skin::addOverrideColor(int section, ColorId color_id, Colour color) {
288 if (section == kNone)
289 setColor(color_id, color);
290 else
291 color_overrides_[section][color_id] = color;
292}
293
294void Skin::removeOverrideColor(int section, ColorId color_id) {
295 if (section != kNone)
296 color_overrides_[section].erase(color_id);
297}
298
299void Skin::addOverrideValue(int section, ValueId value_id, float value) {
300 if (section == kNone)
301 setValue(value_id, value);
302 else
303 value_overrides_[section][value_id] = value;
304}
305
306void Skin::removeOverrideValue(int section, ValueId color_id) {
307 if (section != kNone)
308 value_overrides_[section].erase(color_id);
309}
310
312 json data;
313 for (int i = 0; i < kNumColors; ++i)
314 data[kColorNames[i]] = colors_[i].toString().toStdString();
315
316 for (int i = 0; i < kNumSkinValueIds; ++i)
317 data[kValueNames[i]] = values_[i];
318
319 json overrides;
320 for (int override_index = 0; override_index < kNumSectionOverrides; ++override_index) {
321 json override_section;
322 for (const auto& color : color_overrides_[override_index]) {
323 int index = color.first - Skin::kInitialColor;
324 override_section[kColorNames[index]] = color.second.toString().toStdString();
325 }
326
327 for (const auto& value : value_overrides_[override_index]) {
328 int index = value.first;
329 override_section[kValueNames[index]] = value.second;
330 }
331
332 overrides[kOverrideNames[override_index]] = override_section;
333 }
334
335 data["overrides"] = overrides;
336 data["synth_version"] = ProjectInfo::versionNumber;
337
338 return data;
339}
340
342 return stateToJson().dump();
343}
344
345void Skin::saveToFile(File destination) {
346 destination.replaceWithText(stateToString());
347}
348
350 int version = 0;
351 if (data.count("synth_version"))
352 version = data["synth_version"];
353
354 if (version < 0x608) {
355 data["Knob Arc Size"] = data["Knob Size"];
356 data["Knob Arc Thickness"] = data["Knob Thickness"];
357 data["Knob Handle Length"] = data["Knob Handle Radial Amount"];
358 data["Knob Mod Amount Arc Size"] = data["Knob Mod Amount Size"];
359 data["Knob Mod Amount Arc Thickness"] = data["Knob Mod Amount Thickness"];
360 data["Knob Mod Meter Arc Size"] = data["Knob Mod Meter Size"];
361 data["Knob Mod Meter Arc Thickness"] = data["Knob Mod Meter Thickness"];
362 }
363
364 if (data.count("Widget Fill Boost") == 0)
365 data["Widget Fill Boost"] = 1.6f;
366 if (data.count("Widget Line Boost") == 0)
367 data["Widget Line Boost"] = 1.0f;
368
369 if (version < 0x609)
370 data["Modulation Meter"] = Colours::white.toString().toStdString();
371
372 return data;
373}
374
376 clearSkin();
377 data = updateJson(data);
378
379 if (data.count("overrides")) {
380 json overrides = data["overrides"];
381 for (int override_index = 0; override_index < kNumSectionOverrides; ++override_index) {
382 std::string name = kOverrideNames[override_index];
383 color_overrides_[override_index].clear();
384 value_overrides_[override_index].clear();
385
386 if (overrides.count(name) == 0)
387 continue;
388
389 json override_section = overrides[name];
390 for (int i = 0; i < kNumColors; ++i) {
391 if (override_section.count(kColorNames[i])) {
392 ColorId color_id = static_cast<Skin::ColorId>(i + Skin::kInitialColor);
393
394 std::string color_string = override_section[kColorNames[i]];
395 color_overrides_[override_index][color_id] = Colour::fromString(color_string);
396 }
397 }
398
399 for (int i = 0; i < kNumSkinValueIds; ++i) {
400 if (override_section.count(kValueNames[i])) {
401 Skin::ValueId value_id = static_cast<Skin::ValueId>(i);
402 float value = override_section[kValueNames[i]];
403 value_overrides_[override_index][value_id] = value;
404 }
405 }
406 }
407 }
408
409 for (int i = 0; i < kNumColors; ++i) {
410 if (data.count(kColorNames[i])) {
411 std::string color_string = data[kColorNames[i]];
412 colors_[i] = Colour::fromString(color_string);
413 }
414 }
415
416 for (int i = 0; i < kNumSkinValueIds; ++i) {
417 if (data.count(kValueNames[i]))
418 values_[i] = data[kValueNames[i]];
419 else
420 values_[i] = 0.0f;
421 }
422}
423
424bool Skin::stringToState(String skin_string) {
425 try {
426 json data = json::parse(skin_string.toStdString(), nullptr, false);
427 jsonToState(data);
428 }
429 catch (const json::exception& e) {
430 return false;
431 }
432 return true;
433}
434
435bool Skin::loadFromFile(File source) {
436 return stringToState(source.loadFileAsString());
437}
438
439class SkinColorPicker : public Component, public Button::Listener, public Slider::Listener, public ChangeListener {
440 public:
441 static constexpr int kLoadSaveHeight = 20;
442 static constexpr int kButtonHeight = 30;
443
444 SkinColorPicker(String name, Skin* skin, FullInterface* full_interface) :
445 Component(name), load_button_("Load"), save_button_("Save"),
446 override_index_(0), editing_index_(0), skin_(skin), full_interface_(full_interface) {
447 addAndMakeVisible(&load_button_);
448 load_button_.addListener(this);
449 addAndMakeVisible(&save_button_);
450 save_button_.addListener(this);
451
452 for (int i = 0; i < Skin::kNumSectionOverrides; ++i)
454
455 addAndMakeVisible(viewport_);
456 container_ = new Component("Container");
457 viewport_.setViewedComponent(container_);
458
459 for (int i = 0; i < Skin::kNumColors; ++i)
460 addColor(i);
461
462 for (int i = 0; i < Skin::kNumSkinValueIds; ++i)
464
467 }
468
470 for (int i = 0; i < Skin::kNumSkinValueIds; ++i) {
471 float value = skin_->getValue(static_cast<Skin::ValueId>(i));
472 value_sliders_[i]->setValue(value, NotificationType::dontSendNotification);
473 }
474 }
475
476 void addOverrideSection(int override_index) {
477 override_buttons_.push_back(std::make_unique<TextButton>(kOverrideNames[override_index]));
478 size_t index = override_buttons_.size() - 1;
479 addAndMakeVisible(override_buttons_[index].get());
480 override_buttons_[index]->addListener(this);
481 }
482
483 void addColor(int color_index) {
484 color_buttons_.push_back(std::make_unique<TextButton>(kColorNames[color_index]));
485 size_t index = color_buttons_.size() - 1;
486 container_->addAndMakeVisible(color_buttons_[index].get());
487 color_buttons_[index]->addListener(this);
488
489 override_toggle_buttons_.push_back(std::make_unique<ToggleButton>(kColorNames[color_index] + " Override"));
490 container_->addAndMakeVisible(override_toggle_buttons_[index].get());
491 override_toggle_buttons_[index]->addListener(this);
492 override_toggle_buttons_[index]->setColour(ToggleButton::tickColourId, Colours::black);
493 override_toggle_buttons_[index]->setColour(ToggleButton::tickDisabledColourId, Colours::black);
494 }
495
496 void addValueSlider(int value_index) {
497 value_sliders_.push_back(std::make_unique<Slider>(kValueNames[value_index]));
498 size_t index = value_sliders_.size() - 1;
499 container_->addAndMakeVisible(value_sliders_[index].get());
500 value_sliders_[index]->setRange(-10000.0f, 10000.0f);
501 value_sliders_[index]->setValue(0.0f);
502 value_sliders_[index]->setScrollWheelEnabled(false);
503 value_sliders_[index]->setSliderStyle(Slider::IncDecButtons);
504 value_sliders_[index]->addListener(this);
505
506 value_override_toggle_buttons_.push_back(std::make_unique<ToggleButton>(kValueNames[value_index] + " Override"));
507 container_->addAndMakeVisible(value_override_toggle_buttons_[index].get());
508 value_override_toggle_buttons_[index]->addListener(this);
509 value_override_toggle_buttons_[index]->setColour(ToggleButton::tickColourId, Colours::black);
510 value_override_toggle_buttons_[index]->setColour(ToggleButton::tickDisabledColourId, Colours::black);
511 }
512
513 void paint(Graphics& g) override {
514 g.fillCheckerBoard(getLocalBounds().toFloat(), 20.0f, 20.0f, Colours::grey, Colours::white);
515
516 g.setColour(Colour(0xff444444));
517 int x = getWidth() / 3 + kButtonHeight;
518 int text_x = 2 * getWidth() / 3;
519 int y = -viewport_.getViewPositionY();
520 g.fillRect(x, y, 2 * getWidth() / 3, Skin::kNumSkinValueIds * kButtonHeight);
521
522 g.setColour(Colours::white);
523 int width = getWidth() / 2;
524 for (int i = 0; i < Skin::kNumSkinValueIds; ++i) {
525 g.drawText(kValueNames[i], text_x, y, width, kButtonHeight, Justification::centredLeft);
526 y += kButtonHeight;
527 }
528 }
529
530 void resized() override {
531 load_button_.setBounds(0, 0, getWidth() / 6, kLoadSaveHeight);
532 save_button_.setBounds(getWidth() / 6, 0, getWidth() / 6, kLoadSaveHeight);
533
534 float overrides_y = kLoadSaveHeight * 2;
535 float overrides_height = getHeight() - overrides_y;
536 float overrides_width = getWidth() / 3;
537 for (int i = 0; i < Skin::kNumSectionOverrides; ++i) {
538 int override_y = i * overrides_height / Skin::kNumSectionOverrides;
539 int override_height = (i + 1) * overrides_height / Skin::kNumSectionOverrides - override_y;
540 override_buttons_[i]->setBounds(0, override_y + overrides_y, overrides_width, override_height);
541 }
542
543 int y = 0;
544 int width = 2 * getWidth() / 3 - 2 * kButtonHeight;
545 int slider_height = kButtonHeight * 0.7f;
546 int slider_pad = 0.5f * (kButtonHeight - slider_height);
547
548 for (int i = 0; i < Skin::kNumSkinValueIds; ++i) {
549 value_sliders_[i]->setBounds(kButtonHeight, y + slider_pad, width / 2, slider_height);
550 value_sliders_[i]->setTextBoxStyle(Slider::TextBoxLeft, false, width / 2, slider_height);
552 y += kButtonHeight;
553 }
554
555 for (int i = 0; i < color_buttons_.size(); ++i) {
556 color_buttons_[i]->setBounds(kButtonHeight, y, width, kButtonHeight);
558 y += kButtonHeight;
559 }
560
561 container_->setBounds(getWidth() / 3, 0, 2 * getWidth() / 3 - 10, y);
562 viewport_.setBounds(getWidth() / 3, 0, 2 * getWidth() / 3, getHeight());
563 }
564
565 void setOverride(int override_index) {
566 override_index_ = override_index;
567 for (auto& override_button : override_buttons_)
568 override_button->setButtonText(override_button->getName());
569
570 bool show_override = override_index != Skin::kNone;
571 for (int i = 0; i < value_override_toggle_buttons_.size(); ++i) {
572 value_override_toggle_buttons_[i]->setVisible(show_override);
573 Skin::ValueId value_id = static_cast<Skin::ValueId>(i);
574 bool overrides = skin_->overridesValue(override_index_, value_id);
575 value_override_toggle_buttons_[i]->setToggleState(overrides, dontSendNotification);
576 }
577
578 for (int i = 0; i < value_sliders_.size(); ++i) {
579 Skin::ValueId value_id = static_cast<Skin::ValueId>(i);
580 value_sliders_[i]->setValue(skin_->getValue(override_index_, value_id), dontSendNotification);
581 }
582
583 for (int i = 0; i < override_toggle_buttons_.size(); ++i) {
584 override_toggle_buttons_[i]->setVisible(show_override);
585 Skin::ColorId color_id = static_cast<Skin::ColorId>(Skin::kInitialColor + i);
586 bool overrides = skin_->overridesColor(override_index_, color_id);
587 override_toggle_buttons_[i]->setToggleState(overrides, dontSendNotification);
588 }
589
590 for (int i = 0; i < color_buttons_.size(); ++i) {
591 Skin::ColorId color_id = static_cast<Skin::ColorId>(Skin::kInitialColor + i);
593 }
594
595 String new_text = "------ " + override_buttons_[override_index_]->getName() + " ------";
596 override_buttons_[override_index_]->setButtonText(new_text);
597 }
598
599 void toggleOverride(int color_index) {
600 bool visible = override_toggle_buttons_[color_index]->isVisible();
601 bool on = override_toggle_buttons_[color_index]->getToggleState();
602 Skin::ColorId color_id = static_cast<Skin::ColorId>(Skin::kInitialColor + color_index);
603 Colour color = color_buttons_[color_index]->findColour(TextButton::buttonColourId);
604 if (on || !visible)
605 skin_->addOverrideColor(override_index_, color_id, color);
606 else
608
610 }
611
612 void toggleValueOverride(int value_index) {
613 bool visible = value_override_toggle_buttons_[value_index]->isVisible();
614 bool on = value_override_toggle_buttons_[value_index]->getToggleState();
615 Skin::ValueId value_id = static_cast<Skin::ValueId>(value_index);
616 float value = value_sliders_[value_index]->getValue();
617 if (on || !visible)
618 skin_->addOverrideValue(override_index_, value_id, value);
619 else
621
623 }
624
625 void buttonClicked(Button* clicked_button) override {
626 if (clicked_button == &load_button_) {
627 FileChooser open_box("Open Skin", File(), String("*.") + vital::kSkinExtension);
628 if (open_box.browseForFileToOpen()) {
629 if (!skin_->loadFromFile(open_box.getResult())) {
630 AlertWindow::showNativeDialogBox("Error opening skin", "Skin file is corrupted and won't load.", false);
631 return;
632 }
635 }
636 return;
637 }
638 if (clicked_button == &save_button_) {
639 FileChooser save_box("Save Skin", File(), String("*.") + vital::kSkinExtension);
640 if (save_box.browseForFileToSave(true))
641 skin_->saveToFile(save_box.getResult().withFileExtension(vital::kSkinExtension));
642
643 return;
644 }
645
646 for (int i = 0; i < override_buttons_.size(); ++i) {
647 if (clicked_button == override_buttons_[i].get()) {
648 setOverride(i);
649 return;
650 }
651 }
652
653 for (int i = 0; i < value_override_toggle_buttons_.size(); ++i) {
654 if (clicked_button == value_override_toggle_buttons_[i].get()) {
656 return;
657 }
658 }
659
660 for (int i = 0; i < color_buttons_.size(); ++i) {
661 if (clicked_button == override_toggle_buttons_[i].get()) {
663 return;
664 }
665
666 if (clicked_button == color_buttons_[i].get())
667 editing_index_ = i;
668 }
669
670 ColourSelector* color_selector = new ColourSelector();
671 color_selector->setCurrentColour(clicked_button->findColour(TextButton::buttonColourId));
672 color_selector->addChangeListener(this);
673 color_selector->setColour(ColourSelector::backgroundColourId, Colours::transparentBlack);
674 color_selector->setSize(300, 400);
675
676 CallOutBox::launchAsynchronously(std::unique_ptr<Component>(color_selector), clicked_button->getScreenBounds(), nullptr);
677 }
678
679 void sliderValueChanged(Slider* changed_slider) override {
680 for (int i = 0; i < Skin::kNumSkinValueIds; ++i) {
681 if (value_sliders_[i].get() == changed_slider) {
682 if (value_override_toggle_buttons_[i]->isVisible())
683 value_override_toggle_buttons_[i]->setToggleState(true, dontSendNotification);
685 }
686 }
687 }
688
692
693 void setButtonColor(int index, Colour color) {
694 Colour text_color = color.contrasting(0.9f);
695 TextButton* button = color_buttons_[index].get();
696 button->setColour(TextButton::buttonColourId, color);
697 button->setColour(TextButton::textColourOnId, text_color);
698 button->setColour(TextButton::textColourOffId, text_color);
699 }
700
701 void changeListenerCallback(ChangeBroadcaster* source) override {
702 ColourSelector* selector = dynamic_cast<ColourSelector*>(source);
703 if (selector == nullptr)
704 return;
705
706 Colour color = selector->getCurrentColour();
708
710 override_toggle_buttons_[editing_index_]->setToggleState(true, dontSendNotification);
712 }
713
714 protected:
715 TextButton load_button_;
716 TextButton save_button_;
717 std::vector<std::unique_ptr<TextButton>> override_buttons_;
718 std::vector<std::unique_ptr<ToggleButton>> override_toggle_buttons_;
719 std::vector<std::unique_ptr<ToggleButton>> value_override_toggle_buttons_;
720 std::vector<std::unique_ptr<TextButton>> color_buttons_;
721 std::vector<std::unique_ptr<Slider>> value_sliders_;
722 std::vector<std::unique_ptr<Label>> value_labels_;
725
728 Component* container_;
729 Viewport viewport_;
730};
731
733 DocumentWindow("Skin Designer", Colours::grey, DocumentWindow::closeButton){
734 container_ = std::make_unique<SkinColorPicker>("Container", skin, full_interface);
735 setContentNonOwned(container_.get(), false);
736}
737
static DefaultLookAndFeel * instance()
Singleton instance accessor.
Definition default_look_and_feel.h:157
The main GUI container for the entire synthesizer interface.
Definition full_interface.h:61
void reloadSkin(const Skin &skin)
Reloads and applies a new skin, then adjusts layout accordingly.
Definition full_interface.cpp:276
static File getDefaultSkin()
Retrieves the file specifying the default skin.
Definition load_save.cpp:1168
Definition skin.cpp:439
void sliderValueChanged(Slider *changed_slider) override
Definition skin.cpp:679
void resized() override
Definition skin.cpp:530
TextButton load_button_
Definition skin.cpp:715
static constexpr int kButtonHeight
Definition skin.cpp:442
void toggleValueOverride(int value_index)
Definition skin.cpp:612
void addColor(int color_index)
Definition skin.cpp:483
void setSliderValues()
Definition skin.cpp:469
void toggleOverride(int color_index)
Definition skin.cpp:599
void addOverrideSection(int override_index)
Definition skin.cpp:476
FullInterface * full_interface_
Definition skin.cpp:727
std::vector< std::unique_ptr< TextButton > > color_buttons_
Definition skin.cpp:720
void repaintWithSettings()
Definition skin.cpp:689
TextButton save_button_
Definition skin.cpp:716
std::vector< std::unique_ptr< ToggleButton > > value_override_toggle_buttons_
Definition skin.cpp:719
Skin * skin_
Definition skin.cpp:726
Viewport viewport_
Definition skin.cpp:729
std::vector< std::unique_ptr< Label > > value_labels_
Definition skin.cpp:722
std::vector< std::unique_ptr< TextButton > > override_buttons_
Definition skin.cpp:717
void changeListenerCallback(ChangeBroadcaster *source) override
Definition skin.cpp:701
static constexpr int kLoadSaveHeight
Definition skin.cpp:441
std::vector< std::unique_ptr< ToggleButton > > override_toggle_buttons_
Definition skin.cpp:718
SkinColorPicker(String name, Skin *skin, FullInterface *full_interface)
Definition skin.cpp:444
void setButtonColor(int index, Colour color)
Definition skin.cpp:693
void paint(Graphics &g) override
Definition skin.cpp:513
void setOverride(int override_index)
Definition skin.cpp:565
Component * container_
Definition skin.cpp:728
int override_index_
Definition skin.cpp:723
int editing_index_
Definition skin.cpp:724
void buttonClicked(Button *clicked_button) override
Definition skin.cpp:625
std::vector< std::unique_ptr< Slider > > value_sliders_
Definition skin.cpp:721
void addValueSlider(int value_index)
Definition skin.cpp:496
std::unique_ptr< Component > container_
Container component hosting skin editing controls.
Definition skin.h:441
SkinDesigner(Skin *skin, FullInterface *full_interface)
Constructs a SkinDesigner window.
Definition skin.cpp:732
~SkinDesigner()
Destructor.
Manages the overall color and value theme (or "skin") of the user interface.
Definition skin.h:24
Skin()
Constructs a Skin with default or loaded settings.
Definition skin.cpp:176
Colour getColor(int section, ColorId color_id) const
Retrieves a color possibly overridden by a section.
Definition skin.cpp:270
bool stringToState(String skin_string)
Loads skin state from a JSON string.
Definition skin.cpp:424
bool overridesValue(int section, ValueId value_id) const
Checks if a given section overrides a specific value.
Definition skin.cpp:251
Colour colors_[kNumColors]
Array of global colors.
Definition skin.h:404
bool overridesColor(int section, ColorId color_id) const
Checks if a given section overrides a specific color.
Definition skin.cpp:244
json updateJson(json data)
Updates JSON data to a newer format or version if needed.
Definition skin.cpp:349
bool loadFromFile(File source)
Loads skin state from a file.
Definition skin.cpp:435
void addOverrideValue(int section, ValueId value_id, float value)
Adds a value override for a given section.
Definition skin.cpp:299
float getValue(ValueId value_id) const
Gets a global UI value.
Definition skin.h:308
static constexpr int kNumColors
Definition skin.h:208
void addOverrideColor(int section, ColorId color_id, Colour color)
Adds a color override for a given section.
Definition skin.cpp:287
void jsonToState(json skin_var)
Loads skin state from JSON data.
Definition skin.cpp:375
void setValue(ValueId value_id, float value)
Sets a global UI value.
Definition skin.h:301
json stateToJson()
Converts the current skin state to JSON.
Definition skin.cpp:311
void removeOverrideColor(int section, ColorId color_id)
Removes a color override from a section.
Definition skin.cpp:294
ValueId
Identifiers for various UI scaling/spacing values and configuration constants.
Definition skin.h:70
@ kWavetableVerticalAngle
Definition skin.h:111
@ kWidgetFillCenter
Definition skin.h:107
@ kWidgetFillFade
Definition skin.h:108
@ kWavetableHorizontalAngle
Definition skin.h:110
@ kKnobHandleLength
Definition skin.h:92
@ kWidgetLineBoost
Definition skin.h:106
@ kWidgetFillBoost
Definition skin.h:109
@ kFrequencyDisplay
Definition skin.h:116
@ kNumSkinValueIds
Definition skin.h:115
std::map< ValueId, float > value_overrides_[kNumSectionOverrides]
Per-section value overrides.
Definition skin.h:408
ColorId
Identifiers for all colors used in the UI.
Definition skin.h:126
@ kFinalColor
Definition skin.h:205
@ kPopupBorder
Definition skin.h:145
@ kInitialColor
Definition skin.h:127
@ kBodyText
Definition skin.h:133
@ kPopupBackground
Definition skin.h:144
void removeOverrideValue(int section, ValueId value_id)
Removes a value override from a section.
Definition skin.cpp:306
Colour getColor(ColorId color_id) const
Retrieves a globally defined color.
Definition skin.h:264
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 setColor(ColorId color_id, const Colour &color)
Sets a color for a global ColorId.
Definition skin.h:257
SectionOverride
Identifiers for different UI sections that can have color or value overrides.
Definition skin.h:30
@ kNone
Definition skin.h:31
@ kNumSectionOverrides
Definition skin.h:61
String stateToString()
Converts the current skin state to a string (JSON representation).
Definition skin.cpp:341
void setComponentColors(Component *component) const
Applies all component colors to a given component.
Definition skin.cpp:207
void loadDefaultSkin()
Loads a default built-in skin.
Definition skin.cpp:195
void copyValuesToLookAndFeel(LookAndFeel *look_and_feel) const
Copies global skin values into a LookAndFeel instance.
Definition skin.cpp:258
void saveToFile(File destination)
Saves the current skin to a file.
Definition skin.cpp:345
std::map< ColorId, Colour > color_overrides_[kNumSectionOverrides]
Per-section color overrides.
Definition skin.h:407
void clearSkin()
Clears all overrides, returning to a clean default state.
Definition skin.cpp:188
float values_[kNumSkinValueIds]
Array of global float values.
Definition skin.h:405
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
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
nlohmann::json json
Definition line_generator.h:7
const std::string kSkinExtension
File extension for Vital skin/theme files.
Definition synth_constants.h:97
Declares the Wavetable3d class, which provides a 3D and 2D visualization for wavetables.