ImportHelper.h (10983B)
1 /*---------------------------------------------------------------------------------------- 2 3 Copyright (c) 2023 AUDIOKINETIC Inc. 4 5 This file is licensed to use under the license available at: 6 https://github.com/audiokinetic/ReaWwise/blob/main/License.txt (the "License"). 7 You may not use this file except in compliance with the License. 8 9 Unless required by applicable law or agreed to in writing, software distributed 10 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 specific language governing permissions and limitations under the License. 13 14 ----------------------------------------------------------------------------------------*/ 15 16 #pragma once 17 18 #include "Helpers/WwiseHelper.h" 19 #include "Model/IDs.h" 20 #include "Model/Import.h" 21 22 #include <AK/Tools/Common/AkFNVHash.h> 23 #include <juce_gui_basics/juce_gui_basics.h> 24 25 namespace AK::WwiseTransfer::ImportHelper 26 { 27 inline juce::ValueTree hierarchyMappingNodeToValueTree(Import::HierarchyMappingNode hierarchyMappingNode) 28 { 29 juce::ValueTree valueTree(IDs::hierarchyMappingNode); 30 valueTree.setProperty(IDs::objectName, hierarchyMappingNode.name, nullptr); 31 valueTree.setProperty(IDs::objectNameValid, hierarchyMappingNode.nameValid, nullptr); 32 valueTree.setProperty(IDs::objectNameErrorMessage, hierarchyMappingNode.nameErrorMessage, nullptr); 33 valueTree.setProperty(IDs::objectType, juce::VariantConverter<Wwise::ObjectType>::toVar(hierarchyMappingNode.type), nullptr); 34 valueTree.setProperty(IDs::objectTypeValid, hierarchyMappingNode.typeValid, nullptr); 35 valueTree.setProperty(IDs::objectTypeErrorMessage, hierarchyMappingNode.typeErrorMessage, nullptr); 36 valueTree.setProperty(IDs::propertyTemplatePath, hierarchyMappingNode.propertyTemplatePath, nullptr); 37 valueTree.setProperty(IDs::propertyTemplatePathEnabled, hierarchyMappingNode.propertyTemplatePathEnabled, nullptr); 38 valueTree.setProperty(IDs::propertyTemplatePathValid, hierarchyMappingNode.propertyTemplatePathValid, nullptr); 39 valueTree.setProperty(IDs::propertyTemplatePathErrorMessage, hierarchyMappingNode.propertyTemplatePathErrorMessage, nullptr); 40 valueTree.setProperty(IDs::objectLanguage, hierarchyMappingNode.language, nullptr); 41 42 return valueTree; 43 } 44 45 inline juce::ValueTree hierachyMappingNodeListToValueTree(const std::vector<Import::HierarchyMappingNode>& hierarchyMappingNodeList) 46 { 47 juce::ValueTree valueTree(IDs::hierarchyMapping); 48 for(const auto& hierarchyMappingNode : hierarchyMappingNodeList) 49 { 50 valueTree.appendChild(hierarchyMappingNodeToValueTree(hierarchyMappingNode), nullptr); 51 } 52 53 return valueTree; 54 } 55 56 inline Import::HierarchyMappingNode valueTreeToHiarchyMappingNode(juce::ValueTree valueTree) 57 { 58 return Import::HierarchyMappingNode(valueTree[IDs::objectName], 59 valueTree[IDs::objectNameValid], 60 valueTree[IDs::objectNameErrorMessage], 61 juce::VariantConverter<Wwise::ObjectType>::fromVar(valueTree[IDs::objectType]), 62 valueTree[IDs::objectTypeValid], 63 valueTree[IDs::objectTypeErrorMessage], 64 valueTree[IDs::propertyTemplatePath], 65 valueTree[IDs::propertyTemplatePathEnabled], 66 valueTree[IDs::propertyTemplatePathValid], 67 valueTree[IDs::propertyTemplatePathErrorMessage], 68 valueTree[IDs::objectLanguage]); 69 } 70 71 inline Import::PreviewItemNode valueTreeToPreviewItemNode(juce::ValueTree valueTree) 72 { 73 return Import::PreviewItemNode{ 74 valueTree[IDs::objectName], 75 juce::VariantConverter<Wwise::ObjectType>::fromVar(valueTree[IDs::objectType]), 76 juce::VariantConverter<Import::ObjectStatus>::fromVar(valueTree[IDs::objectStatus]), 77 valueTree[IDs::audioFilePath], 78 juce::VariantConverter<Import::WavStatus>::fromVar(valueTree[IDs::wavStatus]), 79 valueTree[IDs::unresolvedWildcard], 80 }; 81 } 82 83 inline juce::ValueTree previewItemNodeToValueTree(const juce::String& path, Import::PreviewItemNode previewItem) 84 { 85 juce::ValueTree valueTree(path); 86 valueTree.setProperty(IDs::objectName, previewItem.name, nullptr); 87 valueTree.setProperty(IDs::objectType, juce::VariantConverter<Wwise::ObjectType>::toVar(previewItem.type), nullptr); 88 valueTree.setProperty(IDs::objectStatus, juce::VariantConverter<Import::ObjectStatus>::toVar(previewItem.objectStatus), nullptr); 89 valueTree.setProperty(IDs::audioFilePath, previewItem.audioFilePath, nullptr); 90 valueTree.setProperty(IDs::wavStatus, juce::VariantConverter<Import::WavStatus>::toVar(previewItem.wavStatus), nullptr); 91 92 valueTree.setProperty(IDs::unresolvedWildcard, previewItem.unresolvedWildcard, nullptr); 93 94 return valueTree; 95 } 96 97 inline std::vector<Import::HierarchyMappingNode> valueTreeToHierarchyMappingNodeList(juce::ValueTree hierarchyMappingValueTree) 98 { 99 std::vector<Import::HierarchyMappingNode> hierarchyMappingNodeList; 100 101 for(int i = 0; i < hierarchyMappingValueTree.getNumChildren(); ++i) 102 { 103 auto hierarchyMappingNodeValueTree = hierarchyMappingValueTree.getChild(i); 104 105 hierarchyMappingNodeList.emplace_back(ImportHelper::valueTreeToHiarchyMappingNode(hierarchyMappingNodeValueTree)); 106 } 107 108 return hierarchyMappingNodeList; 109 } 110 111 inline juce::String hierarchyMappingToPath(std::vector<Import::HierarchyMappingNode> hierachyMappingNodeList) 112 { 113 juce::String path; 114 115 for(auto& hierarchyMappingNode : hierachyMappingNodeList) 116 { 117 if(hierarchyMappingNode.type != Wwise::ObjectType::Unknown) 118 path << WwiseHelper::buildObjectPathNode(hierarchyMappingNode.type, hierarchyMappingNode.name); 119 } 120 121 return path; 122 } 123 124 inline juce::String containerNameExistsOptionToString(Import::ContainerNameExistsOption option) 125 { 126 switch(option) 127 { 128 case Import::ContainerNameExistsOption::UseExisting: 129 return "useExisting"; 130 case Import::ContainerNameExistsOption::CreateNew: 131 return "createNew"; 132 case Import::ContainerNameExistsOption::Replace: 133 return "replaceExisting"; 134 default: 135 return "notImplemented"; 136 } 137 } 138 139 inline Import::ContainerNameExistsOption stringToContainerNameExistsOption(const juce::String& option) 140 { 141 if(option == "useExisting") 142 return Import::ContainerNameExistsOption::UseExisting; 143 else if(option == "createNew") 144 return Import::ContainerNameExistsOption::CreateNew; 145 else if(option == "replace") 146 return Import::ContainerNameExistsOption::Replace; 147 else 148 return Import::ContainerNameExistsOption::Unknown; 149 } 150 151 inline juce::String containerNameExistsOptionToReadableString(Import::ContainerNameExistsOption option) 152 { 153 switch(option) 154 { 155 case Import::ContainerNameExistsOption::UseExisting: 156 return "Use Existing"; 157 case Import::ContainerNameExistsOption::CreateNew: 158 return "Create New"; 159 case Import::ContainerNameExistsOption::Replace: 160 return "Replace"; 161 default: 162 return "Not Implemented"; 163 } 164 } 165 166 inline juce::String audioFilenameExistsOptionToReadableString(Import::AudioFilenameExistsOption option) 167 { 168 switch(option) 169 { 170 case Import::AudioFilenameExistsOption::UseExisting: 171 return "Use Existing"; 172 case Import::AudioFilenameExistsOption::Replace: 173 return "Replace"; 174 default: 175 return "Not Implemented"; 176 } 177 } 178 179 inline juce::String applyTemplateOptionToReadableString(Import::ApplyTemplateOption option) 180 { 181 switch(option) 182 { 183 case Import::ApplyTemplateOption::Always: 184 return "Always"; 185 case Import::ApplyTemplateOption::NewObjectCreationOnly: 186 return "New Object Creation Only"; 187 default: 188 return "Not Implemented"; 189 } 190 } 191 192 inline juce::String objectStatusToReadableString(Import::ObjectStatus itemState) 193 { 194 switch(itemState) 195 { 196 case Import::ObjectStatus::Replaced: 197 return "Replaced"; 198 case Import::ObjectStatus::New: 199 return "New"; 200 case Import::ObjectStatus::NewRenamed: 201 return "New (Renamed)"; 202 case Import::ObjectStatus::NoChange: 203 return "No Change"; 204 default: 205 return ""; 206 } 207 } 208 209 inline juce::String wavStatusToReadableString(Import::WavStatus itemState) 210 { 211 switch(itemState) 212 { 213 case Import::WavStatus::Replaced: 214 return "Replaced"; 215 case Import::WavStatus::New: 216 return "New"; 217 default: 218 return ""; 219 } 220 } 221 222 inline unsigned int importPreviewItemsToHash(const std::vector<Import::PreviewItem>& importItems) 223 { 224 AK::FNVHash32 hash; 225 226 for(const auto& importItem : importItems) 227 { 228 auto audioFilePathRaw = importItem.audioFilePath.toUTF8(); 229 hash.Compute(audioFilePathRaw, audioFilePathRaw.sizeInBytes()); 230 231 auto originalsSubfolderRaw = importItem.originalsSubFolder.toUTF8(); 232 hash.Compute(originalsSubfolderRaw, originalsSubfolderRaw.sizeInBytes()); 233 234 hash.Compute(AK::FNVHash32::ComputeLowerCase(importItem.path.toUTF8())); 235 } 236 237 return hash.Get(); 238 } 239 240 inline juce::String createImportSummary(const juce::String& applicationName, juce::Time currentTime, const Import::Summary& summary, const Import::Task::Options& importTaskOptions) 241 { 242 juce::String report; 243 244 auto hasErrors = !summary.errors.empty(); 245 246 report << "<style>table td, th { border:1px solid black; padding:10px; }"; 247 report << "table { border-collapse:collapse; }"; 248 report << "table th { text-align: left; }</style>"; 249 report << applicationName + ": Wwise Import Summary " + currentTime.formatted("%Y-%m-%d %H:%M:%S") + "<br><br>"; 250 report << "Import Destination: " + importTaskOptions.importDestination + "<br>"; 251 report << "Container Name Exists: " + ImportHelper::containerNameExistsOptionToReadableString(importTaskOptions.containerNameExistsOption) + "<br>"; 252 report << "Apply Template: " + ImportHelper::applyTemplateOptionToReadableString(importTaskOptions.applyTemplateOption) + "<br><br>"; 253 254 report << "Objects created: " + juce::String(summary.getNumObjectsCreated()) + "<br>"; 255 report << "Object Templates Applied: " + juce::String(summary.getNumObjectTemplatesApplied()) + "<br>"; 256 report << "Audio Files Imported: " + juce::String(summary.getNumAudiofilesTransfered()) + "<br>"; 257 258 if(hasErrors) 259 report << "<br>Wwise Imported with <a href='#waapi-errors'>Errors!</a><br>"; 260 261 report << "<h3>Wwise Objects</h3>"; 262 report << "<pre><table><tr><th>Object Path</th><th>Type</th><th>Object Status</th><th>Originals Wav</th><th>Wav Status</th><th>Property Template Applied</th></tr>"; 263 264 for(const auto& [objectPath, object] : summary.objects) 265 { 266 report << "<tr><td>" + objectPath + "</td><td>" + WwiseHelper::objectTypeToReadableString(object.type) + "</td>"; 267 report << "<td>" + ImportHelper::objectStatusToReadableString(object.objectStatus) + "</td><td>" + object.originalWavFilePath + "</td>"; 268 report << "<td>" + ImportHelper::wavStatusToReadableString(object.wavStatus) + "</td><td>" + object.propertyTemplatePath + "</td></tr>"; 269 } 270 271 report << "</table></pre>"; 272 273 if(hasErrors) 274 { 275 report << "<h3 id='waapi-errors'>Waapi Errors</h3>"; 276 277 for(const auto& error : summary.errors) 278 { 279 report << "<h4>" + error.procedureUri + "</h4>"; 280 281 // Using juce::JSON for pretty printing 282 report << "<pre>" + juce::JSON::toString(juce::JSON::fromString(error.raw)) + "</pre>"; 283 } 284 } 285 286 return report; 287 } 288 } // namespace AK::WwiseTransfer::ImportHelper