diff --git a/plugins/common/plugin/InstrumentDescription.cpp b/plugins/common/plugin/InstrumentDescription.cpp index 8e396c0d..af8955a0 100644 --- a/plugins/common/plugin/InstrumentDescription.cpp +++ b/plugins/common/plugin/InstrumentDescription.cpp @@ -102,6 +102,7 @@ std::string getDescriptionBlob(sfizz_synth_t* handle) synth.sendMessage(*client, 0, "/num_samples", "", nullptr); synth.sendMessage(*client, 0, "/root_path", "", nullptr); synth.sendMessage(*client, 0, "/image", "", nullptr); + synth.sendMessage(*client, 0, "/image_controls", "", nullptr); synth.sendMessage(*client, 0, "/key/slots", "", nullptr); synth.sendMessage(*client, 0, "/sw/last/slots", "", nullptr); synth.sendMessage(*client, 0, "/cc/slots", "", nullptr); @@ -149,6 +150,8 @@ InstrumentDescription parseDescriptionBlob(absl::string_view blob) desc.rootPath = args[0].s; else if (Messages::matchOSC("/image", path, indices) && !strcmp(sig, "s")) desc.image = args[0].s; + else if (Messages::matchOSC("/image_controls", path, indices) && !strcmp(sig, "s")) + desc.image_controls = args[0].s; else if (Messages::matchOSC("/key/slots", path, indices) && !strcmp(sig, "b")) copyArgToBitSpan(args[0], desc.keyUsed.span()); else if (Messages::matchOSC("/sw/last/slots", path, indices) && !strcmp(sig, "b")) @@ -187,6 +190,7 @@ std::ostream& operator<<(std::ostream& os, const InstrumentDescription& desc) os << " root_path: " << desc.rootPath << "\n"; os << " image: " << desc.image << "\n"; + os << " image_controls: " << desc.image_controls << "\n"; os << " keys:\n"; for (unsigned i = 0; i < 128; ++i) { diff --git a/plugins/common/plugin/InstrumentDescription.h b/plugins/common/plugin/InstrumentDescription.h index a78988cd..2435706c 100644 --- a/plugins/common/plugin/InstrumentDescription.h +++ b/plugins/common/plugin/InstrumentDescription.h @@ -24,6 +24,7 @@ struct InstrumentDescription { uint32_t numSamples {}; std::string rootPath; std::string image; + std::string image_controls; BitArray<128> keyUsed {}; BitArray<128> keyswitchUsed {}; BitArray<128> sustainOrSostenuto {}; diff --git a/plugins/editor/src/editor/DlgAbout.cpp b/plugins/editor/src/editor/DlgAbout.cpp index 1b81e2ab..a095fdaa 100644 --- a/plugins/editor/src/editor/DlgAbout.cpp +++ b/plugins/editor/src/editor/DlgAbout.cpp @@ -22,7 +22,7 @@ SAboutDialog::SAboutDialog(const CRect& bounds) : CViewContainer(bounds) { SharedPointer logo = owned(new CBitmap("logo_orange.png")); - setBackgroundColor(kColorControlsScroller); + setBackgroundColor(kColorControlsScrollerTransparency); CView* aboutView = nullptr; { diff --git a/plugins/editor/src/editor/EditIds.h b/plugins/editor/src/editor/EditIds.h index d0ab1b0e..f6f6c1a5 100644 --- a/plugins/editor/src/editor/EditIds.h +++ b/plugins/editor/src/editor/EditIds.h @@ -54,6 +54,7 @@ enum class EditId : int { UIZoom, // BackgroundImage, + ControlsImage, // PluginFormat, PluginHost, diff --git a/plugins/editor/src/editor/Editor.cpp b/plugins/editor/src/editor/Editor.cpp index 47ebe515..81e5d371 100644 --- a/plugins/editor/src/editor/Editor.cpp +++ b/plugins/editor/src/editor/Editor.cpp @@ -180,6 +180,7 @@ struct Editor::Impl : EditorController::Receiver, SharedPointer backgroundBitmap_; SharedPointer defaultBackgroundBitmap_; + SharedPointer controlsBitmap_; CTextLabel* sfizzVersionLabel_ = nullptr; @@ -258,6 +259,7 @@ struct Editor::Impl : EditorController::Receiver, void updateSWLastCurrent(int sw); void updateSWLastLabel(unsigned sw, const char* label); void updateBackgroundImage(const char* filepath); + void updateControlsImage(const char* filepath); void updateMemoryUsed(uint64_t mem); // edition of CC by UI @@ -576,6 +578,12 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v) updateBackgroundImage(value.c_str()); } break; + case EditId::ControlsImage: + { + const std::string& value = v.to_string(); + updateControlsImage(value.c_str()); + } + break; case EditId::PluginOutputs: { const int value = static_cast(v.to_float()); @@ -728,6 +736,7 @@ void Editor::Impl::createFrameContents() defaultBackgroundBitmap_ = background; backgroundBitmap_ = background; + controlsBitmap_ = nullptr; { theme = new Theme; @@ -764,7 +773,7 @@ void Editor::Impl::createFrameContents() }; auto createSquaredTransparentGroup = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) { auto* box = new CViewContainer(bounds); - box->setBackgroundColor(kColorSemiTransparent); + box->setBackgroundColor(kColorInfoTransparency); return box; }; #if 0 @@ -1082,10 +1091,10 @@ void Editor::Impl::createFrameContents() panel->setKnobFont(font); panel->setKnobFontColor(kWhiteCColor); panel->setKnobLineIndicatorColor(kWhiteCColor); - panel->setKnobRotatorColor(kColorSemiTransparent); + panel->setKnobRotatorColor(kColorControlsTransparency); panel->setNameLabelFont(font); panel->setNameLabelFontColor(kWhiteCColor); - panel->setNameLabelBackColor(kColorSemiTransparent); + panel->setNameLabelBackColor(kColorControlsTransparency); OnThemeChanged.push_back([panel, palette]() { panel->setValueEditFontColor(palette->knobText); auto shadingColor = palette->knobText; @@ -1955,6 +1964,17 @@ void Editor::Impl::updateBackgroundImage(const char* filepath) applyBackgroundForCurrentPanel(); } +void Editor::Impl::updateControlsImage(const char* filepath) +{ + controlsBitmap_ = loadAnyFormatImage(filepath); + + if (!controlsBitmap_) { + return; + } + + applyBackgroundForCurrentPanel(); +} + void Editor::Impl::setupCurrentPanel() { for (unsigned i = 0; i < kNumPanels; ++i) { @@ -1968,10 +1988,19 @@ void Editor::Impl::setupCurrentPanel() void Editor::Impl::applyBackgroundForCurrentPanel() { CBitmap* bitmap; - if (activePanel_ == kPanelGeneral || activePanel_ == kPanelInfo) + imageContainer_->setBackgroundColor(theme_->frameBackground); + + if (activePanel_ == kPanelGeneral || activePanel_ == kPanelInfo) { bitmap = backgroundBitmap_; - else - bitmap = defaultBackgroundBitmap_; + } else if (activePanel_ == kPanelControls) { + bitmap = controlsBitmap_; + if (!controlsBitmap_) { + imageContainer_->setBackground(nullptr); + return; + } + } else { + return; + } downscaleToWidthAndHeight(bitmap, imageContainer_->getViewSize().getSize()); diff --git a/plugins/editor/src/editor/GUIComponents.cpp b/plugins/editor/src/editor/GUIComponents.cpp index 83300a61..6b2a6dde 100644 --- a/plugins/editor/src/editor/GUIComponents.cpp +++ b/plugins/editor/src/editor/GUIComponents.cpp @@ -1094,7 +1094,7 @@ void SControlsPanel::recalculateSubViews() // update scrollbar style vsb->setFrameColor(kColorTransparent); vsb->setBackgroundColor(kColorTransparent); - vsb->setScrollerColor(kColorControlsScroller); + vsb->setScrollerColor(kColorControlsScrollerTransparency); } } diff --git a/plugins/editor/src/editor/GUIDefs.cpp b/plugins/editor/src/editor/GUIDefs.cpp index 8428d3a1..176f3220 100644 --- a/plugins/editor/src/editor/GUIDefs.cpp +++ b/plugins/editor/src/editor/GUIDefs.cpp @@ -12,13 +12,14 @@ namespace gui { - const CColor kColorSemiTransparent { CColor(0x00, 0x00, 0x00, 0x99) }; const CColor kColorTransparent { CColor(0x00, 0x00, 0x00, 0x00) }; const CColor kColorTransparentDark { CColor(0x00, 0x00, 0x00, 0xc0) }; const CColor kColorOrange { CColor(0xfd, 0x98, 0x00, 0xff) }; - const CColor kColorControlsScroller { CColor(0x00, 0x00, 0x00, 0x80) }; + const CColor kColorControlsScrollerTransparency { CColor(0x00, 0x00, 0x00, 0x80) }; + const CColor kColorControlsTransparency { CColor(0x00, 0x00, 0x00, 0x80) }; + const CColor kColorInfoTransparency { CColor(0x00, 0x00, 0x00, 0x99) }; const CColor kColorMeterDanger { CColor(0xaa, 0x00, 0x00) }; const CColor kColorMeterNormal { CColor(0x00, 0xaa, 0x11) }; const CColor kColorTooltipBackground { CColor(0xff, 0xff, 0xd2, 0xff) }; diff --git a/plugins/editor/src/editor/GUIDefs.h b/plugins/editor/src/editor/GUIDefs.h index 1bcf7b76..5238aba6 100644 --- a/plugins/editor/src/editor/GUIDefs.h +++ b/plugins/editor/src/editor/GUIDefs.h @@ -14,13 +14,14 @@ using VSTGUI::CColor; namespace gui { - extern const CColor kColorSemiTransparent; extern const CColor kColorTransparent; extern const CColor kColorTransparentDark; extern const CColor kColorOrange; - extern const CColor kColorControlsScroller; + extern const CColor kColorControlsScrollerTransparency; + extern const CColor kColorControlsTransparency; + extern const CColor kColorInfoTransparency; extern const CColor kColorMeterDanger; extern const CColor kColorMeterNormal; extern const CColor kColorTooltipBackground; diff --git a/plugins/lv2/sfizz_ui.cpp b/plugins/lv2/sfizz_ui.cpp index 5c974eb5..ba468959 100644 --- a/plugins/lv2/sfizz_ui.cpp +++ b/plugins/lv2/sfizz_ui.cpp @@ -560,7 +560,9 @@ sfizz_ui_update_description(sfizz_ui_t *self, const InstrumentDescription& desc) const fs::path rootPath = fs::u8path(desc.rootPath); const fs::path imagePath = rootPath / fs::u8path(desc.image); + const fs::path imageCtrlPath = rootPath / fs::u8path(desc.image_controls); self->uiReceiveValue(EditId::BackgroundImage, imagePath.u8string()); + self->uiReceiveValue(EditId::ControlsImage, imageCtrlPath.u8string()); for (unsigned key = 0; key < 128; ++key) { bool keyUsed = desc.keyUsed.test(key); diff --git a/plugins/vst/SfizzVstEditor.cpp b/plugins/vst/SfizzVstEditor.cpp index 758b88fc..c401535d 100644 --- a/plugins/vst/SfizzVstEditor.cpp +++ b/plugins/vst/SfizzVstEditor.cpp @@ -238,6 +238,9 @@ bool SfizzVstEditor::processUpdate(FUnknown* changedUnknown, int32 message) const fs::path imagePath = rootPath / fs::u8path(desc.image); uiReceiveValue(EditId::BackgroundImage, imagePath.u8string()); + const fs::path ctrlImagePath = rootPath / fs::u8path(desc.image_controls); + uiReceiveValue(EditId::ControlsImage, ctrlImagePath.u8string()); + for (unsigned key = 0; key < 128; ++key) { bool keyUsed = desc.keyUsed.test(key); bool keyswitchUsed = desc.keyswitchUsed.test(key); diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 3042092c..e1228778 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -429,6 +429,9 @@ void Synth::Impl::handleControlOpcodes(const std::vector& members) case hash("image"): image_ = absl::StrCat(defaultPath_, absl::StrReplaceAll(trim(member.value), { { "\\", "/" } })); break; + case hash("image_controls"): + image_controls_ = absl::StrCat(defaultPath_, absl::StrReplaceAll(trim(member.value), { { "\\", "/" } })); + break; case hash("note_offset"): noteOffset_ = member.read(Default::noteOffset); break; diff --git a/src/sfizz/SynthMessaging.cpp b/src/sfizz/SynthMessaging.cpp index 26ec6102..7776ed77 100644 --- a/src/sfizz/SynthMessaging.cpp +++ b/src/sfizz/SynthMessaging.cpp @@ -125,6 +125,10 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co client.receive<'s'>(delay, path, impl.image_.c_str()); } break; + MATCH("/image_controls", "") { + client.receive<'s'>(delay, path, impl.image_controls_.c_str()); + } break; + //---------------------------------------------------------------------- MATCH("/sw/last/slots", "") { diff --git a/src/sfizz/SynthPrivate.h b/src/sfizz/SynthPrivate.h index 30e457f2..3b051f0d 100644 --- a/src/sfizz/SynthPrivate.h +++ b/src/sfizz/SynthPrivate.h @@ -334,6 +334,7 @@ struct Synth::Impl final: public Parser::Listener { // Control opcodes std::string defaultPath_ { "" }; std::string image_ { "" }; + std::string image_controls_ { "" }; int noteOffset_ { Default::noteOffset }; int octaveOffset_ { Default::octaveOffset };