ReaWwise

REAPER extension
Log | Files | Refs | Submodules

commit c219000188fedbc59466253f5a5a0783dd2abc60
parent 0a0326675c0bc5d35e1710c29f43df5761d42850
Author: James Stubbs <jstubbs@audiokinetic.com>
Date:   Fri, 21 Jun 2024 11:20:36 -0400

ReaWwise v1.0.6a

Features:

- Added the ability to transfer files from REAPER to an instance of Wwise located on a different machine.

Change-Id: I8ff1dbc483def289e9d4ad9841013af6b5bd4e79

Diffstat:
MPackage.instrument | 26++++++++++++++++++++++++++
Abundle_template.json | 15+++++++++++++++
Msrc/shared/Core/AssertHook.cpp | 1-
Msrc/shared/Core/ImportTask.h | 2+-
Msrc/shared/Core/WaapiClient.cpp | 150++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/shared/Core/WaapiClient.h | 13+++++++++++--
Msrc/shared/Helpers/StringHelper.h | 3+--
Msrc/shared/Model/Import.h | 2++
Msrc/shared/Model/Waapi.h | 2++
Msrc/shared/Persistance/ApplicationProperties.cpp | 44++++++++++++++++++++++++++++++++++++++++----
Msrc/shared/Persistance/ApplicationProperties.h | 4++++
Asrc/shared/Theme/Icons/Dialog_Settings_Active.png | 0
Msrc/shared/UI/ImportControlsComponent.cpp | 68++++++++++++++++++++++++++++++++++----------------------------------
Msrc/shared/UI/MainComponent.cpp | 8++++++--
Msrc/shared/UI/MainComponent.h | 3+--
Msrc/shared/UI/OriginalsSubfolderComponent.cpp | 25++++++++++++++++++++++++-
Msrc/shared/UI/OriginalsSubfolderComponent.h | 7++++++-
Msrc/shared/UI/TruncatableTextEditor.cpp | 2+-
Asrc/shared/UI/WaapiNetworkTransferSettingsComponent.cpp | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/shared/UI/WaapiNetworkTransferSettingsComponent.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 files changed, 471 insertions(+), 105 deletions(-)

diff --git a/Package.instrument b/Package.instrument @@ -101,4 +101,30 @@ /> </target> + <target name="generate-bundle-json"> + <fail message="Requires the 'BUILD_NUMBER' property to be set." if="${BUILD_NUMBER == None}" /> + <fail message="Requires the 'WWISE_VERSION' property to be set." if="${WWISE_VERSION is None}" /> + <fail message="Requires the 'WWISE_BUILD_NUMBER' property to be set." if="${WWISE_BUILD_NUMBER is None}" /> + <fail message="Requires the 'VERSION' property to be set." if="${VERSION is None}" /> + <fail message="Requires the 'VERSION_MAJOR' property to be set." if="${VERSION_MAJOR is None}" /> + <fail message="Requires the 'VERSION_MINOR' property to be set." if="${VERSION_MINOR is None}" /> + <fail message="Requires the 'VERSION_SUBMINOR' property to be set." if="${VERSION_SUBMINOR is None}" /> + + <property name="PKG_PATH" value="${BUILDS_LOCATION}\ReaperWwiseTransfer\${VERSION}\${WWISE_VERSION}.${WWISE_BUILD_NUMBER}.${BUILD_NUMBER}\Bundles" /> + + <!-- Generate a bundle.json file in the release folder with version info. --> + <ak:generatebundlejson + wwise-branch="" + wwise-build="${BUILD_NUMBER}" + wwise-major="${VERSION_MAJOR}" + wwise-minor="${VERSION_MINOR}" + wwise-nickname="" + wwise-subminor="${VERSION_SUBMINOR}" + template-path="ReaperWwiseTransfer\bundle_template.json" + release-path="${PKG_PATH}" + product-dependent-data="" + /> + + </target> + </instrument> diff --git a/bundle_template.json b/bundle_template.json @@ -0,0 +1,14 @@ +{ + "description": "Wwise Reaper extension", + "id": "audiokinetic.reawwise.${year}_${major}_${minor}", + "name": "ReaWwise", + "tag": "reawwise", + "type": "reawwise", + "vendor": "Audiokinetic", + "version": { + "build": ${build}, + "major": ${major}, + "minor": ${minor}, + "year": ${year} + } +} +\ No newline at end of file diff --git a/src/shared/Core/AssertHook.cpp b/src/shared/Core/AssertHook.cpp @@ -14,7 +14,6 @@ specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------------------*/ #include <AK/Tools/Common/AkAssert.h> - #include <cassert> #include <stdio.h> diff --git a/src/shared/Core/ImportTask.h b/src/shared/Core/ImportTask.h @@ -62,7 +62,7 @@ namespace AK::WwiseTransfer { if(WwiseHelper::isPathComplete(importItem.path)) { - importItemRequests.emplace_back(Waapi::ImportItemRequest{importItem.path, importItem.originalsSubFolder, importItem.renderFilePath}); + importItemRequests.emplace_back(Waapi::ImportItemRequest{importItem.path, importItem.originalsSubFolder, importItem.renderFilePath, importItem.renderFileWavBase64, importItem.renderFileName}); auto pathWithoutObjectTypes = WwiseHelper::pathToPathWithoutObjectTypes(importItem.path); objectsInExtension.insert(pathWithoutObjectTypes); diff --git a/src/shared/Core/WaapiClient.cpp b/src/shared/Core/WaapiClient.cpp @@ -63,6 +63,8 @@ namespace AK::WwiseTransfer , waapiClientWatcherConfig(waapiClientWatcherConfig) , connectionRetryDelay(waapiClientWatcherConfig.MinConnectionRetryDelay) , languages(applicationState.getChildWithName(IDs::languages)) + , ip(waapiClientWatcherConfig.Ip) + , port(waapiClientWatcherConfig.Port) { } @@ -76,10 +78,20 @@ namespace AK::WwiseTransfer stopThread(-1); } + void WaapiClientWatcher::changeParameters(const juce::String& ip, int port) + { + { + std::lock_guard lock(guiMutex); + this->ip = ip; + this->port = port; + shouldReconnect = true; + } + notify(); + } + void WaapiClientWatcher::run() { using namespace WwiseAuthoringAPI; - auto onDisconnect = [this] { juce::Logger::writeToLog("Disconnected from waapi"); @@ -108,6 +120,18 @@ namespace AK::WwiseTransfer while(!threadShouldExit()) { + { + std::unique_lock lock(guiMutex); + if(shouldReconnect) + { + waapiClientWatcherConfig.Ip = ip; + waapiClientWatcherConfig.Port = port; + shouldReconnect = false; + lock.unlock(); + disconnectFromWaapi(); + } + } + int waitTime = waapiClientWatcherConfig.ConnectionMonitorDelay; if(!waapiClient.isConnected()) @@ -183,55 +207,7 @@ namespace AK::WwiseTransfer } if(waapiClient.isConnected()) { - AkJson result; - if(waapiClient.unsubscribe(projectLoadedSubscriptionId, result)) - { - juce::Logger::writeToLog("Unsubscribed from project loaded"); - } - else - { - juce::Logger::writeToLog("Failed to unsubscribed from project unloaded"); - } - - if(waapiClient.unsubscribe(projectPostClosedSubscriptionId, result)) - { - juce::Logger::writeToLog("Unsubscribed from project post closed"); - } - else - { - juce::Logger::writeToLog("Failed to unsubscribed from project post closed"); - } - - if(waapiClient.unsubscribe(objectCreatedEventSubscriptionId, result)) - { - juce::Logger::writeToLog("Unsubscribed from object created"); - } - else - { - juce::Logger::writeToLog("Failed to unsubscribed from object created"); - } - - if(waapiClient.unsubscribe(objectPostDeletedEventSubscriptionId, result)) - { - juce::Logger::writeToLog("Unsubscribed from object postDeleted"); - } - else - { - juce::Logger::writeToLog("Failed to unsubscribed from object postDeleted"); - } - - if(waapiClient.unsubscribe(objectNameChangedEventSubscriptionId, result)) - { - juce::Logger::writeToLog("Unsubscribed from object postDeleted"); - } - else - { - juce::Logger::writeToLog("Failed to unsubscribed from object postDeleted"); - } - - setWaapiConnected(false); - - waapiClient.disconnect(); + disconnectFromWaapi(); } } void WaapiClientWatcher::setProjectId(const juce::String& id) @@ -262,6 +238,61 @@ namespace AK::WwiseTransfer juce::MessageManager::callAsync(onCallAsync); } + void WaapiClientWatcher::disconnectFromWaapi() + { + using namespace WwiseAuthoringAPI; + AkJson result; + if(waapiClient.unsubscribe(projectLoadedSubscriptionId, result)) + { + juce::Logger::writeToLog("Unsubscribed from project loaded"); + } + else + { + juce::Logger::writeToLog("Failed to unsubscribed from project unloaded"); + } + + if(waapiClient.unsubscribe(projectPostClosedSubscriptionId, result)) + { + juce::Logger::writeToLog("Unsubscribed from project post closed"); + } + else + { + juce::Logger::writeToLog("Failed to unsubscribed from project post closed"); + } + + if(waapiClient.unsubscribe(objectCreatedEventSubscriptionId, result)) + { + juce::Logger::writeToLog("Unsubscribed from object created"); + } + else + { + juce::Logger::writeToLog("Failed to unsubscribed from object created"); + } + + if(waapiClient.unsubscribe(objectPostDeletedEventSubscriptionId, result)) + { + juce::Logger::writeToLog("Unsubscribed from object postDeleted"); + } + else + { + juce::Logger::writeToLog("Failed to unsubscribed from object postDeleted"); + } + + if(waapiClient.unsubscribe(objectNameChangedEventSubscriptionId, result)) + { + juce::Logger::writeToLog("Unsubscribed from object postDeleted"); + } + else + { + juce::Logger::writeToLog("Failed to unsubscribed from object postDeleted"); + } + + waapiClient.disconnect(); + + setWaapiConnected(false); + setProjectId(""); + } + void WaapiClientWatcher::setWaapiConnected(bool connected) { juce::Logger::writeToLog("Setting waapi connected"); @@ -338,11 +369,22 @@ namespace AK::WwiseTransfer AkJson::Array importItemsAsJson; for(const auto& importItemRequest : importItemsRequest) { + std::string key; + std::string value; + if(importItemRequest.renderFileWavBase64.isEmpty()) + { + key = "audioFile"; + value = importItemRequest.renderFilePath.toStdString(); + } + else + { + key = "audioFileBase64"; + value = importItemRequest.renderFileName.toStdString() + "|" + importItemRequest.renderFileWavBase64.toStdString(); + } + using namespace juce; auto importItemAsJson = AkJson(AkJson::Map{ - { - "audioFile", - AkVariant(importItemRequest.renderFilePath.toStdString()), - }, + {key, + AkVariant(value)}, { "objectPath", AkVariant(importItemRequest.path.toStdString()), diff --git a/src/shared/Core/WaapiClient.h b/src/shared/Core/WaapiClient.h @@ -29,8 +29,8 @@ namespace AK::WwiseTransfer { struct WaapiClientWatcherConfig { - const juce::String Ip; - const int Port; + juce::String Ip; + int Port; const int ConnectionMonitorDelay; const int MinConnectionRetryDelay; const int MaxConnectionRetryDelay; @@ -228,6 +228,7 @@ namespace AK::WwiseTransfer void start(); void stop(); + void changeParameters(const juce::String& ip, int port); private: juce::ValueTree applicationState; @@ -248,10 +249,18 @@ namespace AK::WwiseTransfer uint64_t objectPostDeletedEventSubscriptionId{0}; uint64_t objectNameChangedEventSubscriptionId{0}; + // protected by guiMutex except for on construction + std::mutex guiMutex; + bool shouldReconnect = false; + juce::String ip; + int port; + // + void run() override; void setProjectId(const juce::String& projectId); void setWaapiConnected(bool connected); void setWwiseObjectsChanged(bool changed); + void disconnectFromWaapi(); }; } // namespace AK::WwiseTransfer diff --git a/src/shared/Helpers/StringHelper.h b/src/shared/Helpers/StringHelper.h @@ -15,11 +15,10 @@ specific language governing permissions and limitations under the License. #pragma once -#include <juce_gui_basics/juce_gui_basics.h> - #include <algorithm> #include <iostream> #include <iterator> +#include <juce_gui_basics/juce_gui_basics.h> #include <string> #include <vector> diff --git a/src/shared/Model/Import.h b/src/shared/Model/Import.h @@ -68,6 +68,8 @@ namespace AK::WwiseTransfer::Import struct Item : public PreviewItem { juce::String renderFilePath; + juce::String renderFileWavBase64; + juce::String renderFileName; }; struct PreviewItemNode diff --git a/src/shared/Model/Waapi.h b/src/shared/Model/Waapi.h @@ -29,6 +29,8 @@ namespace AK::WwiseTransfer::Waapi juce::String path; juce::String originalsSubFolder; juce::String renderFilePath; + juce::String renderFileWavBase64; + juce::String renderFileName; }; struct ProjectInfo diff --git a/src/shared/Persistance/ApplicationProperties.cpp b/src/shared/Persistance/ApplicationProperties.cpp @@ -37,6 +37,9 @@ namespace AK::WwiseTransfer const juce::String showSilentIncrementWarningName = "showSilentIncrementWarning"; constexpr bool showSilentIncrementWarningValue = true; + + const juce::String enableCrossMachineTransferName = "enableCrossMachineTransfer"; + constexpr bool enableCrossMachineTransferValue = false; } // namespace ApplicationPropertyConstants ApplicationProperties::ApplicationProperties(const juce::String& applicationName) @@ -63,13 +66,35 @@ namespace AK::WwiseTransfer juce::String ApplicationProperties::getWaapiIp() { using namespace ApplicationPropertyConstants; - return getUserSettings()->getValue(waapiIpPropertyName, waapiIpDefaultPropertyValue); + juce::String val = getUserSettings()->getValue(waapiIpPropertyName, waapiIpDefaultPropertyValue); + if(val.isEmpty() || !getIsCrossMachineTransferEnabled()) + return waapiIpDefaultPropertyValue; + return val; + } + + void ApplicationProperties::setWaapiIp(const juce::String& ip) + { + using namespace ApplicationPropertyConstants; + if(ip.isEmpty()) + return; + getUserSettings()->setValue(waapiIpPropertyName, ip); } int ApplicationProperties::getWaapiPort() { using namespace ApplicationPropertyConstants; - return getUserSettings()->getIntValue(waapiPortPropertyName, waapiPortDefaultPropertyValue); + int val = getUserSettings()->getIntValue(waapiPortPropertyName, waapiPortDefaultPropertyValue); + if(val <= 0) + return waapiPortDefaultPropertyValue; + return val; + } + + void ApplicationProperties::setWaapiPort(int port) + { + using namespace ApplicationPropertyConstants; + if(port <= 0) + return; + getUserSettings()->setValue(waapiPortPropertyName, port); } int ApplicationProperties::getPreviewRefreshInterval() @@ -81,7 +106,8 @@ namespace AK::WwiseTransfer juce::StringArray ApplicationProperties::getRecentHierarchyMappingPresets() { using namespace ApplicationPropertyConstants; - auto recentHierarchyMappingPresetsAsString = getUserSettings()->getValue(recentHierarchyMappingPresetsPropertyName, recentHierarchyMappingPresetsPropertyValue); + auto recentHierarchyMappingPresetsAsString = + getUserSettings()->getValue(recentHierarchyMappingPresetsPropertyName, recentHierarchyMappingPresetsPropertyValue); juce::StringArray recentHierarchyMappingPresets; recentHierarchyMappingPresets.addTokens(recentHierarchyMappingPresetsAsString, ";", ""); @@ -108,7 +134,7 @@ namespace AK::WwiseTransfer using namespace ApplicationPropertyConstants; auto recentHierarchyMappingPresets = getRecentHierarchyMappingPresets(); - if (recentHierarchyMappingPresets.contains(path)) + if(recentHierarchyMappingPresets.contains(path)) recentHierarchyMappingPresets.removeString(path); const auto recentHierarchyMappingPresetsAsString = recentHierarchyMappingPresets.joinIntoString(";", 0, 10); @@ -138,4 +164,14 @@ namespace AK::WwiseTransfer using namespace ApplicationPropertyConstants; getUserSettings()->setValue(showSilentIncrementWarningName, value); } + bool ApplicationProperties::getIsCrossMachineTransferEnabled() + { + using namespace ApplicationPropertyConstants; + return getUserSettings()->getBoolValue(enableCrossMachineTransferName, enableCrossMachineTransferValue); + } + void ApplicationProperties::setIsCrossMachineTransferEnabled(bool value) + { + using namespace ApplicationPropertyConstants; + getUserSettings()->setValue(enableCrossMachineTransferName, value); + } } // namespace AK::WwiseTransfer diff --git a/src/shared/Persistance/ApplicationProperties.h b/src/shared/Persistance/ApplicationProperties.h @@ -25,7 +25,9 @@ namespace AK::WwiseTransfer explicit ApplicationProperties(const juce::String& applicationName); juce::String getWaapiIp(); + void setWaapiIp(const juce::String& ip); int getWaapiPort(); + void setWaapiPort(int port); int getPreviewRefreshInterval(); juce::StringArray getRecentHierarchyMappingPresets(); void addRecentHierarchyMappingPreset(const juce::String& path); @@ -34,6 +36,8 @@ namespace AK::WwiseTransfer double getScaleFactorOverride(); bool getShowSilentIncrementWarning(); void setShowSilentIncrementWarning(bool value); + bool getIsCrossMachineTransferEnabled(); + void setIsCrossMachineTransferEnabled(bool value); private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ApplicationProperties) diff --git a/src/shared/Theme/Icons/Dialog_Settings_Active.png b/src/shared/Theme/Icons/Dialog_Settings_Active.png Binary files differ. diff --git a/src/shared/UI/ImportControlsComponent.cpp b/src/shared/UI/ImportControlsComponent.cpp @@ -41,7 +41,11 @@ namespace AK::WwiseTransfer constexpr int errorMessageMarginLeft = 75; }; // namespace ImportControlsComponentConstants - ImportControlsComponent::ImportControlsComponent(juce::ValueTree appState, WaapiClient& waapiClient, DawContext& dawContext, ApplicationProperties& applicationProperties, const juce::String& applicationName) + ImportControlsComponent::ImportControlsComponent(juce::ValueTree appState, + WaapiClient& waapiClient, + DawContext& dawContext, + ApplicationProperties& applicationProperties, + const juce::String& applicationName) : applicationState(appState) , originalsSubfolderValid(applicationState, IDs::originalsSubfolderValid, nullptr) , importDestinationValid(applicationState, IDs::importDestinationValid, nullptr) @@ -108,7 +112,8 @@ namespace AK::WwiseTransfer transferInProgress = true; - const auto hierarchyMappingPath = ImportHelper::hierarchyMappingToPath(ImportHelper::valueTreeToHierarchyMappingNodeList(applicationState.getChildWithName(IDs::hierarchyMapping))); + const auto hierarchyMappingPath = + ImportHelper::hierarchyMappingToPath(ImportHelper::valueTreeToHierarchyMappingNodeList(applicationState.getChildWithName(IDs::hierarchyMapping))); const Import::Options opts(importDestination, originalsSubFolder, hierarchyMappingPath); const auto previewItems = dawContext.getItemsForPreview(opts); @@ -132,14 +137,15 @@ namespace AK::WwiseTransfer return; } - const auto importItems = dawContext.getItemsForImport(opts); + auto importItems = dawContext.getItemsForImport(opts); bool showIncompletePathWarning = false; bool showRenameWarning = false; + bool isCrossMachineTransferEnabled = applicationProperties.getIsCrossMachineTransferEnabled(); if(importItems.size() > 0) { - for(const auto& importItem : importItems) + for(auto& importItem : importItems) { if(importItem.renderFilePath.isEmpty()) { @@ -152,6 +158,20 @@ namespace AK::WwiseTransfer if(!WwiseHelper::isPathComplete(importItem.path)) showIncompletePathWarning = true; + + using namespace juce; + const File rendPath(importItem.renderFilePath); + importItem.renderFileName = rendPath.getFileName(); + + if(isCrossMachineTransferEnabled) + { + MemoryBlock mb; + std::unique_ptr<FileInputStream> inputStream = rendPath.createInputStream(); + inputStream->readIntoMemoryBlock(mb); + importItem.renderFileWavBase64 = Base64::toBase64(mb.getData(), mb.getSize()); + // add base64 padding + importItem.renderFileWavBase64 += String(std::string(importItem.renderFileWavBase64.length() % 4, '=')); + } } } else @@ -180,11 +200,7 @@ namespace AK::WwiseTransfer message << juce::NewLine() << summary.getNumObjectTemplatesApplied() << " object template(s) applied."; message << juce::NewLine() << summary.getNumAudiofilesTransfered() << " audio files(s) imported."; - auto messageBoxOptions = juce::MessageBoxOptions() - .withTitle(title) - .withMessage(message) - .withButton("View Details") - .withButton("Close"); + auto messageBoxOptions = juce::MessageBoxOptions().withTitle(title).withMessage(message).withButton("View Details").withButton("Close"); auto onDialogBtnClicked = [this, summary = summary, importTaskOptions = importTaskOptions](int result) { @@ -244,16 +260,15 @@ namespace AK::WwiseTransfer void ImportControlsComponent::refreshComponent() { - auto importButtonEnabled = !transferInProgress.get() && originalsSubfolderValid.get() && importDestinationValid.get() && - projectPath.get().isNotEmpty() && previewItems.getNumChildren() > 0; + auto importButtonEnabled = !transferInProgress.get() && originalsSubfolderValid.get() && importDestinationValid.get() && projectPath.get().isNotEmpty() && + previewItems.getNumChildren() > 0; auto hieararchyMappingNodes = ImportHelper::valueTreeToHierarchyMappingNodeList(hierarchyMapping); auto hierarchyMappingValid = true; for(const auto& hierarchyMappingNode : hieararchyMappingNodes) { - hierarchyMappingValid &= hierarchyMappingNode.typeValid && - hierarchyMappingNode.nameValid && + hierarchyMappingValid &= hierarchyMappingNode.typeValid && hierarchyMappingNode.nameValid && (!hierarchyMappingNode.propertyTemplatePathEnabled || hierarchyMappingNode.propertyTemplatePathValid); } @@ -275,7 +290,8 @@ namespace AK::WwiseTransfer void ImportControlsComponent::valueTreePropertyChanged(juce::ValueTree& treeWhosePropertyHasChanged, const juce::Identifier& property) { - if(treeWhosePropertyHasChanged == applicationState && (property == IDs::originalsSubfolderValid || property == IDs::importDestinationValid || property == IDs::projectPath || property == IDs::transferInProgress) || + if(treeWhosePropertyHasChanged == applicationState && (property == IDs::originalsSubfolderValid || property == IDs::importDestinationValid || + property == IDs::projectPath || property == IDs::transferInProgress) || treeWhosePropertyHasChanged.getType() == IDs::hierarchyMappingNode) { triggerAsyncUpdate(); @@ -350,11 +366,7 @@ namespace AK::WwiseTransfer const juce::String message("One or more file names where silently incremented to avoid overwriting during the render process."); juce::Logger::writeToLog(message); - auto messageBoxOptions = juce::MessageBoxOptions() - .withTitle("Action Required") - .withMessage(message) - .withButton("Continue") - .withButton("Cancel"); + auto messageBoxOptions = juce::MessageBoxOptions().withTitle("Action Required").withMessage(message).withButton("Continue").withButton("Cancel"); juce::AlertWindow::showAsync(messageBoxOptions, onDialogBtnClicked); @@ -382,11 +394,7 @@ namespace AK::WwiseTransfer const juce::String message("One or more object paths are incomplete and will not be transfered."); juce::Logger::writeToLog(message); - auto messageBoxOptions = juce::MessageBoxOptions() - .withTitle("Action Required") - .withMessage(message) - .withButton("Continue") - .withButton("Cancel"); + auto messageBoxOptions = juce::MessageBoxOptions().withTitle("Action Required").withMessage(message).withButton("Continue").withButton("Cancel"); juce::AlertWindow::showAsync(messageBoxOptions, onDialogBtnClicked); } @@ -396,16 +404,8 @@ namespace AK::WwiseTransfer const auto hierarchyMappingNodeList = ImportHelper::valueTreeToHierarchyMappingNodeList(hierarchyMapping); const Import::Task::Options importTaskOptions{ - importItems, - containerNameExistsOption, - applyTemplateOption, - importDestination, - hierarchyMappingNodeList, - originalsFolder, - languageSubfolder, - selectObjectsOnImportCommand, - applyTemplateFeatureEnabled, - undoGroupFeatureEnabled, + importItems, containerNameExistsOption, applyTemplateOption, importDestination, hierarchyMappingNodeList, + originalsFolder, languageSubfolder, selectObjectsOnImportCommand, applyTemplateFeatureEnabled, undoGroupFeatureEnabled, waqlEnabled}; auto onImportComplete = [this, importTaskOptions = importTaskOptions](const Import::Summary& importSummary) diff --git a/src/shared/UI/MainComponent.cpp b/src/shared/UI/MainComponent.cpp @@ -40,8 +40,12 @@ namespace AK::WwiseTransfer : applicationState(ApplicationState::create()) , validator(applicationState, waapiClient) , applicationProperties(applicationName) - , waapiClientWatcher(applicationState, waapiClient, WaapiClientWatcherConfig{applicationProperties.getWaapiIp(), applicationProperties.getWaapiPort(), MainComponentConstants::connectionMonitorDelayDefault, MainComponentConstants::minConnectionRetryDelayDefault, MainComponentConstants::maxConnectionRetryDelayDefault}) - , originalsSubfolderComponent(applicationState, applicationName) + , waapiClientWatcher(applicationState, + waapiClient, + WaapiClientWatcherConfig{applicationProperties.getWaapiIp(), applicationProperties.getWaapiPort(), + MainComponentConstants::connectionMonitorDelayDefault, MainComponentConstants::minConnectionRetryDelayDefault, + MainComponentConstants::maxConnectionRetryDelayDefault}) + , originalsSubfolderComponent(applicationState, applicationName, applicationProperties, waapiClientWatcher) , importDestinationComponent(applicationState, waapiClient) , importComponent(applicationState, waapiClient, applicationProperties, applicationName) , importPreviewComponent(applicationState) diff --git a/src/shared/UI/MainComponent.h b/src/shared/UI/MainComponent.h @@ -38,8 +38,7 @@ specific language governing permissions and limitations under the License. namespace AK::WwiseTransfer { - class MainComponent - : public juce::Component + class MainComponent : public juce::Component , juce::ValueTree::Listener , juce::AsyncUpdater { diff --git a/src/shared/UI/OriginalsSubfolderComponent.cpp b/src/shared/UI/OriginalsSubfolderComponent.cpp @@ -30,15 +30,17 @@ namespace AK::WwiseTransfer constexpr int smallButtonWidth = 26; } // namespace WwiseOriginalsComponentConstants - OriginalsSubfolderComponent::OriginalsSubfolderComponent(juce::ValueTree appState, const juce::String& applicationName) + OriginalsSubfolderComponent::OriginalsSubfolderComponent(juce::ValueTree appState, const juce::String& applicationName, ApplicationProperties& applicationProperties, WaapiClientWatcher& waapiCW) : applicationState(appState) , projectPath(applicationState, IDs::projectPath, nullptr) , originalsSubfolder(applicationState, IDs::originalsSubfolder, nullptr) , fileBrowserButton("FileBrowserButton", juce::Drawable::createFromImageData(BinaryData::General_FolderWithTriangle_Normal_svg, BinaryData::General_FolderWithTriangle_Normal_svgSize)) , aboutButton("AboutButton", juce::Drawable::createFromImageData(BinaryData::Dialog_Help_Active_png, BinaryData::Dialog_Help_Active_pngSize)) + , crossMachineTransferSettingsButton("crossMachineTransferSettingsButton", juce::Drawable::createFromImageData(BinaryData::Dialog_Settings_Active_png, BinaryData::Dialog_Settings_Active_pngSize)) , originalsFolder(applicationState, IDs::originalsFolder, nullptr) , languageSubfolder(applicationState, IDs::languageSubfolder, nullptr) , aboutComponent(applicationName) + , crossMachineTransferSettingsComponent(applicationName, applicationProperties, waapiCW) { projectPathLabel.setText("Project Path", juce::dontSendNotification); projectPathLabel.setBorderSize(juce::BorderSize(0)); @@ -68,6 +70,12 @@ namespace AK::WwiseTransfer showAboutWindow(); }; + crossMachineTransferSettingsButton.setTooltip("Cross Machine Transfer Settings"); + crossMachineTransferSettingsButton.onClick = [this] + { + showCrossMachineTransferSettingsWindow(); + }; + fileBrowserButton.onClick = [this] { selectOriginalsSubfoler(); @@ -85,6 +93,7 @@ namespace AK::WwiseTransfer addAndMakeVisible(fileBrowserButton); addAndMakeVisible(wildcardSelector); addAndMakeVisible(aboutButton); + addAndMakeVisible(crossMachineTransferSettingsButton); refreshComponent(); @@ -110,6 +119,9 @@ namespace AK::WwiseTransfer aboutButton.setBounds(projectPathSection.removeFromRight(smallButtonWidth)); projectPathSection.removeFromRight(spacing); + crossMachineTransferSettingsButton.setBounds(projectPathSection.removeFromRight(smallButtonWidth)); + projectPathSection.removeFromRight(spacing); + projectPathEditor.setBounds(projectPathSection); } @@ -186,4 +198,15 @@ namespace AK::WwiseTransfer options.launchAsync(); } + void OriginalsSubfolderComponent::showCrossMachineTransferSettingsWindow() + { + juce::DialogWindow::LaunchOptions options; + options.dialogTitle = "Waapi Network Transfer Settings"; + options.useNativeTitleBar = true; + options.resizable = false; + options.componentToCentreAround = this->getParentComponent()->getParentComponent(); + options.content = juce::OptionalScopedPointer<juce::Component>(&crossMachineTransferSettingsComponent, false); + + options.launchAsync(); + } } // namespace AK::WwiseTransfer diff --git a/src/shared/UI/OriginalsSubfolderComponent.h b/src/shared/UI/OriginalsSubfolderComponent.h @@ -19,6 +19,7 @@ specific language governing permissions and limitations under the License. #include "CustomDrawableButton.h" #include "TruncatableTextEditor.h" #include "ValidatableTextEditor.h" +#include "WaapiNetworkTransferSettingsComponent.h" #include "WildcardSelector.h" #include <juce_gui_basics/juce_gui_basics.h> @@ -32,7 +33,7 @@ namespace AK::WwiseTransfer , private juce::AsyncUpdater { public: - OriginalsSubfolderComponent(juce::ValueTree applicationState, const juce::String& applicationName); + OriginalsSubfolderComponent(juce::ValueTree applicationState, const juce::String& applicationName, ApplicationProperties& applicationProperties, WaapiClientWatcher& waapiCW); ~OriginalsSubfolderComponent(); private: @@ -54,6 +55,9 @@ namespace AK::WwiseTransfer CustomDrawableButton aboutButton; AboutComponent aboutComponent; + CustomDrawableButton crossMachineTransferSettingsButton; + WaapiNetworkTransferSettingsComponent crossMachineTransferSettingsComponent; + void resized() override; void refreshComponent(); void selectOriginalsSubfoler(); @@ -62,6 +66,7 @@ namespace AK::WwiseTransfer void handleAsyncUpdate() override; void showAboutWindow(); + void showCrossMachineTransferSettingsWindow(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OriginalsSubfolderComponent) }; diff --git a/src/shared/UI/TruncatableTextEditor.cpp b/src/shared/UI/TruncatableTextEditor.cpp @@ -51,7 +51,7 @@ namespace AK::WwiseTransfer void TruncatableTextEditor::resetText() { - juce::String text{ "..." }; + juce::String text{"..."}; const auto indent = getLeftIndent() * 4; const auto ellipsisWidth = getFont().getStringWidth(text); const auto width = getWidth(); diff --git a/src/shared/UI/WaapiNetworkTransferSettingsComponent.cpp b/src/shared/UI/WaapiNetworkTransferSettingsComponent.cpp @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------------------- + +Copyright (c) 2024 AUDIOKINETIC Inc. + +This file is licensed to use under the license available at: +https://github.com/audiokinetic/ReaWwise/blob/main/License.txt (the "License"). +You may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +----------------------------------------------------------------------------------------*/ + +#include "WaapiNetworkTransferSettingsComponent.h" + +#include "AK/AkWwiseSDKVersion.h" +#include "BinaryData.h" +#include "Theme/CustomLookAndFeel.h" + +#include <juce_gui_basics/juce_gui_basics.h> + +#define AK_WWISE_VST_VERSION_FULL AK_WWISESDK_VERSIONNAME_SHORT "." AK_WWISESDK_NUM2STRING(AK_WWISESDK_VERSION_BUILD) + +namespace AK::WwiseTransfer +{ + namespace CrossMachineTransferComponentConstants + { + constexpr int editorBoxHeight = 26; + constexpr int labelWidth = 220; + constexpr int margin = 10; + constexpr int width = 370; + constexpr int height = 100; + } // namespace CrossMachineTransferComponentConstants + + WaapiNetworkTransferSettingsComponent::WaapiNetworkTransferSettingsComponent(const juce::String& applicationName, + ApplicationProperties& appProps, + WaapiClientWatcher& waapiCW) + : applicationProperties(appProps) + , waapiClientWatcher(waapiCW) + { + using namespace CrossMachineTransferComponentConstants; + + setSize(width, height); + setLookAndFeel(&lookAndFeel); + + ipAddressLabel.setText("Waapi IP Address", juce::dontSendNotification); + ipAddressLabel.setBorderSize(juce::BorderSize(0)); + ipAddressLabel.setMinimumHorizontalScale(1.0f); + ipAddressLabel.setJustificationType(juce::Justification::left); + + ipAddressTextEditor.setFont(CustomLookAndFeelConstants::smallFontSize); + ipAddressTextEditor.setText(applicationProperties.getWaapiIp()); + ipAddressTextEditor.onFocusLost = [this] + { + applicationProperties.setWaapiIp(ipAddressTextEditor.getText()); + waapiClientWatcher.changeParameters(applicationProperties.getWaapiIp(), applicationProperties.getWaapiPort()); + }; + + addAndMakeVisible(ipAddressLabel); + addAndMakeVisible(ipAddressTextEditor); + + portLabel.setText("Waapi Port", juce::dontSendNotification); + portLabel.setBorderSize(juce::BorderSize(0)); + portLabel.setMinimumHorizontalScale(1.0f); + portLabel.setJustificationType(juce::Justification::left); + + portTextEditor.setFont(CustomLookAndFeelConstants::smallFontSize); + portTextEditor.setText(juce::String(applicationProperties.getWaapiPort())); + portTextEditor.onFocusLost = [this] + { + applicationProperties.setWaapiPort(portTextEditor.getTextValue().getValue()); + waapiClientWatcher.changeParameters(applicationProperties.getWaapiIp(), applicationProperties.getWaapiPort()); + }; + + addAndMakeVisible(portLabel); + addAndMakeVisible(portTextEditor); + + enableCrossMachineTransferLabel.setText("Enable Cross Machine Transfer", juce::dontSendNotification); + enableCrossMachineTransferLabel.setBorderSize(juce::BorderSize(0)); + enableCrossMachineTransferLabel.setMinimumHorizontalScale(1.0f); + enableCrossMachineTransferLabel.setJustificationType(juce::Justification::left); + + enableCrossMachineTransferButton.setToggleState(applicationProperties.getIsCrossMachineTransferEnabled(), juce::dontSendNotification); + setToCrossMachineTransfer(applicationProperties.getIsCrossMachineTransferEnabled(), true); + enableCrossMachineTransferButton.onClick = [this]() + { + setToCrossMachineTransfer(!applicationProperties.getIsCrossMachineTransferEnabled()); + }; + + addAndMakeVisible(enableCrossMachineTransferLabel); + addAndMakeVisible(enableCrossMachineTransferButton); + } + + WaapiNetworkTransferSettingsComponent::~WaapiNetworkTransferSettingsComponent() + { + setLookAndFeel(nullptr); + } + + void WaapiNetworkTransferSettingsComponent::resized() + { + using namespace CrossMachineTransferComponentConstants; + + auto area = getLocalBounds(); + area.reduce(margin, margin); + + auto crossMachineTransferEnableSection = area.removeFromTop(editorBoxHeight); + { + enableCrossMachineTransferLabel.setBounds(crossMachineTransferEnableSection.removeFromLeft(labelWidth)); + crossMachineTransferEnableSection.removeFromLeft(margin); + + enableCrossMachineTransferButton.setBounds(crossMachineTransferEnableSection); + } + + auto ipAddressSection = area.removeFromTop(editorBoxHeight); + { + ipAddressLabel.setBounds(ipAddressSection.removeFromLeft(labelWidth)); + ipAddressSection.removeFromLeft(margin); + + ipAddressTextEditor.setBounds(ipAddressSection); + } + + auto portSection = area.removeFromTop(editorBoxHeight); + { + portLabel.setBounds(portSection.removeFromLeft(labelWidth)); + portSection.removeFromLeft(margin); + + portTextEditor.setBounds(portSection); + } + } + + void WaapiNetworkTransferSettingsComponent::paint(juce::Graphics& g) + { + g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId)); + } + + void WaapiNetworkTransferSettingsComponent::setToCrossMachineTransfer(bool isCrossMachineTransfer, bool onInit) + { + applicationProperties.setIsCrossMachineTransferEnabled(isCrossMachineTransfer); + enableCrossMachineTransferButton.setToggleState(isCrossMachineTransfer, juce::dontSendNotification); + ipAddressTextEditor.setEnabled(isCrossMachineTransfer); + ipAddressTextEditor.setText(applicationProperties.getWaapiIp(), false); + if(!onInit) + waapiClientWatcher.changeParameters(applicationProperties.getWaapiIp(), applicationProperties.getWaapiPort()); + } +} // namespace AK::WwiseTransfer diff --git a/src/shared/UI/WaapiNetworkTransferSettingsComponent.h b/src/shared/UI/WaapiNetworkTransferSettingsComponent.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------------------- + +Copyright (c) 2024 AUDIOKINETIC Inc. + +This file is licensed to use under the license available at: +https://github.com/audiokinetic/ReaWwise/blob/main/License.txt (the "License"). +You may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +----------------------------------------------------------------------------------------*/ + +#pragma once + +#include "Core/WaapiClient.h" +#include "Persistance/ApplicationProperties.h" +#include "Theme/CustomLookAndFeel.h" + +#include <juce_gui_basics/juce_gui_basics.h> + +namespace AK::WwiseTransfer +{ + class WaapiNetworkTransferSettingsComponent : public juce::Component + { + public: + WaapiNetworkTransferSettingsComponent(const juce::String& applicationName, ApplicationProperties& applicationProperties, WaapiClientWatcher& waapiCW); + ~WaapiNetworkTransferSettingsComponent() override; + + void resized() override; + void paint(juce::Graphics& g) override; + + private: + CustomLookAndFeel lookAndFeel; + + juce::Label enableCrossMachineTransferLabel; + juce::ToggleButton enableCrossMachineTransferButton; + + juce::Label ipAddressLabel; + juce::TextEditor ipAddressTextEditor; + + juce::Label portLabel; + juce::TextEditor portTextEditor; + + ApplicationProperties& applicationProperties; + WaapiClientWatcher& waapiClientWatcher; + + void setToCrossMachineTransfer(bool isCrossMachineTransfer, bool onInit = false); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WaapiNetworkTransferSettingsComponent) + }; +} // namespace AK::WwiseTransfer