| @@ -818,6 +818,13 @@ | |||
| path = "../../Source/Wizards/jucer_ProjectWizard_Animated.h"; | |||
| sourceTree = "SOURCE_ROOT"; | |||
| }; | |||
| 3D36F0CEB84B27BD02FC461A = { | |||
| isa = PBXFileReference; | |||
| lastKnownFileType = sourcecode.c.h; | |||
| name = "jucer_LabelPropertyComponent.h"; | |||
| path = "../../Source/Utility/UI/PropertyComponents/jucer_LabelPropertyComponent.h"; | |||
| sourceTree = "SOURCE_ROOT"; | |||
| }; | |||
| 3D6FD9C0065BF16568EC0AB7 = { | |||
| isa = PBXFileReference; | |||
| lastKnownFileType = sourcecode.c.h; | |||
| @@ -3022,6 +3029,7 @@ | |||
| children = ( | |||
| 9EB33734D0DBD0370AB1247B, | |||
| E367FC2BDAF5EBA48D767FBB, | |||
| 3D36F0CEB84B27BD02FC461A, | |||
| 59F8A47C0020D62C8836A1E7, | |||
| ); | |||
| name = PropertyComponents; | |||
| @@ -1619,6 +1619,7 @@ | |||
| <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_Icons.h"/> | |||
| @@ -2325,6 +2325,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| @@ -1619,6 +1619,7 @@ | |||
| <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_Icons.h"/> | |||
| @@ -2325,6 +2325,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| @@ -1621,6 +1621,7 @@ | |||
| <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/> | |||
| <ClInclude Include="..\..\Source\Utility\UI\jucer_Icons.h"/> | |||
| @@ -2325,6 +2325,9 @@ | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_LabelPropertyComponent.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"> | |||
| <Filter>Projucer\Utility\UI\PropertyComponents</Filter> | |||
| </ClInclude> | |||
| @@ -657,6 +657,8 @@ | |||
| resource="0" file="Source/Utility/UI/PropertyComponents/jucer_ColourPropertyComponent.h"/> | |||
| <FILE id="sfUzaf" name="jucer_FilePathPropertyComponent.h" compile="0" | |||
| resource="0" file="Source/Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h"/> | |||
| <FILE id="c5PWPd" name="jucer_LabelPropertyComponent.h" compile="0" | |||
| resource="0" file="Source/Utility/UI/PropertyComponents/jucer_LabelPropertyComponent.h"/> | |||
| <FILE id="DkLOIQ" name="jucer_PropertyComponentsWithEnablement.h" compile="0" | |||
| resource="0" file="Source/Utility/UI/PropertyComponents/jucer_PropertyComponentsWithEnablement.h"/> | |||
| </GROUP> | |||
| @@ -26,51 +26,63 @@ | |||
| #pragma once | |||
| #include "../../Utility/UI/PropertyComponents/jucer_LabelPropertyComponent.h" | |||
| //============================================================================== | |||
| class GlobalPathsWindowComponent : public Component, | |||
| private Timer | |||
| private Timer, | |||
| private Value::Listener | |||
| { | |||
| public: | |||
| GlobalPathsWindowComponent() | |||
| { | |||
| addLabelsAndSetProperties(); | |||
| addAndMakeVisible (info); | |||
| info.setInfoToDisplay ("Use this dropdown to set the global paths for different OSes. " | |||
| "\nN.B. These paths are stored locally and will only be used when " | |||
| "saving a project on this machine. Other machines will have their own " | |||
| "locally stored paths."); | |||
| addAndMakeVisible (osSelector); | |||
| osSelector.addItem ("OSX", 1); | |||
| osSelector.addItem ("Windows", 2); | |||
| osSelector.addItem ("Linux", 3); | |||
| addChildComponent (rescanJUCEPathButton); | |||
| rescanJUCEPathButton.onClick = [this] | |||
| { | |||
| ProjucerApplication::getApp().rescanJUCEPathModules(); | |||
| lastJUCEModulePath = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get(); | |||
| }; | |||
| osSelector.onChange = [this] | |||
| addChildComponent (rescanUserPathButton); | |||
| rescanUserPathButton.onClick = [this] | |||
| { | |||
| addLabelsAndSetProperties(); | |||
| updateValues(); | |||
| updateFilePathPropertyComponents(); | |||
| ProjucerApplication::getApp().rescanUserPathModules(); | |||
| lastUserModulePath = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get(); | |||
| }; | |||
| addAndMakeVisible (resetToDefaultsButton); | |||
| resetToDefaultsButton.onClick = [this] { resetCurrentOSPathsToDefaults(); }; | |||
| addAndMakeVisible (propertyViewport); | |||
| propertyViewport.setViewedComponent (&propertyGroup, false); | |||
| auto os = TargetOS::getThisOS(); | |||
| if (os == TargetOS::osx) osSelector.setSelectedId (1); | |||
| else if (os == TargetOS::windows) osSelector.setSelectedId (2); | |||
| else if (os == TargetOS::linux) osSelector.setSelectedId (3); | |||
| if (os == TargetOS::osx) selectedOSValue = "osx"; | |||
| else if (os == TargetOS::windows) selectedOSValue = "windows"; | |||
| else if (os == TargetOS::linux) selectedOSValue = "linux"; | |||
| addChildComponent (rescanJUCEPathButton); | |||
| rescanJUCEPathButton.onClick = [] { ProjucerApplication::getApp().rescanJUCEPathModules(); }; | |||
| selectedOSValue.addListener (this); | |||
| addChildComponent (rescanUserPathButton); | |||
| rescanUserPathButton.onClick = [] { ProjucerApplication::getApp().rescanUserPathModules(); }; | |||
| buildProps(); | |||
| addAndMakeVisible (resetToDefaultsButton); | |||
| resetToDefaultsButton.onClick = [this] { resetCurrentOSPathsToDefaults(); }; | |||
| lastJUCEModulePath = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get(); | |||
| lastUserModulePath = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get(); | |||
| } | |||
| updateValues(); | |||
| updateFilePathPropertyComponents(); | |||
| ~GlobalPathsWindowComponent() | |||
| { | |||
| auto juceValue = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()); | |||
| auto userValue = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()); | |||
| auto jucePathNeedsScanning = (! juceValue.isUsingDefault() && juceValue.get() != lastJUCEModulePath); | |||
| auto userPathNeedsScanning = (! userValue.isUsingDefault() && userValue.get() != lastUserModulePath); | |||
| if (jucePathNeedsScanning) | |||
| ProjucerApplication::getApp().rescanJUCEPathModules(); | |||
| if (userPathNeedsScanning) | |||
| ProjucerApplication::getApp().rescanUserPathModules(); | |||
| } | |||
| void paint (Graphics& g) override | |||
| @@ -88,59 +100,31 @@ public: | |||
| { | |||
| auto b = getLocalBounds().reduced (10); | |||
| auto topSlice = b.removeFromTop (25); | |||
| osSelector.setSize (200, 25); | |||
| osSelector.setCentrePosition (topSlice.getCentre()); | |||
| info.setBounds (osSelector.getBounds().withWidth (osSelector.getHeight()).translated ((osSelector.getWidth() + 5), 0).reduced (2)); | |||
| auto buttonBounds = b.removeFromBottom (50); | |||
| int labelIndex = 0; | |||
| bool isFirst = true; | |||
| bool showRescanButtons = (rescanJUCEPathButton.isVisible() && rescanUserPathButton.isVisible()); | |||
| rescanJUCEPathButton.setBounds (buttonBounds.removeFromLeft (150).reduced (5, 10)); | |||
| rescanUserPathButton.setBounds (buttonBounds.removeFromLeft (150).reduced (5, 10)); | |||
| for (auto* pathComp : pathPropertyComponents) | |||
| { | |||
| if (pathComp == nullptr) | |||
| { | |||
| b.removeFromTop (15); | |||
| pathPropertyLabels.getUnchecked (labelIndex++)->setBounds (b.removeFromTop (20)); | |||
| b.removeFromTop (20); | |||
| } | |||
| else | |||
| { | |||
| if (isFirst) | |||
| b.removeFromTop (20); | |||
| auto compBounds = b.removeFromTop (pathComp->getPreferredHeight()); | |||
| if (showRescanButtons) | |||
| { | |||
| auto propName = pathComp->getName(); | |||
| if (propName == "JUCE Modules") | |||
| rescanJUCEPathButton.setBounds (compBounds.removeFromRight (75).reduced (5, 0)); | |||
| else if (propName == "User Modules") | |||
| rescanUserPathButton.setBounds (compBounds.removeFromRight (75).reduced (5, 0)); | |||
| } | |||
| pathComp->setBounds (compBounds); | |||
| b.removeFromTop (5); | |||
| } | |||
| isFirst = false; | |||
| } | |||
| resetToDefaultsButton.setBounds (buttonBounds.removeFromRight (150).reduced (5, 10)); | |||
| resetToDefaultsButton.setBounds (b.removeFromBottom (35).reduced (150, 0)); | |||
| propertyGroup.updateSize (0, 0, getWidth() - 20 - propertyViewport.getScrollBarThickness()); | |||
| propertyViewport.setBounds (b); | |||
| } | |||
| void highlightJUCEPath() | |||
| { | |||
| if (! isTimerRunning() && isSelectedOSThisOS()) | |||
| { | |||
| if (auto* jucePathComp = pathPropertyComponents.getFirst()) | |||
| boundsToHighlight = jucePathComp->getBounds(); | |||
| if (isTimerRunning() || ! isSelectedOSThisOS()) | |||
| return; | |||
| PropertyComponent* jucePathPropertyComponent = nullptr; | |||
| for (auto* prop : propertyGroup.properties) | |||
| if (prop->getName() == "Path to JUCE") | |||
| jucePathPropertyComponent = prop; | |||
| if (jucePathPropertyComponent != nullptr) | |||
| { | |||
| boundsToHighlight = getLocalArea (&propertyGroup, jucePathPropertyComponent->getBounds()); | |||
| flashAlpha = 0.0f; | |||
| hasFlashed = false; | |||
| @@ -149,22 +133,6 @@ public: | |||
| } | |||
| private: | |||
| ValueWithDefault jucePathValue, juceModulePathValue, userModulePathValue, vst3PathValue, rtasPathValue, aaxPathValue, | |||
| androidSDKPathValue, androidNDKPathValue, clionExePathValue, androidStudioExePathValue; | |||
| OwnedArray<Label> pathPropertyLabels; | |||
| OwnedArray<PropertyComponent> pathPropertyComponents; | |||
| TextButton rescanJUCEPathButton { "Re-scan" }, | |||
| rescanUserPathButton { "Re-scan" }, | |||
| resetToDefaultsButton { "Reset to Defaults" }; | |||
| ComboBox osSelector; | |||
| InfoButton info; | |||
| Rectangle<int> boundsToHighlight; | |||
| float flashAlpha = 0.0f; | |||
| bool hasFlashed = false; | |||
| //============================================================================== | |||
| void timerCallback() override | |||
| { | |||
| @@ -185,61 +153,79 @@ private: | |||
| repaint(); | |||
| } | |||
| void valueChanged (Value&) override | |||
| { | |||
| buildProps(); | |||
| resized(); | |||
| } | |||
| //============================================================================== | |||
| bool isSelectedOSThisOS() { return TargetOS::getThisOS() == getSelectedOS(); } | |||
| TargetOS::OS getSelectedOS() const | |||
| { | |||
| auto selectedOS = TargetOS::unknown; | |||
| auto val = selectedOSValue.getValue(); | |||
| switch (osSelector.getSelectedId()) | |||
| { | |||
| case 1: selectedOS = TargetOS::osx; break; | |||
| case 2: selectedOS = TargetOS::windows; break; | |||
| case 3: selectedOS = TargetOS::linux; break; | |||
| default: break; | |||
| } | |||
| if (val == "osx") return TargetOS::osx; | |||
| else if (val == "windows") return TargetOS::windows; | |||
| else if (val == "linux") return TargetOS::linux; | |||
| return selectedOS; | |||
| jassertfalse; | |||
| return TargetOS::unknown; | |||
| } | |||
| void updateFilePathPropertyComponents() | |||
| //============================================================================== | |||
| void buildProps() | |||
| { | |||
| pathPropertyComponents.clear(); | |||
| updateValues(); | |||
| PropertyListBuilder builder; | |||
| auto isThisOS = isSelectedOSThisOS(); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (jucePathValue, "Path to JUCE", true, isThisOS))); | |||
| builder.add (new ChoicePropertyComponent (selectedOSValue, "OS", { "OSX", "Windows", "Linux" }, { "osx", "windows", "linux" }), | |||
| "Use this dropdown to set the global paths for different OSes. " | |||
| "\nN.B. These paths are stored locally and will only be used when " | |||
| "saving a project on this machine. Other machines will have their own " | |||
| "locally stored paths."); | |||
| pathPropertyComponents.add (nullptr); | |||
| builder.add (new LabelPropertyComponent ("JUCE"), {}); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (juceModulePathValue, "JUCE Modules", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS, {}, {}, true))); | |||
| builder.add (new FilePathPropertyComponent (jucePathValue, "Path to JUCE", true, isThisOS), | |||
| "This should be the path to the top-level directory of your JUCE folder. " | |||
| "This path will be used when searching for the JUCE examples and DemoRunner application."); | |||
| pathPropertyComponents.add (nullptr); | |||
| builder.add (new FilePathPropertyComponent (juceModulePathValue, "JUCE Modules", true, isThisOS), | |||
| String ("This should be the path to the folder containing the JUCE modules that you wish to use, typically the \"modules\" directory of your JUCE folder.") | |||
| + (isThisOS ? " Use the button below to re-scan a new path." : "")); | |||
| builder.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS, {}, {}, true), | |||
| String ("A semicolon-separated list of user module paths. These paths will be used to display any non-JUCE modules that are available.") | |||
| + (isThisOS ? " Use the button below to re-scan new paths." : "")); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (vst3PathValue, "Custom VST3 SDK", true, isThisOS))); | |||
| builder.add (new LabelPropertyComponent ("SDKs"), {}); | |||
| if (getSelectedOS() == TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "AAX SDK", true, isThisOS))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| builder.add (new FilePathPropertyComponent (vstPathValue, "VST (Legacy) SDK", true, isThisOS), | |||
| "If you are building a legacy VST plug-in then this path should point to a VST2 SDK. " | |||
| "The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK or JUCE version 5.3.2. " | |||
| "You also need a VST2 license from Steinberg to distribute VST2 plug-ins."); | |||
| builder.add (new FilePathPropertyComponent (vst3PathValue, "VST3 SDK", true, isThisOS), | |||
| "This path can be set to use a custom VST3 SDK instead of the one which is embedded in JUCE."); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (Value(), "RTAS SDK", true, isThisOS))); | |||
| pathPropertyComponents.getLast()->setEnabled (false); | |||
| } | |||
| else | |||
| if (getSelectedOS() != TargetOS::linux) | |||
| { | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (aaxPathValue, "AAX SDK", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (rtasPathValue, "RTAS SDK", true, isThisOS))); | |||
| builder.add (new FilePathPropertyComponent (aaxPathValue, "AAX SDK", true, isThisOS), | |||
| "If you are building AAX plug-ins, this should be the path to the AAX SDK folder."); | |||
| builder.add (new FilePathPropertyComponent (rtasPathValue, "RTAS SDK", true, isThisOS), | |||
| "If you are building RTAS plug-ins, this should be the path to the RTAS SDK folder."); | |||
| } | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidSDKPathValue, "Android SDK", true, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidNDKPathValue, "Android NDK", true, isThisOS))); | |||
| builder.add (new FilePathPropertyComponent (androidSDKPathValue, "Android SDK", true, isThisOS), | |||
| "This path will be used when writing the local.properties file of an Android project and should point to the Android SDK folder."); | |||
| builder.add (new FilePathPropertyComponent (androidNDKPathValue, "Android NDK", true, isThisOS), | |||
| "This path will be used when writing the local.properties file of an Android project and should point to the Android NDK folder."); | |||
| if (isThisOS) | |||
| { | |||
| pathPropertyComponents.add (nullptr); | |||
| builder.add (new LabelPropertyComponent ("Other"), {}); | |||
| #if JUCE_MAC | |||
| String exeLabel ("app"); | |||
| @@ -249,8 +235,10 @@ private: | |||
| String exeLabel ("startup script"); | |||
| #endif | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (clionExePathValue, "CLion " + exeLabel, false, isThisOS))); | |||
| addAndMakeVisible (pathPropertyComponents.add (new FilePathPropertyComponent (androidStudioExePathValue, "Android Studio " + exeLabel, false, isThisOS))); | |||
| builder.add (new FilePathPropertyComponent (clionExePathValue, "CLion " + exeLabel, false, isThisOS), | |||
| "This path will be used for the \"Save Project and Open in IDE...\" option of the CLion exporter."); | |||
| builder.add (new FilePathPropertyComponent (androidStudioExePathValue, "Android Studio " + exeLabel, false, isThisOS), | |||
| "This path will be used for the \"Save Project and Open in IDE...\" option of the Android Studio exporter."); | |||
| rescanJUCEPathButton.setVisible (true); | |||
| rescanUserPathButton.setVisible (true); | |||
| @@ -261,7 +249,7 @@ private: | |||
| rescanUserPathButton.setVisible (false); | |||
| } | |||
| resized(); | |||
| propertyGroup.setProperties (builder); | |||
| } | |||
| void updateValues() | |||
| @@ -272,6 +260,7 @@ private: | |||
| jucePathValue = settings.getStoredPath (Ids::jucePath, os); | |||
| juceModulePathValue = settings.getStoredPath (Ids::defaultJuceModulePath, os); | |||
| userModulePathValue = settings.getStoredPath (Ids::defaultUserModulePath, os); | |||
| vstPathValue = settings.getStoredPath (Ids::vstLegacyPath, os); | |||
| vst3PathValue = settings.getStoredPath (Ids::vst3Path, os); | |||
| rtasPathValue = settings.getStoredPath (Ids::rtasPath, os); | |||
| aaxPathValue = settings.getStoredPath (Ids::aaxPath, os); | |||
| @@ -281,27 +270,12 @@ private: | |||
| androidStudioExePathValue = settings.getStoredPath (Ids::androidStudioExePath, os); | |||
| } | |||
| void addLabelsAndSetProperties() | |||
| { | |||
| pathPropertyLabels.clear(); | |||
| pathPropertyLabels.add (new Label ("modulesLabel", "Modules")); | |||
| pathPropertyLabels.add (new Label ("sdksLabel", "SDKs")); | |||
| pathPropertyLabels.add (new Label ("otherLabel", "Other")); | |||
| for (auto* l : pathPropertyLabels) | |||
| { | |||
| addAndMakeVisible (l); | |||
| l->setFont (Font (18.0f, Font::FontStyleFlags::bold)); | |||
| l->setJustificationType (Justification::centredLeft); | |||
| } | |||
| } | |||
| void resetCurrentOSPathsToDefaults() | |||
| { | |||
| jucePathValue .resetToDefault(); | |||
| juceModulePathValue .resetToDefault(); | |||
| userModulePathValue .resetToDefault(); | |||
| vstPathValue .resetToDefault(); | |||
| vst3PathValue .resetToDefault(); | |||
| rtasPathValue .resetToDefault(); | |||
| aaxPathValue .resetToDefault(); | |||
| @@ -313,6 +287,27 @@ private: | |||
| repaint(); | |||
| } | |||
| //============================================================================== | |||
| Value selectedOSValue; | |||
| ValueWithDefault jucePathValue, juceModulePathValue, userModulePathValue, | |||
| vst3PathValue, vstPathValue, rtasPathValue, aaxPathValue, | |||
| androidSDKPathValue, androidNDKPathValue, | |||
| clionExePathValue, androidStudioExePathValue; | |||
| Viewport propertyViewport; | |||
| PropertyGroupComponent propertyGroup { "Global Paths", { getIcons().openFolder, Colours::transparentBlack } }; | |||
| TextButton rescanJUCEPathButton { "Re-scan JUCE Modules" }, | |||
| rescanUserPathButton { "Re-scan User Modules" }, | |||
| resetToDefaultsButton { "Reset to Defaults" }; | |||
| Rectangle<int> boundsToHighlight; | |||
| float flashAlpha = 0.0f; | |||
| bool hasFlashed = false; | |||
| var lastJUCEModulePath, lastUserModulePath; | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalPathsWindowComponent) | |||
| }; | |||
| @@ -1297,7 +1297,7 @@ void ProjucerApplication::showPathsWindow (bool highlightJUCEPath) | |||
| else | |||
| new FloatingToolWindow ("Global Paths", "pathsWindowPos", | |||
| new GlobalPathsWindowComponent(), pathsWindow, false, | |||
| 600, 650, 600, 650, 600, 650); | |||
| 600, 700, 600, 700, 600, 700); | |||
| if (highlightJUCEPath) | |||
| if (auto* pathsComp = dynamic_cast<GlobalPathsWindowComponent*> (pathsWindow->getChildComponent (0))) | |||
| @@ -1042,11 +1042,11 @@ void Project::createPropertyEditors (PropertyListBuilder& props) | |||
| void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) | |||
| { | |||
| props.add (new MultiChoicePropertyComponent (pluginFormatsValue, "Plugin Formats", | |||
| { "VST3", "AU", "AUv3", "RTAS", "AAX", "Standalone", "Unity", "Enable IAA", "VST (legacy)" }, | |||
| { "VST3", "AU", "AUv3", "RTAS", "AAX", "Standalone", "Unity", "Enable IAA", "VST (Legacy)" }, | |||
| { Ids::buildVST3.toString(), Ids::buildAU.toString(), Ids::buildAUv3.toString(), | |||
| Ids::buildRTAS.toString(), Ids::buildAAX.toString(), Ids::buildStandalone.toString(), Ids::buildUnity.toString(), | |||
| Ids::enableIAA.toString(), Ids::buildVST.toString() }), | |||
| "Plugin formats to build. If you have selected \"VST (legacy)\" then you will need to ensure that you have a VST2 SDK " | |||
| "Plugin formats to build. If you have selected \"VST (Legacy)\" then you will need to ensure that you have a VST2 SDK " | |||
| "in your header search paths. The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK " | |||
| "or JUCE version 5.3.2. You also need a VST2 license from Steinberg to distribute VST2 plug-ins."); | |||
| props.add (new MultiChoicePropertyComponent (pluginCharacteristicsValue, "Plugin Characteristics", | |||
| @@ -1102,7 +1102,7 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) | |||
| for (auto s : getAllVSTCategoryStrings()) | |||
| vstCategoryVars.add (s); | |||
| props.add (new MultiChoicePropertyComponent (pluginVSTCategoryValue, "Plugin VST (legacy) Category", getAllVSTCategoryStrings(), vstCategoryVars, 1), | |||
| props.add (new MultiChoicePropertyComponent (pluginVSTCategoryValue, "Plugin VST (Legacy) Category", getAllVSTCategoryStrings(), vstCategoryVars, 1), | |||
| "VST category."); | |||
| } | |||
| } | |||
| @@ -100,9 +100,17 @@ public: | |||
| //============================================================================== | |||
| void initialiseDependencyPathValues() override | |||
| { | |||
| vst3PathValueWrapper.init ({ settings, Ids::vst3Folder, nullptr }, getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::windows), TargetOS::windows); | |||
| aaxPathValueWrapper .init ({ settings, Ids::aaxFolder, nullptr }, getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::windows), TargetOS::windows); | |||
| rtasPathValueWrapper.init ({ settings, Ids::rtasFolder, nullptr }, getAppSettings().getStoredPath (Ids::rtasPath, TargetOS::windows), TargetOS::windows); | |||
| vstLegacyPathValueWrapper.init ({ settings, Ids::vstLegacyFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::vstLegacyPath, TargetOS::windows), TargetOS::windows); | |||
| vst3PathValueWrapper.init ({ settings, Ids::vst3Folder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::windows), TargetOS::windows); | |||
| aaxPathValueWrapper.init ({ settings, Ids::aaxFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::windows), TargetOS::windows); | |||
| rtasPathValueWrapper.init ({ settings, Ids::rtasFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::rtasPath, TargetOS::windows), TargetOS::windows); | |||
| } | |||
| //============================================================================== | |||
| @@ -322,7 +330,7 @@ public: | |||
| "The folder in which the compiled Unity plugin binary and associated C# GUI script should be placed."); | |||
| if (project.shouldBuildVST()) | |||
| props.add (new TextPropertyComponentWithEnablement (vstBinaryLocation, pluginBinaryCopyStepValue, "VST (legacy) Binary Location", | |||
| props.add (new TextPropertyComponentWithEnablement (vstBinaryLocation, pluginBinaryCopyStepValue, "VST (Legacy) Binary Location", | |||
| 1024, false), | |||
| "The folder in which the compiled lehacy VST binary should be placed."); | |||
| @@ -445,9 +445,17 @@ public: | |||
| //============================================================================== | |||
| void initialiseDependencyPathValues() override | |||
| { | |||
| vst3PathValueWrapper.init ({ settings, Ids::vst3Folder, nullptr }, getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::osx), TargetOS::osx); | |||
| aaxPathValueWrapper .init ({ settings, Ids::aaxFolder, nullptr }, getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::osx), TargetOS::osx); | |||
| rtasPathValueWrapper.init ({ settings, Ids::rtasFolder, nullptr }, getAppSettings().getStoredPath (Ids::rtasPath, TargetOS::osx), TargetOS::osx); | |||
| vstLegacyPathValueWrapper.init ({ settings, Ids::vstLegacyFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::vstLegacyPath, TargetOS::osx), TargetOS::osx); | |||
| vst3PathValueWrapper.init ({ settings, Ids::vst3Folder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::osx), TargetOS::osx); | |||
| aaxPathValueWrapper.init ({ settings, Ids::aaxFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::osx), TargetOS::osx); | |||
| rtasPathValueWrapper.init ({ settings, Ids::rtasFolder, nullptr }, | |||
| getAppSettings().getStoredPath (Ids::rtasPath, TargetOS::osx), TargetOS::osx); | |||
| } | |||
| protected: | |||
| @@ -298,6 +298,13 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) | |||
| "The location of the folder in which the " + name + " project will be created. " | |||
| "This path can be absolute, but it's much more sensible to make it relative to the jucer project directory."); | |||
| if (shouldBuildTargetType (ProjectType::Target::VSTPlugIn) && project.shouldBuildVST()) | |||
| { | |||
| props.add (new FilePathPropertyComponent (vstLegacyPathValueWrapper.wrappedValue, "VST (Legacy) SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS()), | |||
| "If you're building a VST plug-in, you can use this field to override the global VST (Legacy) SDK path with a project-specific path. " | |||
| "This can be an absolute path, or a path relative to the Projucer project file."); | |||
| } | |||
| if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) | |||
| { | |||
| props.add (new FilePathPropertyComponent (vst3PathValueWrapper.wrappedValue, "VST3 SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS()), | |||
| @@ -385,7 +392,10 @@ void ProjectExporter::addVSTPathsIfPluginOrHost() | |||
| { | |||
| if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) || project.isVST3PluginHost() | |||
| || shouldBuildTargetType (ProjectType::Target::VSTPlugIn) || project.isVSTPluginHost()) | |||
| { | |||
| addLegacyVSTFolderToPathIfSpecified(); | |||
| addVST3FolderToPath(); | |||
| } | |||
| } | |||
| void ProjectExporter::addCommonAudioPluginSettings() | |||
| @@ -396,6 +406,14 @@ void ProjectExporter::addCommonAudioPluginSettings() | |||
| // Note: RTAS paths are platform-dependent, impl -> addPlatformSpecificSettingsForProjectType | |||
| } | |||
| void ProjectExporter::addLegacyVSTFolderToPathIfSpecified() | |||
| { | |||
| auto vstFolder = getVSTLegacyPathString(); | |||
| if (vstFolder.isNotEmpty()) | |||
| addToExtraSearchPaths (RelativePath (vstFolder, RelativePath::projectFolder), 0); | |||
| } | |||
| RelativePath ProjectExporter::getInternalVST3SDKPath() | |||
| { | |||
| return getModuleFolderRelativeToProject ("juce_audio_processors") | |||
| @@ -153,6 +153,7 @@ public: | |||
| bool shouldUseGNUExtensions() const { return gnuExtensionsValue.get(); } | |||
| String getVSTLegacyPathString() const { return vstLegacyPathValueWrapper.wrappedValue.get(); } | |||
| String getVST3PathString() const { return vst3PathValueWrapper.wrappedValue.get(); } | |||
| String getAAXPathString() const { return aaxPathValueWrapper.wrappedValue.get(); } | |||
| String getRTASPathString() const { return rtasPathValueWrapper.wrappedValue.get(); } | |||
| @@ -400,7 +401,7 @@ protected: | |||
| TargetOS::OS os; | |||
| }; | |||
| ValueWithDefaultWrapper vst3PathValueWrapper, rtasPathValueWrapper, aaxPathValueWrapper; | |||
| ValueWithDefaultWrapper vstLegacyPathValueWrapper, vst3PathValueWrapper, rtasPathValueWrapper, aaxPathValueWrapper; | |||
| ValueWithDefault targetLocationValue, extraCompilerFlagsValue, extraLinkerFlagsValue, externalLibrariesValue, | |||
| userNotesValue, gnuExtensionsValue, bigIconValue, smallIconValue, extraPPDefsValue; | |||
| @@ -476,6 +477,7 @@ private: | |||
| void createIconProperties (PropertyListBuilder&); | |||
| void addVSTPathsIfPluginOrHost(); | |||
| void addCommonAudioPluginSettings(); | |||
| void addLegacyVSTFolderToPathIfSpecified(); | |||
| RelativePath getInternalVST3SDKPath(); | |||
| void addVST3FolderToPath(); | |||
| void addAAXFoldersToPath(); | |||
| @@ -281,6 +281,10 @@ static bool isGlobalPathValid (const File& relativeTo, const Identifier& key, co | |||
| { | |||
| String fileToCheckFor; | |||
| if (key == Ids::vstLegacyPath) | |||
| { | |||
| fileToCheckFor = "pluginterfaces/vst2.x/aeffect.h"; | |||
| } | |||
| if (key == Ids::vst3Path) | |||
| { | |||
| fileToCheckFor = "base/source/baseiids.cpp"; | |||
| @@ -391,7 +395,7 @@ static String getFallbackPathForOS (const Identifier& key, DependencyPathOS os) | |||
| { | |||
| return (os == TargetOS::windows ? "C:\\modules" : "~/modules"); | |||
| } | |||
| else if (key == Ids::vst3Path) | |||
| else if (key == Ids::vstLegacyPath || key == Ids::vst3Path) | |||
| { | |||
| return {}; | |||
| } | |||
| @@ -68,9 +68,11 @@ namespace Ids | |||
| DECLARE_ID (jucePath); | |||
| DECLARE_ID (defaultJuceModulePath); | |||
| DECLARE_ID (defaultUserModulePath); | |||
| DECLARE_ID (vstLegacyFolder); | |||
| DECLARE_ID (vst3Folder); | |||
| DECLARE_ID (rtasFolder); | |||
| DECLARE_ID (auFolder); | |||
| DECLARE_ID (vstLegacyPath); | |||
| DECLARE_ID (vst3Path); | |||
| DECLARE_ID (rtasPath); | |||
| DECLARE_ID (aaxPath); | |||
| @@ -0,0 +1,74 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| JUCE is an open source library subject to commercial or open-source | |||
| licensing. | |||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||
| Or: You may also use this code under the terms of the GPL v3 (see | |||
| www.gnu.org/licenses). | |||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||
| DISCLAIMED. | |||
| ============================================================================== | |||
| */ | |||
| #pragma once | |||
| //============================================================================== | |||
| class LabelPropertyComponent : public PropertyComponent | |||
| { | |||
| public: | |||
| LabelPropertyComponent (const String& labelText, int propertyHeight = 25, | |||
| Font labelFont = Font (16.0f, Font::bold), | |||
| Justification labelJustification = Justification::centred) | |||
| : PropertyComponent (labelText), | |||
| labelToDisplay ({}, labelText) | |||
| { | |||
| setPreferredHeight (propertyHeight); | |||
| labelToDisplay.setJustificationType (labelJustification); | |||
| labelToDisplay.setFont (labelFont); | |||
| addAndMakeVisible (labelToDisplay); | |||
| setLookAndFeel (&lf); | |||
| } | |||
| ~LabelPropertyComponent() { setLookAndFeel (nullptr); } | |||
| //============================================================================== | |||
| void refresh() override {} | |||
| void resized() override | |||
| { | |||
| labelToDisplay.setBounds (getLocalBounds()); | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| struct LabelLookAndFeel : public ProjucerLookAndFeel | |||
| { | |||
| void drawPropertyComponentLabel (Graphics&, int, int, PropertyComponent&) {} | |||
| }; | |||
| void lookAndFeelChanged() override | |||
| { | |||
| labelToDisplay.setColour (Label::textColourId, ProjucerApplication::getApp().lookAndFeel.findColour (defaultTextColourId)); | |||
| } | |||
| //============================================================================== | |||
| LabelLookAndFeel lf; | |||
| Label labelToDisplay; | |||
| }; | |||