From dec0772c413b243bbbf6406c041d67a6c79a8822 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Mon, 28 Jan 2019 15:53:49 -0500 Subject: [PATCH] Implement VST3 zoom VST3 zoom is very similar to VST2 zoom since both rely on VSTGUI (and the associated bugs therein), but differ on the approach to notify the host. The primary difference in notifying the host is requiring a reference to the Steinberg::IPlugFrame frame class, which has to be publically exposed to allow the processor to see it. (This may be indicative of issues still with us choosing to not have a formal processor/editor split, as mentioned in #164). Regardless, once the IPlugFrame is exposed, we can use the resizeView() API in vst3 to inform hosts in our zoom callback, as implemented here. --- build-osx.sh | 13 ++++++++ src/common/gui/SurgeGUIEditor.cpp | 13 ++++++-- src/common/gui/SurgeGUIEditor.h | 15 +++++++++- src/vst3/SurgeVst3Processor.cpp | 50 +++++++++++++++++++++++++++++++ src/vst3/SurgeVst3Processor.h | 2 ++ 5 files changed, 90 insertions(+), 3 deletions(-) diff --git a/build-osx.sh b/build-osx.sh index de14184c7a3..a38ebadde8b 100755 --- a/build-osx.sh +++ b/build-osx.sh @@ -37,6 +37,7 @@ Commands are: --build-and-install Build and install the assets --build-validate-au Build and install the audio unit then validate it --build-install-vst2 Build and install only the VST2 + --build-install-vst3 Build and install only the VST3 --package Creates a .pkg file from current built state in products --clean-and-package Cleans everything; runs all the builds; makes an installer; drops it in products @@ -214,6 +215,15 @@ run_build_install_vst2() rsync -r --delete "products/Surge.vst/" ~/Library/Audio/Plug-Ins/VST/Surge.vst/ } +run_build_install_vst3() +{ + run_premake_if + run_build "vst3" + + rsync -r "resources/data/" "$HOME/Library/Application Support/Surge/" + rsync -r --delete "products/Surge.vst3/" ~/Library/Audio/Plug-Ins/VST3/Surge.vst3/ +} + run_clean_builds() { if [ ! -d "Surge.xcworkspace" ]; then @@ -307,6 +317,9 @@ case $command in --build-install-vst2) run_build_install_vst2 ;; + --build-install-vst3) + run_build_install_vst3 + ;; --clean) run_clean_builds ;; diff --git a/src/common/gui/SurgeGUIEditor.cpp b/src/common/gui/SurgeGUIEditor.cpp index 42380c10b5d..a52751d4824 100644 --- a/src/common/gui/SurgeGUIEditor.cpp +++ b/src/common/gui/SurgeGUIEditor.cpp @@ -2433,12 +2433,21 @@ void SurgeGUIEditor::setZoomFactor(int zf) #endif CRect screenDim = Surge::GUI::getScreenDimensions(getFrame()); + +#if TARGET_VST3 + /* + ** VST3 doesn't have this API available to it, so just assume for now + */ + float baseW = WINDOW_SIZE_X; + float baseH = WINDOW_SIZE_Y; +#else ERect *baseUISize; getRect (&baseUISize); float baseW = (baseUISize->right - baseUISize->left); float baseH = (baseUISize->top - baseUISize->bottom); - +#endif + // Leave enough room for window decoration with that .9. (You can probably do .95 on mac) if (zf != 100.0 && ( (baseW * zf / 100.0) > 0.9 * screenDim.getWidth() || @@ -2566,7 +2575,7 @@ CPoint SurgeGUIEditor::getCurrentMouseLocationCorrectedForVSTGUIBugs() frame->getCurrentMouseLocation(where); where = frame->localToFrame(where); -#if TARGET_VST2 && HOST_SUPPORTS_ZOOM +#if ( TARGET_VST2 || TARGET_VST3 ) && HOST_SUPPORTS_ZOOM CGraphicsTransform vstfix = frame->getTransform().inverse(); vstfix.transform(where); vstfix.transform(where); diff --git a/src/common/gui/SurgeGUIEditor.h b/src/common/gui/SurgeGUIEditor.h index af318325fd5..956732de99b 100644 --- a/src/common/gui/SurgeGUIEditor.h +++ b/src/common/gui/SurgeGUIEditor.h @@ -82,6 +82,19 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi */ VSTGUI::CPoint getCurrentMouseLocationCorrectedForVSTGUIBugs(); +#if TARGET_VST3 +public: + /** + * getIPlugFrame + * + * Amazingly, IPlugView has a setFrame( IPlugFrame ) method but + * no getter. It does, however, store the value as a protected + * variable. To collaborate for zoom, we need this reference + * in the VST Processor, so expose this function + */ + Steinberg::IPlugFrame *getIPlugFrame() { return plugFrame; } +#endif + private: void openOrRecreateEditor(); void close_editor(); @@ -153,6 +166,6 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi VSTGUI::CVSTGUITimer* _idleTimer = nullptr; }; -#if ( MAC && ( TARGET_AUDIOUNIT || TARGET_VST2 ) ) || (WINDOWS && TARGET_VST2 ) +#if MAC || WINDOWS #define HOST_SUPPORTS_ZOOM 1 #endif diff --git a/src/vst3/SurgeVst3Processor.cpp b/src/vst3/SurgeVst3Processor.cpp index edb3cd31937..d064ef5a151 100644 --- a/src/vst3/SurgeVst3Processor.cpp +++ b/src/vst3/SurgeVst3Processor.cpp @@ -10,6 +10,8 @@ #include "pluginterfaces/vst/ivstevents.h" #include "pluginterfaces/base/ustring.h" +#include "CScalableBitmap.h" + using namespace Steinberg::Vst; #define CHECK_INITIALIZED \ @@ -402,6 +404,8 @@ IPlugView* PLUGIN_API SurgeVst3Processor::createView(const char* name) { SurgeGUIEditor* editor = new SurgeGUIEditor(this, surgeInstance.get()); + editor->setZoomCallback( [this](SurgeGUIEditor *e) { handleZoom(e); } ); + return editor; } return nullptr; @@ -601,3 +605,49 @@ void SurgeVst3Processor::setParameterAutomated(int externalparam, float value) performEdit(externalparam, value); endEdit(externalparam); } + +void SurgeVst3Processor::handleZoom(SurgeGUIEditor *e) +{ + float fzf = e->getZoomFactor() / 100.0; + int newW = WINDOW_SIZE_X * fzf; + int newH = WINDOW_SIZE_Y * fzf; + + + VSTGUI::CFrame *frame = e->getFrame(); + if(frame) + { + frame->setZoom( e->getZoomFactor() / 100.0 ); + + /* + ** rather than calling setSize on myself as in vst2, I have to + ** inform the plugin frame that I have resized wiht a reference + ** to a view (which is the editor). This collaborates with + ** the host to resize once the content is scaled + */ + Steinberg::IPlugFrame *ipf = e->getIPlugFrame(); + if (ipf) + { + Steinberg::ViewRect vr( 0, 0, newW, newH ); + ipf->resizeView( e, &vr ); + } + + /* + ** VSTGUI has an error which is that the background bitmap doesn't get the frame transform + ** applied. Simply look at cviewcontainer::drawBackgroundRect. So we have to force the background + ** scale up using a backdoor API. + */ + + VSTGUI::CBitmap *bg = frame->getBackground(); + if(bg != NULL) + { + CScalableBitmap *sbm = dynamic_cast(bg); // dynamic casts are gross but better safe + if (sbm) + { + sbm->setExtraScaleFactor( e->getZoomFactor() ); + } + } + + frame->setDirty( true ); + frame->invalid(); + } +} diff --git a/src/vst3/SurgeVst3Processor.h b/src/vst3/SurgeVst3Processor.h index e837e4cb5d4..60433bca50c 100644 --- a/src/vst3/SurgeVst3Processor.h +++ b/src/vst3/SurgeVst3Processor.h @@ -121,5 +121,7 @@ class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect //, publ std::vector viewsArray; int blockpos; + void handleZoom(SurgeGUIEditor *e); + FpuState _fpuState; };