WwiseHelper.h (8877B)
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 "Model/IDs.h" 19 #include "Model/Wwise.h" 20 21 #include <juce_gui_basics/juce_gui_basics.h> 22 #include <regex> 23 24 namespace AK::WwiseTransfer::WwiseHelper 25 { 26 inline bool validateObjectTypeParentChildRelationShip(Wwise::ObjectType parent, Wwise::ObjectType child) 27 { 28 using namespace Wwise; 29 30 switch(parent) 31 { 32 case ObjectType::BlendContainer: 33 case ObjectType::RandomContainer: 34 case ObjectType::SequenceContainer: 35 case ObjectType::SwitchContainer: 36 { 37 static constexpr std::initializer_list<ObjectType> children{ 38 ObjectType::SwitchContainer, 39 ObjectType::RandomContainer, 40 ObjectType::SequenceContainer, 41 ObjectType::BlendContainer, 42 ObjectType::SoundSFX, 43 ObjectType::SoundVoice, 44 }; 45 46 return std::find(children.begin(), children.end(), child) != children.end(); 47 }; 48 case ObjectType::ActorMixer: 49 case ObjectType::VirtualFolder: 50 case ObjectType::WorkUnit: 51 { 52 static constexpr std::initializer_list<ObjectType> children{ 53 ObjectType::WorkUnit, 54 ObjectType::VirtualFolder, 55 ObjectType::ActorMixer, 56 ObjectType::SwitchContainer, 57 ObjectType::RandomContainer, 58 ObjectType::SequenceContainer, 59 ObjectType::BlendContainer, 60 ObjectType::SoundSFX, 61 ObjectType::SoundVoice, 62 }; 63 64 return std::find(children.begin(), children.end(), child) != children.end(); 65 }; 66 case ObjectType::PhysicalFolder: 67 { 68 static constexpr std::initializer_list<ObjectType> children{ 69 ObjectType::PhysicalFolder, 70 ObjectType::WorkUnit, 71 }; 72 73 return std::find(children.begin(), children.end(), child) != children.end(); 74 }; 75 default: 76 return false; 77 } 78 }; 79 80 inline juce::String objectTypeToReadableString(Wwise::ObjectType objectType) 81 { 82 using namespace Wwise; 83 84 switch(objectType) 85 { 86 case ObjectType::ActorMixer: 87 return "Actor-Mixer"; 88 case ObjectType::AudioFileSource: 89 return "Audio File Source"; 90 case ObjectType::BlendContainer: 91 return "Blend Container"; 92 case ObjectType::PhysicalFolder: 93 return "Physical Folder"; 94 case ObjectType::RandomContainer: 95 return "Random Container"; 96 case ObjectType::SequenceContainer: 97 return "Sequence Container"; 98 case ObjectType::SoundSFX: 99 return "Sound SFX"; 100 case ObjectType::SoundVoice: 101 return "Sound Voice"; 102 case ObjectType::SwitchContainer: 103 return "Switch Container"; 104 case ObjectType::VirtualFolder: 105 return "Virtual Folder"; 106 case ObjectType::WorkUnit: 107 return "Work Unit"; 108 case ObjectType::Sound: 109 return "Sound"; 110 default: 111 return "Unknown"; 112 } 113 }; 114 115 inline Wwise::ObjectType stringToObjectType(const juce::String& objectTypeAsString) 116 { 117 using namespace Wwise; 118 119 if(objectTypeAsString == "AudioFileSource" || objectTypeAsString == "Audio File Source") 120 return ObjectType::AudioFileSource; 121 else if(objectTypeAsString == "ActorMixer" || objectTypeAsString == "Actor Mixer" || objectTypeAsString == "Actor-Mixer") 122 return ObjectType::ActorMixer; 123 else if(objectTypeAsString == "BlendContainer" || objectTypeAsString == "Blend Container") 124 return ObjectType::BlendContainer; 125 else if(objectTypeAsString == "Folder") 126 return ObjectType::VirtualFolder; 127 else if(objectTypeAsString == "RandomSequenceContainer" || objectTypeAsString == "Random Container") 128 return ObjectType::RandomContainer; 129 else if(objectTypeAsString == "SequenceContainer" || objectTypeAsString == "Sequence Container") 130 return ObjectType::SequenceContainer; 131 else if(objectTypeAsString == "Sound") 132 return ObjectType::Sound; 133 else if(objectTypeAsString == "SoundSFX" || objectTypeAsString == "Sound SFX") 134 return ObjectType::SoundSFX; 135 else if(objectTypeAsString == "Sound Voice") 136 return ObjectType::SoundVoice; 137 else if(objectTypeAsString == "SwitchContainer" || objectTypeAsString == "Switch Container") 138 return ObjectType::SwitchContainer; 139 else if(objectTypeAsString == "WorkUnit" || objectTypeAsString == "Work Unit") 140 return ObjectType::WorkUnit; 141 else if(objectTypeAsString == "Virtual Folder") 142 return ObjectType::VirtualFolder; 143 else if(objectTypeAsString == "Physical Folder") 144 return ObjectType::PhysicalFolder; 145 else 146 return ObjectType::Unknown; 147 }; 148 149 inline juce::String buildObjectPathNode(Wwise::ObjectType objectType, const juce::String& name) 150 { 151 return "\\<" + objectTypeToReadableString(objectType) + ">" + name; 152 } 153 154 inline juce::String pathToPathWithoutObjectTypes(const juce::String& objectPath) 155 { 156 static std::regex pattern("<.+?>"); 157 auto result = std::regex_replace(objectPath.toStdString(), pattern, ""); 158 return juce::String(result); 159 } 160 161 inline std::vector<juce::String> pathToPathParts(const juce::String& objectPath) 162 { 163 juce::StringArray parts; 164 parts.addTokens(objectPath.trimCharactersAtStart("\\"), "\\", ""); 165 166 std::vector<juce::String> objectPathParts; 167 for(auto& part : parts) 168 { 169 objectPathParts.emplace_back(part); 170 } 171 172 return objectPathParts; 173 } 174 175 inline std::vector<juce::String> pathToAncestorPaths(const juce::String& objectPath) 176 { 177 std::vector<juce::String> ancestors; 178 179 auto parts = pathToPathParts(objectPath); 180 181 juce::String current; 182 for(int i = 0; i < parts.size() - 1; ++i) 183 { 184 current << "\\" << parts[i]; 185 ancestors.emplace_back(current); 186 } 187 188 return ancestors; 189 } 190 191 inline juce::String pathToObjectName(const juce::String& objectPath) 192 { 193 auto lastIndexGreaterThan = objectPath.lastIndexOf(">"); 194 auto lastIndexOfPathSeperator = objectPath.lastIndexOf("\\"); 195 196 if(lastIndexGreaterThan > lastIndexOfPathSeperator) 197 return objectPath.substring(lastIndexGreaterThan + 1); 198 else 199 return objectPath.substring(lastIndexOfPathSeperator + 1); 200 } 201 202 inline Wwise::ObjectType pathToObjectType(const juce::String& objectPath) 203 { 204 if(objectPath == "\\Actor-Mixer Hierarchy") 205 return Wwise::ObjectType::ActorMixer; 206 207 auto lastIndexLessThan = objectPath.lastIndexOf("<"); 208 auto lastIndexGreaterThan = objectPath.lastIndexOf(">"); 209 210 return WwiseHelper::stringToObjectType(objectPath.substring(lastIndexLessThan + 1, lastIndexGreaterThan)); 211 } 212 213 inline juce::ValueTree versionToValueTree(const Wwise::Version& version) 214 { 215 juce::ValueTree valueTree(IDs::version); 216 217 valueTree.setProperty(IDs::year, version.year, nullptr); 218 valueTree.setProperty(IDs::major, version.major, nullptr); 219 valueTree.setProperty(IDs::minor, version.minor, nullptr); 220 valueTree.setProperty(IDs::build, version.build, nullptr); 221 222 return valueTree; 223 } 224 225 inline Wwise::Version valueTreeToVersion(juce::ValueTree valueTree) 226 { 227 return { 228 valueTree[IDs::year], 229 valueTree[IDs::major], 230 valueTree[IDs::minor], 231 valueTree[IDs::build], 232 }; 233 } 234 235 inline juce::ValueTree languagesToValueTree(const std::vector<juce::String>& languages) 236 { 237 juce::ValueTree languagesValueTree(IDs::languages); 238 239 for(const auto& language : languages) 240 { 241 juce::ValueTree languageValueTree(IDs::language); 242 languageValueTree.setProperty(IDs::languageName, language, nullptr); 243 244 languagesValueTree.appendChild(languageValueTree, nullptr); 245 } 246 247 return languagesValueTree; 248 } 249 250 inline std::vector<juce::String> valueTreeToLanguages(juce::ValueTree valueTree) 251 { 252 std::vector<juce::String> languages; 253 254 for(int i = 0; i < valueTree.getNumChildren(); ++i) 255 { 256 languages.emplace_back(valueTree.getChild(i)[IDs::languageName].toString()); 257 } 258 259 return languages; 260 } 261 262 inline juce::String getCommonAncestor(const juce::String& firstPath, const juce::String& secondPath) 263 { 264 auto firstAsParts = WwiseHelper::pathToPathParts(firstPath); 265 auto lastAsParts = WwiseHelper::pathToPathParts(secondPath); 266 267 juce::String commonAncestorPath; 268 for(int i = 0; i < firstAsParts.size() && i < lastAsParts.size(); ++i) 269 { 270 if(firstAsParts[i] == lastAsParts[i]) 271 commonAncestorPath << "\\" << firstAsParts[i]; 272 else 273 break; 274 } 275 276 return commonAncestorPath; 277 } 278 279 inline bool isPathComplete(const juce::String path) 280 { 281 for(int i = 1; i < path.length(); ++i) 282 { 283 if(path[i] == '\\' && (path[i - 1] == '\\' || path[i - 1] == '>')) 284 return false; 285 286 if(i == path.length() - 1 && (path[i] == '>' || path[i] == '\\')) 287 return false; 288 } 289 290 return true; 291 } 292 } // namespace AK::WwiseTransfer::WwiseHelper