gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit fed73658bcc63113358d4964f39f014d7e639f95
parent b08056e9e5d36ad684d770057f7a7c4284fe7f2a
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Tue, 15 Mar 2022 21:07:25 +0100

implement patch browser / part select / play mode switches / parameter hovering

Diffstat:
Msource/jucePlugin/CMakeLists.txt | 2++
Msource/jucePlugin/PluginEditor.cpp | 2+-
Msource/jucePlugin/VirusParameter.h | 2+-
Msource/jucePlugin/genericUI/assets/VirusC.json | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msource/jucePlugin/genericUI/uiObject.cpp | 2++
Msource/jucePlugin/ui/Virus_PatchBrowser.cpp | 4++--
Msource/jucePlugin/ui/Virus_PatchBrowser.h | 4++++
Msource/jucePlugin/ui3/Parts.cpp | 32++++++++++++++++++++------------
Msource/jucePlugin/ui3/Parts.h | 22++++++++++++----------
Asource/jucePlugin/ui3/PatchBrowser.cpp | 29+++++++++++++++++++++++++++++
Asource/jucePlugin/ui3/PatchBrowser.h | 16++++++++++++++++
Msource/jucePlugin/ui3/VirusEditor.cpp | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msource/jucePlugin/ui3/VirusEditor.h | 29++++++++++++++++++++++++++++-
Mtemp/cmake_win64/gearmulator.sln.DotSettings | 1+
14 files changed, 487 insertions(+), 41 deletions(-)

diff --git a/source/jucePlugin/CMakeLists.txt b/source/jucePlugin/CMakeLists.txt @@ -76,6 +76,8 @@ set(SOURCES_UI2 set(SOURCES_UI3 ui3/Parts.cpp ui3/Parts.h + ui3/PatchBrowser.cpp + ui3/PatchBrowser.h ui3/Tabs.cpp ui3/Tabs.h ui3/VirusEditor.cpp diff --git a/source/jucePlugin/PluginEditor.cpp b/source/jucePlugin/PluginEditor.cpp @@ -80,7 +80,7 @@ void AudioPluginAudioProcessorEditor::LoadSkin(int index) { { try { - m_virusEditor.reset(new genericVirusUI::VirusEditor(m_parameterBinding, processorRef.getController())); + m_virusEditor.reset(new genericVirusUI::VirusEditor(m_parameterBinding, processorRef.getController(), processorRef)); setSize(m_virusEditor->getWidth(), m_virusEditor->getHeight()); } catch(const std::runtime_error& _err) diff --git a/source/jucePlugin/VirusParameter.h b/source/jucePlugin/VirusParameter.h @@ -32,7 +32,7 @@ namespace Virus juce::Value &getValueObject() { return m_value; }; const juce::Value &getValueObject() const { return m_value; }; - const Description getDescription() const { return m_desc; }; + const Description& getDescription() const { return m_desc; }; const juce::NormalisableRange<float> &getNormalisableRange() const override { return m_range; } diff --git a/source/jucePlugin/genericUI/assets/VirusC.json b/source/jucePlugin/genericUI/assets/VirusC.json @@ -18,6 +18,76 @@ } }, { + "name" : "singleLabel", + "label" : { + "text" : "SINGLE", + "textHeight" : "16", + "color" : "EBEBEBFF", + "alignH" : "R", + "alignV" : "C", + "bold" : "1", + "x" : "154", + "y" : "281", + "width" : "70", + "height" : "30" + } + }, + { + "name" : "PlayModeSingle", + "button" : { + "isToggle" : "1", + "radioGroupId" : "5", + "normalImage" : "0", + "overImage" : "0", + "downImage" : "1", + "normalImageOn" : "1", + "overImageOn" : "1", + "downImageOn" : "1", + "x" : "234", + "y" : "281", + "width" : "86", + "height" : "30", + "texture" : "presest_btn_select_86x60_x2", + "tileSizeX" : "86", + "tileSizeY" : "30" + } + }, + { + "name" : "PlayModeMulti", + "button" : { + "isToggle" : "1", + "radioGroupId" : "5", + "normalImage" : "0", + "overImage" : "0", + "downImage" : "1", + "normalImageOn" : "1", + "overImageOn" : "1", + "downImageOn" : "1", + "x" : "506", + "y" : "281", + "width" : "86", + "height" : "30", + "texture" : "presest_btn_select_86x60_x2", + "tileSizeX" : "86", + "tileSizeY" : "30" + } + }, + { + "name" : "multiLabel", + "label" : { + "text" : "MULTI", + "textHeight" : "16", + "color" : "EBEBEBFF", + "alignH" : "L", + "alignV" : "C", + "bold" : "1", + "x" : "600", + "y" : "281", + "width" : "70", + "height" : "30" + } + }, + { "name" : "PatchName", "label" : { "text" : "OvertureCK", @@ -25,7 +95,8 @@ "color" : "FF7180FF", "alignH" : "L", "alignV" : "C", - "x" : "828,6", + "bold" : "1", + "x" : "824,6", "y" : "80,9", "width" : "470", "height" : "100" @@ -34,15 +105,16 @@ { "name" : "ControlLabel", "label" : { - "text" : "Osc 1 Semitone -45", + "text" : "Osc 1 Semitone\n-12", "textHeight" : "32", "color" : "FF7180FF", "alignH" : "R", "alignV" : "T", - "x" : "1243,326", + "bold" : "1", + "x" : "1190,6", "y" : "92,9", - "width" : "312,3241", - "height" : "100" + "width" : "368", + "height" : "80" } }, { @@ -106,10 +178,14 @@ "combobox" : { "text" : "Virus_C_OS_6.5.bin", "textHeight" : "24", - "x" : "2024,012", - "y" : "119,4953", - "width" : "508,4647", - "height" : "37,0013" + "color" : "FD9595FF", + "alignH" : "L", + "alignV" : "C", + "x" : "2024", + "y" : "119", + "width" : "508", + "height" : "37", + "tooltip" : "Copy a valid ROM file with file extension .bin next to this plugin" } }, { @@ -2066,6 +2142,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "138", "width" : "162", @@ -2080,6 +2158,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "376", "width" : "162", @@ -2094,6 +2174,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "572", "width" : "162", @@ -2108,6 +2190,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "810", "width" : "162", @@ -2122,6 +2206,8 @@ "combobox" : { "text" : "8", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "1043", "width" : "162", @@ -2397,6 +2483,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1210", "y" : "310", "width" : "162", @@ -2533,6 +2621,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1210", "y" : "409,8", "width" : "162", @@ -2584,6 +2674,8 @@ "combobox" : { "text" : "Parallel 4", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1578", "y" : "309", "width" : "162", @@ -2598,6 +2690,8 @@ "combobox" : { "text" : "Parallel 4", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1578", "y" : "407", "width" : "162", @@ -2612,6 +2706,8 @@ "combobox" : { "text" : "Parallel 4", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1782,4", "y" : "309", "width" : "162", @@ -2845,6 +2941,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "128", "width" : "162", @@ -2859,6 +2957,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "213", "width" : "162", @@ -3083,6 +3183,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "835", "y" : "298", "width" : "193", @@ -3114,6 +3216,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "508", "width" : "162", @@ -3128,6 +3232,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "593", "width" : "162", @@ -3352,6 +3458,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "835", "y" : "678", "width" : "193", @@ -3383,6 +3491,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "887", "width" : "162", @@ -3397,6 +3507,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "71", "y" : "972", "width" : "162", @@ -3499,6 +3611,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "835", "y" : "905", "width" : "193", @@ -3530,6 +3644,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "184", "width" : "190", @@ -3544,6 +3660,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "300", "width" : "190", @@ -3575,6 +3693,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1289", "y" : "779", "width" : "190", @@ -3589,6 +3709,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1289", "y" : "895", "width" : "190", @@ -3620,6 +3742,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1289", "y" : "1047,8", "width" : "190", @@ -3651,6 +3775,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1291", "y" : "185", "width" : "190", @@ -3665,6 +3791,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1291", "y" : "301", "width" : "190", @@ -3696,6 +3824,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1291", "y" : "453,8", "width" : "190", @@ -3727,6 +3857,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1291", "y" : "605", "width" : "190", @@ -3758,6 +3890,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "433", "width" : "190", @@ -3772,6 +3906,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "549", "width" : "190", @@ -3803,6 +3939,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "681,7", "width" : "190", @@ -3817,6 +3955,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "797,7", "width" : "190", @@ -3848,6 +3988,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "930", "width" : "190", @@ -3862,6 +4004,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1758", "y" : "1046", "width" : "190", @@ -3888,6 +4032,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "138", "width" : "162", @@ -3953,6 +4099,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "372", "width" : "162", @@ -4069,6 +4217,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "610", "width" : "162", @@ -4287,6 +4437,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "86", "y" : "1058", "width" : "162", @@ -4562,6 +4714,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1109", "y" : "137", "width" : "162", @@ -4576,6 +4730,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1109", "y" : "334", "width" : "162", @@ -4590,6 +4746,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1333", "y" : "334", "width" : "162", @@ -4621,6 +4779,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1109", "y" : "608", "width" : "162", @@ -4822,6 +4982,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1109", "y" : "1004", "width" : "162", @@ -5018,6 +5180,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "137", "y" : "609", "width" : "162", @@ -5032,6 +5196,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "340", "y" : "609", "width" : "162", @@ -5063,6 +5229,9 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "24", + "color" : "FD9595FF", + "alignH" : "L", + "alignV" : "C", "x" : "1164", "y" : "121", "width" : "170", @@ -5077,6 +5246,9 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "24", + "color" : "FD9595FF", + "alignH" : "L", + "alignV" : "C", "x" : "1164", "y" : "187", "width" : "170", @@ -5091,6 +5263,9 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "24", + "color" : "FD9595FF", + "alignH" : "L", + "alignV" : "C", "x" : "1377", "y" : "121", "width" : "170", @@ -5176,6 +5351,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "969", "y" : "381", "width" : "162", @@ -5190,6 +5367,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1180,55", "y" : "381", "width" : "162", @@ -5204,6 +5383,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1609", "y" : "381", "width" : "162", @@ -5218,6 +5399,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1820,55", "y" : "381", "width" : "162", @@ -5232,6 +5415,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "969", "y" : "617,4", "width" : "162", @@ -5280,6 +5465,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "969", "y" : "776,5", "width" : "162", @@ -5328,6 +5515,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1608", "y" : "617,4", "width" : "160", @@ -5342,6 +5531,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1822", "y" : "617,4", "width" : "160", @@ -5356,6 +5547,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1608", "y" : "716,4", "width" : "160", @@ -5370,6 +5563,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1822", "y" : "716,4", "width" : "160", @@ -5384,6 +5579,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1608", "y" : "815,4", "width" : "160", @@ -5398,6 +5595,8 @@ "combobox" : { "text" : "Wave 42", "textHeight" : "30", + "alignH" : "L", + "alignV" : "C", "x" : "1822", "y" : "815,4", "width" : "160", @@ -5410,12 +5609,15 @@ { "name" : "MidiIn", "combobox" : { - "text" : "Wave 42", + "text" : "In Device X", "textHeight" : "24", + "alignH" : "R", + "alignV" : "C", "x" : "954,88", "y" : "1116", "width" : "124,2466", - "height" : "36" + "height" : "36", + "tooltip" : "Select an additional physical Midi Input device for " }, "parameterAttachment" : { "parameter" : "Category1" @@ -5424,8 +5626,10 @@ { "name" : "MidiOut", "combobox" : { - "text" : "Wave 42", + "text" : "Out Device X", "textHeight" : "24", + "alignH" : "L", + "alignV" : "C", "x" : "1116,35", "y" : "1116", "width" : "124,2466", @@ -5445,6 +5649,44 @@ "width" : "2034", "height" : "1238", "texture" : "Pres_2034x1238_x2" + }, + "children" : [ + { + "name" : "ContainerPresetBrowser", + "component" : { + "x" : "88", + "y" : "96", + "width" : "1857", + "height" : "1055" + } + } + ] + }, + { + "name" : "DonateInfo", + "hyperlinkbutton" : { + "url" : "https://paypal.me/dsp56300", + "text" : "To donate: https://paypal.me/dsp56300", + "textHeight" : "28", + "color" : "FF7180FF", + "x" : "74", + "y" : "1543", + "width" : "730", + "height" : "45" + } + }, + { + "name" : "VersionInfo", + "label" : { + "text" : "DSP56300 Emulator Version 1.2.11 - March 8 2022 20:03:57", + "textHeight" : "28", + "color" : "FF7180FF", + "alignH" : "R", + "alignV" : "C", + "x" : "1416", + "y" : "1543", + "width" : "1280", + "height" : "45" } } ] diff --git a/source/jucePlugin/genericUI/uiObject.cpp b/source/jucePlugin/genericUI/uiObject.cpp @@ -302,6 +302,8 @@ namespace genericUI auto& binding = _editor.getParameterBinding(); binding.bind(_target, index); + + _target.getProperties().set("parameter", static_cast<int>(index)); } template <typename Target, typename Style> void UiObject::createStyle(Editor& _editor, Target& _target, Style* _style) diff --git a/source/jucePlugin/ui/Virus_PatchBrowser.cpp b/source/jucePlugin/ui/Virus_PatchBrowser.cpp @@ -16,10 +16,10 @@ const Array<String> g_categories = {"", "Lead", "Bass", "Pad", "Decay", PatchBrowser::PatchBrowser(VirusParameterBinding & _parameterBinding, Virus::Controller& _controller) : m_parameterBinding(_parameterBinding), m_controller(_controller), - m_fileFilter("*.syx;*.mid;*.midi", "*", "virus patch dumps"), + m_fileFilter("*.syx;*.mid;*.midi", "*", "Virus Patch Dumps"), m_bankList(FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles, File::getSpecialLocation(File::SpecialLocationType::currentApplicationFile), &m_fileFilter, nullptr), m_search("Search Box"), - m_patchList("Patch browser"), + m_patchList("Patch Browser"), m_properties(m_controller.getConfig()) { const auto bankDir = m_properties->getValue("virus_bank_dir", ""); diff --git a/source/jucePlugin/ui/Virus_PatchBrowser.h b/source/jucePlugin/ui/Virus_PatchBrowser.h @@ -32,6 +32,10 @@ public: static void splitMultipleSysex(std::vector<std::vector<uint8_t>>& _dst, const std::vector<uint8_t>& _src); + juce::FileBrowserComponent& getBankList() {return m_bankList; } + juce::TableListBox& getPatchList() {return m_patchList; } + juce::TextEditor& getSearchBox() {return m_search; } + private: VirusParameterBinding &m_parameterBinding; Virus::Controller& m_controller; diff --git a/source/jucePlugin/ui3/Parts.cpp b/source/jucePlugin/ui3/Parts.cpp @@ -31,21 +31,29 @@ namespace genericVirusUI updateAll(); } - Parts::~Parts() + Parts::~Parts() = default; + + void Parts::onProgramChange() const { + updateAll(); } - void Parts::onProgramChange() + void Parts::onPlayModeChanged() const { updateAll(); } - void Parts::selectPart(const size_t _part) + void Parts::onCurrentPartChanged() const + { + updateSelectedPart(); + } + + void Parts::selectPart(const size_t _part) const { - m_editor.getParameterBinding().setPart(static_cast<uint8_t>(_part)); + m_editor.setPart(_part); } - void Parts::selectPrevPreset(const size_t _part) + void Parts::selectPrevPreset(const size_t _part) const { Virus::Controller& controller = m_editor.getController(); @@ -57,7 +65,7 @@ namespace genericVirusUI } } - void Parts::selectNextPreset(const size_t _part) + void Parts::selectNextPreset(const size_t _part) const { Virus::Controller& controller = m_editor.getController(); @@ -68,7 +76,7 @@ namespace genericVirusUI } } - void Parts::selectPreset(size_t _part) + void Parts::selectPreset(size_t _part) const { juce::PopupMenu selector; @@ -82,7 +90,7 @@ namespace genericVirusUI for (uint8_t j = 0; j < presetNames.size(); j++) { const auto presetName = presetNames[j]; - p.addItem(presetNames[j], [this, bank, j, pt, presetName] + p.addItem(presetName, [this, bank, j, pt] { m_editor.getController().setCurrentPartPreset(pt, bank, j); }); @@ -94,13 +102,13 @@ namespace genericVirusUI selector.showMenuAsync(juce::PopupMenu::Options()); } - void Parts::updatePresetNames() + void Parts::updatePresetNames() const { for(size_t i=0; i<m_presetName.size(); ++i) m_presetName[i]->setButtonText(m_editor.getController().getCurrentPartPresetName(static_cast<uint8_t>(i))); } - void Parts::updateSelectedPart() + void Parts::updateSelectedPart() const { const auto part = m_editor.getController().getCurrentPart(); @@ -115,7 +123,7 @@ namespace genericVirusUI } } - void Parts::updateSingleOrMultiMode() + void Parts::updateSingleOrMultiMode() const { const auto multiMode = m_editor.getController().isMultiMode(); @@ -132,7 +140,7 @@ namespace genericVirusUI } } - void Parts::updateAll() + void Parts::updateAll() const { updatePresetNames(); updateSelectedPart(); diff --git a/source/jucePlugin/ui3/Parts.h b/source/jucePlugin/ui3/Parts.h @@ -14,18 +14,20 @@ namespace genericVirusUI explicit Parts(VirusEditor& _editor); virtual ~Parts(); - void onProgramChange(); + void onProgramChange() const; + void onPlayModeChanged() const; + void onCurrentPartChanged() const; private: - void selectPart(size_t _part); - void selectPrevPreset(size_t _part); - void selectNextPreset(size_t _part); - void selectPreset(size_t _part); - - void updatePresetNames(); - void updateSelectedPart(); - void updateAll(); - void updateSingleOrMultiMode(); + void selectPart(size_t _part) const; + void selectPrevPreset(size_t _part) const; + void selectNextPreset(size_t _part) const; + void selectPreset(size_t _part) const; + + void updatePresetNames() const; + void updateSelectedPart() const; + void updateAll() const; + void updateSingleOrMultiMode() const; VirusEditor& m_editor; diff --git a/source/jucePlugin/ui3/PatchBrowser.cpp b/source/jucePlugin/ui3/PatchBrowser.cpp @@ -0,0 +1,29 @@ +#include "PatchBrowser.h" + +#include "VirusEditor.h" + +namespace genericVirusUI +{ + PatchBrowser::PatchBrowser(const VirusEditor& _editor) : m_patchBrowser(_editor.getParameterBinding(), _editor.getController()) + { + // We use the old patch browser for now. Fit into the desired parent + auto* pagePresets = _editor.findComponent("ContainerPresetBrowser"); + + const auto parentBounds = pagePresets->getBounds(); + + const auto w = parentBounds.getWidth() >> 1; + const auto h = parentBounds.getHeight() >> 1; + + m_patchBrowser.setBounds(0,0,w,h); + + const auto searchY = h - m_patchBrowser.getSearchBox().getHeight() - 5; + + m_patchBrowser.getBankList().setBounds(0, 0, w>>1, h); + m_patchBrowser.getPatchList().setBounds(w>>1, 0, w>>1, searchY); + m_patchBrowser.getSearchBox().setBounds(w>>1, searchY, w>>1, m_patchBrowser.getSearchBox().getHeight()); + + pagePresets->addAndMakeVisible(&m_patchBrowser); + + m_patchBrowser.setTransform(juce::AffineTransform::scale(2.0f)); + } +} diff --git a/source/jucePlugin/ui3/PatchBrowser.h b/source/jucePlugin/ui3/PatchBrowser.h @@ -0,0 +1,16 @@ +#pragma once + +#include "../ui/Virus_PatchBrowser.h" + +namespace genericVirusUI +{ + class VirusEditor; + + class PatchBrowser + { + public: + explicit PatchBrowser(const VirusEditor& _editor); + private: + ::PatchBrowser m_patchBrowser; + }; +} diff --git a/source/jucePlugin/ui3/VirusEditor.cpp b/source/jucePlugin/ui3/VirusEditor.cpp @@ -1,23 +1,136 @@ #include "VirusEditor.h" #include "BinaryData.h" +#include "../PluginProcessor.h" #include "../VirusController.h" +#include "../VirusParameterBinding.h" namespace genericVirusUI { - VirusEditor::VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller) : Editor(std::string(BinaryData::VirusC_json, BinaryData::VirusC_jsonSize), _binding, _controller), + VirusEditor::VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller, AudioPluginAudioProcessor &_processorRef) : Editor(std::string(BinaryData::VirusC_json, BinaryData::VirusC_jsonSize), _binding, _controller), m_parts(*this), - m_tabs(*this) + m_tabs(*this), + m_patchBrowser(*this) { m_presetName = findComponentT<juce::Label>("PatchName"); + m_controlLabel = findComponentT<juce::Label>("ControlLabel"); + m_romSelector = findComponentT<juce::ComboBox>("RomSelector"); + + m_playModeSingle = findComponentT<juce::Button>("PlayModeSingle"); + m_playModeMulti = findComponentT<juce::Button>("PlayModeMulti"); + + m_playModeSingle->onClick = [this]{ setPlayMode(virusLib::PlayMode::PlayModeSingle); }; + m_playModeMulti->onClick = [this]{ setPlayMode(virusLib::PlayMode::PlayModeMulti); }; + + if(m_romSelector) + { + if(!_processorRef.isPluginValid()) + m_romSelector->addItem("<No ROM found>", 1); + else + m_romSelector->addItem(_processorRef.getRomName(), 1); + + m_romSelector->setSelectedId(1, juce::dontSendNotification); + } getController().onProgramChange = [this] { onProgramChange(); }; + + addMouseListener(this, true); + + m_controlLabel->setText("", juce::dontSendNotification); } void VirusEditor::onProgramChange() { m_parts.onProgramChange(); + updatePresetName(); + } + + void VirusEditor::onPlayModeChanged() + { + m_parts.onPlayModeChanged(); + updatePresetName(); + } + + void VirusEditor::onCurrentPartChanged() + { + m_parts.onCurrentPartChanged(); + updatePresetName(); + } + + void VirusEditor::mouseDrag(const juce::MouseEvent & event) + { + updateControlLabel(event.eventComponent); + } + + void VirusEditor::mouseEnter(const juce::MouseEvent& event) + { + if (event.mouseWasDraggedSinceMouseDown()) + return; + updateControlLabel(event.eventComponent); + } + void VirusEditor::mouseExit(const juce::MouseEvent& event) + { + if (event.mouseWasDraggedSinceMouseDown()) + return; + updateControlLabel(nullptr); + } + void VirusEditor::mouseUp(const juce::MouseEvent& event) + { + if (event.mouseWasDraggedSinceMouseDown()) + return; + updateControlLabel(event.eventComponent); + } + + void VirusEditor::updateControlLabel(juce::Component* _component) const + { + if(_component) + { + // combo boxes report the child label as event source, try the parent in this case + if(!_component->getProperties().contains("parameter")) + _component = _component->getParentComponent(); + } + + if(!_component || !_component->getProperties().contains("parameter")) + { + m_controlLabel->setText("", juce::dontSendNotification); + return; + } + + const int v = _component->getProperties()["parameter"]; + + const auto* p = getController().getParameter(static_cast<Virus::ParameterType>(v)); + + if(!p) + { + m_controlLabel->setText("", juce::dontSendNotification); + return; + } + + const auto value = p->getText(p->getValue(), 0); + + const auto& desc = p->getDescription(); + + m_controlLabel->setText(desc.name + "\n" + value, juce::dontSendNotification); + } + + void VirusEditor::updatePresetName() const + { m_presetName->setText(getController().getCurrentPartPresetName(getController().getCurrentPart()), juce::dontSendNotification); } + + void VirusEditor::setPlayMode(uint8_t _playMode) + { + getController().getParameter(Virus::Param_PlayMode)->setValue(_playMode); + if (_playMode == virusLib::PlayModeSingle && getController().getCurrentPart() != 0) + getParameterBinding().setPart(0); + + onPlayModeChanged(); + } + + void VirusEditor::setPart(size_t _part) + { + getParameterBinding().setPart(static_cast<uint8_t>(_part)); + onCurrentPartChanged(); + } } diff --git a/source/jucePlugin/ui3/VirusEditor.h b/source/jucePlugin/ui3/VirusEditor.h @@ -5,19 +5,46 @@ #include "Parts.h" #include "Tabs.h" +#include "PatchBrowser.h" + +class AudioPluginAudioProcessor; + namespace genericVirusUI { class VirusEditor : public genericUI::Editor { public: - VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller); + VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller, AudioPluginAudioProcessor &_processorRef); + + void setPart(size_t _part); private: void onProgramChange(); + void onPlayModeChanged(); + void onCurrentPartChanged(); + + void mouseDrag(const juce::MouseEvent& event) override; + void mouseEnter(const juce::MouseEvent& event) override; + void mouseExit(const juce::MouseEvent& event) override; + void mouseUp(const juce::MouseEvent& event) override; + + void updateControlLabel(juce::Component* _component) const; + void updatePresetName() const; + + void setPlayMode(uint8_t _playMode); Parts m_parts; Tabs m_tabs; juce::Label* m_presetName = nullptr; + juce::Label* m_controlLabel = nullptr; + juce::ComboBox* m_romSelector = nullptr; + + juce::Button* m_playModeSingle = nullptr; + juce::Button* m_playModeMulti = nullptr; + + juce::TooltipWindow m_tooltipWindow; + + PatchBrowser m_patchBrowser; }; } diff --git a/temp/cmake_win64/gearmulator.sln.DotSettings b/temp/cmake_win64/gearmulator.sln.DotSettings @@ -25,6 +25,7 @@ <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020variables/@EntryIndexedValue">&lt;NamingElement Priority="8"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="g_" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Local_0020variables/@EntryIndexedValue">&lt;NamingElement Priority="7"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="local variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Namespaces/@EntryIndexedValue">&lt;NamingElement Priority="17"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="namespace" /&gt;&lt;type Name="namespace alias" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String> + <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Other_0020constants/@EntryIndexedValue">&lt;NamingElement Priority="15"&gt;&lt;Descriptor Static="True" Constexpr="Indeterminate" Const="True" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="class field" /&gt;&lt;type Name="local variable" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Parameters/@EntryIndexedValue">&lt;NamingElement Priority="6"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="function parameter" /&gt;&lt;type Name="lambda parameter" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Typedefs/@EntryIndexedValue">&lt;NamingElement Priority="18"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="type alias" /&gt;&lt;type Name="typedef" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>