From d83e03ed4e94bf91acb2121266e369d7acb8f85b Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 26 Aug 2021 18:51:17 -0400 Subject: [PATCH] More Formula Modulator Work (#4923) 1. UI gets tabs 2. UI gets debugger panel 3. Prologue -> Prelude Addresses #2048 --- CMakeLists.txt | 4 +- src/common/LuaSupport.cpp | 14 +-- src/common/LuaSupport.h | 4 +- .../modulators/FormulaModulationHelper.cpp | 2 +- src/gui/overlays/LuaEditors.cpp | 92 +++++++++++++------ src/gui/overlays/LuaEditors.h | 13 ++- src/headless/UnitTestsLUA.cpp | 6 +- .../{surge_prologue.lua => surge_prelude.lua} | 8 +- ...ologue_test.lua => surge_prelude_test.lua} | 2 +- 9 files changed, 92 insertions(+), 53 deletions(-) rename src/lua/{surge_prologue.lua => surge_prelude.lua} (81%) rename src/lua/{surge_prologue_test.lua => surge_prelude_test.lua} (91%) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb459cc26ac..3d67c33e476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,8 +184,8 @@ juce_add_binary_data(surge-shared-binary resources/surge-shared/paramdocumentation.xml # I know this looks odd, but (1) its src and (2) I need it at runtime - src/lua/surge_prologue.lua - src/lua/surge_prologue_test.lua + src/lua/surge_prelude.lua + src/lua/surge_prelude_test.lua ) target_link_libraries(surge-shared PUBLIC diff --git a/src/common/LuaSupport.cpp b/src/common/LuaSupport.cpp index bc86a63efdd..beaca7c8226 100644 --- a/src/common/LuaSupport.cpp +++ b/src/common/LuaSupport.cpp @@ -159,15 +159,15 @@ bool Surge::LuaSupport::setSurgeFunctionEnvironment(lua_State *L) return true; } -bool Surge::LuaSupport::loadSurgePrologue(lua_State *L) +bool Surge::LuaSupport::loadSurgePrelude(lua_State *s) { - auto guard = SGLD("loadPrologue", L); + auto guard = SGLD("loadPrologue", s); // now load the surge library - auto lua_script = SurgeSharedBinary::surge_prologue_lua; - auto lua_size = SurgeSharedBinary::surge_prologue_luaSize; - auto load_stat = luaL_loadbuffer(L, lua_script, lua_size, lua_script); - auto pcall = lua_pcall(L, 0, 1, 0); - lua_setglobal(L, "surge"); + auto lua_script = SurgeSharedBinary::surge_prelude_lua; + auto lua_size = SurgeSharedBinary::surge_prelude_luaSize; + auto load_stat = luaL_loadbuffer(s, lua_script, lua_size, lua_script); + auto pcall = lua_pcall(s, 0, 1, 0); + lua_setglobal(s, "surge"); return true; } diff --git a/src/common/LuaSupport.h b/src/common/LuaSupport.h index 840d053d2ad..2a9f9c2b3c6 100644 --- a/src/common/LuaSupport.h +++ b/src/common/LuaSupport.h @@ -75,9 +75,9 @@ bool setSurgeFunctionEnvironment(lua_State *s); /* * Call this function with a LUA state and it will introduce the global - * 'surge' which is the surge prologue + * 'surge' which is the surge prelude */ -bool loadSurgePrologue(lua_State *s); +bool loadSurgePrelude(lua_State *s); /* * A little leak debugger. Make this on your stack and if you exit the diff --git a/src/common/dsp/modulators/FormulaModulationHelper.cpp b/src/common/dsp/modulators/FormulaModulationHelper.cpp index f84ad47fb8c..f50cccda65a 100644 --- a/src/common/dsp/modulators/FormulaModulationHelper.cpp +++ b/src/common/dsp/modulators/FormulaModulationHelper.cpp @@ -63,7 +63,7 @@ bool prepareForEvaluation(FormulaModulatorStorage *fs, EvaluatorState &s, bool i if (firstTimeThrough) { - Surge::LuaSupport::loadSurgePrologue(s.L); + Surge::LuaSupport::loadSurgePrelude(s.L); auto reserved0 = std::string(R"FN( function surge_reserved_formula_error_stub(m) return 0; diff --git a/src/gui/overlays/LuaEditors.cpp b/src/gui/overlays/LuaEditors.cpp index 6ba5da94deb..3dfa9e8681d 100644 --- a/src/gui/overlays/LuaEditors.cpp +++ b/src/gui/overlays/LuaEditors.cpp @@ -60,14 +60,13 @@ struct EditorColors }; CodeEditorContainerWithApply::CodeEditorContainerWithApply(SurgeGUIEditor *ed, SurgeStorage *s, - Surge::GUI::Skin::ptr_t skin) + Surge::GUI::Skin::ptr_t skin, + bool addComponents) : editor(ed), storage(s) { applyButton = std::make_unique("Apply"); applyButton->setButtonText("Apply"); - applyButton->setEnabled(false); applyButton->addListener(this); - addAndMakeVisible(applyButton.get()); mainDocument = std::make_unique(); mainDocument->addListener(this); @@ -78,7 +77,12 @@ CodeEditorContainerWithApply::CodeEditorContainerWithApply(SurgeGUIEditor *ed, S mainEditor->setTabSize(4, true); mainEditor->addKeyListener(this); EditorColors::setColorsFromSkin(mainEditor.get(), skin); - addAndMakeVisible(mainEditor.get()); + if (addComponents) + { + addAndMakeVisible(applyButton.get()); + addAndMakeVisible(mainEditor.get()); + } + applyButton->setEnabled(false); } void CodeEditorContainerWithApply::buttonClicked(juce::Button *button) @@ -114,31 +118,60 @@ bool CodeEditorContainerWithApply::keyPressed(const juce::KeyPress &key, juce::C void CodeEditorContainerWithApply::paint(juce::Graphics &g) { g.fillAll(juce::Colours::black); } +struct ExpandingFormulaDebugger : public juce::Component +{ + bool isOpen{false}; + ExpandingFormulaDebugger(FormulaModulatorEditor *ed) : editor(ed) {} + FormulaModulatorEditor *editor{nullptr}; + void paint(juce::Graphics &g) override + { + if (isOpen) + { + g.fillAll(juce::Colours::orchid); + g.setColour(juce::Colours::white); + g.drawText("Debugger", getLocalBounds(), juce::Justification::centredTop); + } + else + { + g.fillAll(juce::Colours::steelblue); + + g.setColour(juce::Colours::white); + auto h = 15, y = 10; + for (auto c : "Debugger") + { + g.drawText(std::string("") + c, 0, y, getWidth(), h, juce::Justification::centred); + y += h; + } + } + } + void mouseDown(const juce::MouseEvent &e) override + { + isOpen = !isOpen; + editor->resized(); + } +}; + FormulaModulatorEditor::FormulaModulatorEditor(SurgeGUIEditor *ed, SurgeStorage *s, FormulaModulatorStorage *fs, Surge::GUI::Skin::ptr_t skin) - : CodeEditorContainerWithApply(ed, s, skin), formulastorage(fs) + : CodeEditorContainerWithApply(ed, s, skin, false), formulastorage(fs) { mainDocument->insertText(0, fs->formulaString); + tabs = + std::make_unique(juce::TabbedButtonBar::Orientation::TabsAtBottom); + tabs->addTab("Formula", juce::Colours::red, mainEditor.get(), false); + tabs->addTab("Prelude", juce::Colours::yellow, new juce::Label("Prelude", "Coming Soon"), true); + tabs->addTab("Help", juce::Colours::green, new juce::Label("Help", "Coming Soon"), true); + addAndMakeVisible(*tabs); + + tabs->getTabbedButtonBar().addAndMakeVisible(*applyButton); - warningLabel = std::make_unique("Warning"); - warningLabel->setFont(Surge::GUI::getFontManager()->getLatoAtSize(14)); - warningLabel->setBounds(5, 5, 730, 20); - warningLabel->setColour(juce::Label::textColourId, juce::Colour(255, 0, 0)); - warningLabel->setText("WARNING: Dont use this! Super alpha! It will crash and probably won't " - "load in the future or work now. And have fun!", - juce::NotificationType::dontSendNotification); - - addAndMakeVisible(warningLabel.get()); - - lesserWarningLabel = std::make_unique("Lesser Warning"); - lesserWarningLabel->setFont(Surge::GUI::getFontManager()->getLatoAtSize(9)); - lesserWarningLabel->setText( - "We will copy the script to clipboard when you apply, just in case.", - juce::NotificationType::dontSendNotification); - addAndMakeVisible(lesserWarningLabel.get()); + efd = std::make_unique(this); + addAndMakeVisible(*efd); } +FormulaModulatorEditor::~FormulaModulatorEditor() = default; + void FormulaModulatorEditor::applyCode() { formulastorage->setFormula(mainDocument->getAllContent().toStdString()); @@ -149,13 +182,16 @@ void FormulaModulatorEditor::applyCode() void FormulaModulatorEditor::resized() { - auto w = getWidth() - 5; - auto h = getHeight() - 5; // this is a hack obvs - int m = 3, m2 = m * 2; - warningLabel->setBounds(m, m, w - m2, 20); - mainEditor->setBounds(m, 20 + m2, w - m2, h - 40 - m2 - m2); - applyButton->setBounds(m, h - 20, 50, 20 - m); - lesserWarningLabel->setBounds(m2 + 50, h - 20, w - 70, 20 - m); + int efdWidth = 14; + if (efd->isOpen) + { + efdWidth = 200; + } + tabs->setTabBarDepth(18); + tabs->setBounds(2, 2, getWidth() - 8 - efdWidth, getHeight() - 4); + auto b = tabs->getTabbedButtonBar().getLocalBounds(); + applyButton->setBounds(b.getWidth() - 80, 2, 80 - 2, b.getHeight() - 4); + efd->setBounds(getWidth() - 4 - efdWidth, 2, efdWidth, getHeight() - 4); } struct WavetablePreviewComponent : juce::Component diff --git a/src/gui/overlays/LuaEditors.h b/src/gui/overlays/LuaEditors.h index 41ade143faa..d90bde5685e 100644 --- a/src/gui/overlays/LuaEditors.h +++ b/src/gui/overlays/LuaEditors.h @@ -45,7 +45,8 @@ class CodeEditorContainerWithApply : public juce::Component, public Surge::GUI::SkinConsumingComponent { public: - CodeEditorContainerWithApply(SurgeGUIEditor *ed, SurgeStorage *s, Surge::GUI::Skin::ptr_t sk); + CodeEditorContainerWithApply(SurgeGUIEditor *ed, SurgeStorage *s, Surge::GUI::Skin::ptr_t sk, + bool addComponents = false); std::unique_ptr mainDocument; std::unique_ptr mainEditor; std::unique_ptr applyButton; @@ -64,14 +65,16 @@ class CodeEditorContainerWithApply : public juce::Component, JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CodeEditorContainerWithApply); }; -class FormulaModulatorEditor : public CodeEditorContainerWithApply +struct ExpandingFormulaDebugger; + +struct FormulaModulatorEditor : public CodeEditorContainerWithApply { - public: FormulaModulatorEditor(SurgeGUIEditor *ed, SurgeStorage *s, FormulaModulatorStorage *fs, Surge::GUI::Skin::ptr_t sk); - std::unique_ptr warningLabel; - std::unique_ptr lesserWarningLabel; + ~FormulaModulatorEditor(); + std::unique_ptr tabs; + std::unique_ptr efd; void resized() override; void applyCode() override; diff --git a/src/headless/UnitTestsLUA.cpp b/src/headless/UnitTestsLUA.cpp index 69238fe19eb..3c8c9cc9fc3 100644 --- a/src/headless/UnitTestsLUA.cpp +++ b/src/headless/UnitTestsLUA.cpp @@ -134,10 +134,10 @@ TEST_CASE("Surge Prologue", "[lua]") REQUIRE(L); luaL_openlibs(L); - REQUIRE(Surge::LuaSupport::loadSurgePrologue(L)); + REQUIRE(Surge::LuaSupport::loadSurgePrelude(L)); - auto lua_script = SurgeSharedBinary::surge_prologue_test_lua; - auto lua_size = SurgeSharedBinary::surge_prologue_test_luaSize; + auto lua_script = SurgeSharedBinary::surge_prelude_test_lua; + auto lua_size = SurgeSharedBinary::surge_prelude_test_luaSize; auto lua = std::string(lua_script, lua_size); std::string emsg; REQUIRE(Surge::LuaSupport::parseStringDefiningFunction(L, lua, "test", emsg)); diff --git a/src/lua/surge_prologue.lua b/src/lua/surge_prelude.lua similarity index 81% rename from src/lua/surge_prologue.lua rename to src/lua/surge_prelude.lua index f2c4325ebc7..b12204d37ea 100644 --- a/src/lua/surge_prologue.lua +++ b/src/lua/surge_prelude.lua @@ -1,8 +1,8 @@ --- surge_prologue +-- surge_prelude -- --- The surge prologue is loaded in each surge session and provides a set of +-- The surge prelude is loaded in each surge session and provides a set of -- built in utilities we've found handy in writing modulators. At each release --- point, we will snap the prologue as stable and not break apis after that. +-- point, we will snap the prelude as stable and not break apis after that. local surge = {} local mod = {} @@ -34,4 +34,4 @@ mod.ClockDivider.tick = function(self, intphase, phase) end surge["mod"] = mod -return surge \ No newline at end of file +return surge diff --git a/src/lua/surge_prologue_test.lua b/src/lua/surge_prelude_test.lua similarity index 91% rename from src/lua/surge_prologue_test.lua rename to src/lua/surge_prelude_test.lua index a4dadf8ac79..ae7ae924e40 100644 --- a/src/lua/surge_prologue_test.lua +++ b/src/lua/surge_prelude_test.lua @@ -1,4 +1,4 @@ --- surge = loadfile( "src/lua/surge_prologue.lua")(); loadfile("src/lua/surge_prologue_test.lua")(); print(test()) +-- surge = loadfile( "src/lua/surge_prelude.lua")(); loadfile("src/lua/surge_prelude_test.lua")(); print(test()) function test()