Feat : Wwise Integration

This commit is contained in:
Alex
2026-03-23 14:28:21 +01:00
parent 627d787695
commit 004bc328ed
1149 changed files with 226567 additions and 19 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55225daa38879114ea88811121776ae5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
View File
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 41d8f072980a9234daf4f7772c6054bd
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b403f84d796337a49bc375e60203d976
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
{
"name": "AK.Wwise.Unity.API.Editor",
"rootNamespace": "",
"references": [
"AK.Wwise.Unity.API",
"AK.Wwise.Unity.API.WwiseTypes",
"AK.Wwise.Unity.MonoBehaviour",
"Ak.Wwise.Api.WAAPI",
"AK.Wwise.Unity.ProjectDatabase",
"AK.Wwise.Unity.Utilities",
"AK.Wwise.Unity.Logging"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [
"!UNITY_SERVER"
],
"versionDefines": [
{
"name": "com.unity.addressables",
"expression": "1.8",
"define": "UNITY_ADDRESSABLES"
},
{
"name": "com.audiokinetic.wwise.addressables",
"expression": "1.0.0",
"define": "AK_WWISE_ADDRESSABLES"
}
],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a459e7d00546ebd45a427b049e86d034
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,126 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System;
using System.Threading.Tasks;
using UnityEngine;
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
namespace Wwise.API.Editor.SoundBankDirectoryWatcher.Common
{
[UnityEditor.InitializeOnLoad]
public class AkSoundBankDirectoryWatcher
{
private static readonly AkSoundBankDirectoryWatcher instance;
public static AkSoundBankDirectoryWatcher Instance { get { return instance; } }
private bool emptyPathErrorWasLogged = false;
private string soundBankDirectoryPath;
private string platformName;
private string languageName;
private bool forceUpdate = false;
private bool initCallbackRequired = false;
private const int SecondsBetweenChecks = 3;
private static System.DateTime s_lastFileCheck = System.DateTime.Now.AddSeconds(-SecondsBetweenChecks);
private static System.DateTime s_lastSoundBankDirectoryUpdate = System.DateTime.MinValue;
private AkSoundBankDirectoryWatcher()
{
platformName = AkBasePathGetter.GetPlatformName();
UnityEditor.EditorApplication.update += OnEditorUpdate;
WwiseProjectDatabase.SoundBankDirectoryUpdated += AkPlatformPluginList.ExecuteParse;
forceUpdate = true;
Execute();
}
static AkSoundBankDirectoryWatcher()
{
instance = new AkSoundBankDirectoryWatcher();
}
~AkSoundBankDirectoryWatcher()
{
UnityEditor.EditorApplication.update -= OnEditorUpdate;
WwiseProjectDatabase.SoundBankDirectoryUpdated -= AkPlatformPluginList.ExecuteParse;
}
private void Execute()
{
if (initCallbackRequired)
{
initCallbackRequired = false;
WwiseProjectDatabase.PostInitCallback();
}
if (AkWwiseEditorSettings.Instance.WwiseProjectPath == "")
{
if (!emptyPathErrorWasLogged)
{
WwiseLogger.Warning("WwiseProjectPath is empty in the Wwise integration settings. Set it in order to enable the project database.");
emptyPathErrorWasLogged = true;
}
return;
}
if (System.DateTime.Now.Subtract(s_lastFileCheck).Seconds >= SecondsBetweenChecks &&
!UnityEditor.EditorApplication.isCompiling && !UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode && !AkUtilities.GeneratingSoundBanks)
{
var filename = AkWwiseEditorSettings.GetRootOutputPath();
if (string.IsNullOrEmpty(filename))
{
return;
}
var wProjPath = System.IO.Path.Combine(AkBasePathGetter.GetWwiseProjectPath());
var time = System.IO.File.GetLastWriteTime(filename);
Task.Run(() => InitProjectDB(filename, wProjPath, time));
s_lastFileCheck = System.DateTime.Now;
}
}
private void OnEditorUpdate()
{
Execute();
}
private async Task InitProjectDB(string filename, string wProjPath, DateTime time)
{
if (time > s_lastSoundBankDirectoryUpdate || forceUpdate)
{
forceUpdate = false;
s_lastSoundBankDirectoryUpdate = time;
if (!await WwiseProjectDatabase.InitAsync(filename, platformName))
{
var userWarning = "";
if (!AkUtilities.IsSettingEnabled(wProjPath,"GenerateSoundBankJSON"))
{
userWarning = "Ensure that the Generate JSON Metadata option is enabled in the Wwise Project Settings on the SoundBanks tab, then regenerate the SoundBanks.";
}
else
{
userWarning = "Ensure that the Root Output Path in the Integration Settings matches the Root Output Path in the Wwise Project Settings on the SoundBanks tab, then regenerate the SoundBanks.";
}
WwiseLogger.Error("Cannot find ProjectInfo.json at " + filename + ". " + userWarning);
}
initCallbackRequired = true;
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 49fb232e32de4534b9aba3e5decad751
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 36a9007a1533f7147913a95a45516d31
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3623a364982648c41aa4417832ac717f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,63 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.VersionControl;
[UnityEditor.InitializeOnLoad]
public abstract class AkPlatformPluginActivator
{
public abstract string WwisePlatformName { get; }
public abstract string PluginDirectoryName { get; }
public virtual ISet<string> Architectures => null;
public virtual string DSPDirectoryPath => string.Empty;
public virtual string StaticPluginRegistrationName => null;
public virtual string StaticPluginDefine => null;
public virtual bool RequiresStaticPluginRegistration => false;
public virtual void FilterOutPlatformIfNeeded(BuildTarget target, PluginImporter pluginImporter,
string pluginPlatform)
{
}
public virtual bool IsPluginSDKVersionCompatible(string pluginSDKVersion)
{
return true;
}
internal virtual bool IsBuildEnvironmentValid()
{
return true;
}
internal string[] GetPluginPathParts(string pluginPath)
{
var indexOfPluginFolder = pluginPath.IndexOf(AkPluginActivatorConstants.WwisePluginFolder, StringComparison.OrdinalIgnoreCase);
return pluginPath.Substring(indexOfPluginFolder + AkPluginActivatorConstants.WwisePluginFolder.Length + 1).Split('/');
}
public abstract AkPluginActivator.PluginImporterInformation GetPluginImporterInformation(PluginImporter pluginImporter);
internal abstract bool ConfigurePlugin(PluginImporter pluginImporter, AkPluginActivator.PluginImporterInformation pluginImporterInformation);
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 51091a89998818947a002e921393ccf2
@@ -0,0 +1,283 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using AK.Wwise.Unity.Logging;
internal class AkPlatformPluginList
{
private static readonly Dictionary<string, System.DateTime> s_LastParsed = new Dictionary<string, System.DateTime>();
private static readonly Dictionary<string, HashSet<AkPluginInfo>> s_PerPlatformPlugins = new Dictionary<string, HashSet<AkPluginInfo>>();
internal static void GetPluginsUsedForPlatform(string deploymentTargetName, out HashSet<AkPluginInfo> UsedPlugins)
{
s_PerPlatformPlugins.TryGetValue(deploymentTargetName, out UsedPlugins);
}
internal static bool ContainsPlatform(string platform)
{
return s_PerPlatformPlugins.ContainsKey(platform);
}
public static bool IsPluginUsed(AkPlatformPluginActivator in_config, string in_UnityPlatform, string in_PluginName)
{
var pluginDSPPlatform = in_config.WwisePlatformName;
if (!s_PerPlatformPlugins.ContainsKey(pluginDSPPlatform))
{
return false; //XML not parsed, don't touch anything.
}
if (in_PluginName.Contains("AkUnitySoundEngine"))
{
return true;
}
var pluginName = in_PluginName;
if (in_PluginName.StartsWith("lib"))
{
pluginName = in_PluginName.Substring(3);
}
const string factory = "Factory";
int indexOfFactory = in_PluginName.IndexOf(factory);
// Ensure the plugin name ends with "Factory.h"
if (indexOfFactory != -1 && indexOfFactory + factory.Length == in_PluginName.Length)
{
pluginName = in_PluginName.Substring(0, indexOfFactory);
}
System.Collections.Generic.HashSet<AkPluginInfo> plugins;
if (s_PerPlatformPlugins.TryGetValue(pluginDSPPlatform, out plugins))
{
if (!in_config.RequiresStaticPluginRegistration)
{
foreach (var pluginInfo in plugins)
{
if (pluginInfo.DllName == pluginName ||
(pluginInfo.StaticLibName == "AkMeterFX" && pluginName.Contains("AkSoundEngine")))
{
return true;
}
}
}
//Exceptions
if (!string.IsNullOrEmpty(in_config.StaticPluginRegistrationName) && pluginName.Contains(in_config.StaticPluginRegistrationName))
{
return true;
}
//WebGL, iOS, tvOS, visionOS, and Switch deal with the static libs directly, unlike all other platforms.
//Luckily the DLL name is always a subset of the lib name.
foreach (var pluginInfo in plugins)
{
if (pluginInfo.StaticLibName == pluginName)
{
return true;
}
}
}
return false;
}
public static void ExecuteParse()
{
Update();
}
public static void Update(bool forceUpdate = false)
{
//Gather all GeneratedSoundBanks folder from the project
var allPaths = AkUtilities.GetAllBankPaths(AkWwiseEditorSettings.WwiseProjectAbsolutePath);
var bNeedRefresh = false;
var projectDir = AkBasePathGetter.GetWwiseProjectDirectory();
var baseSoundBankPath = AkWwiseEditorSettings.GetRootOutputPath();
AkWwiseInitializationSettings.UpdatePlatforms();
//make a copy of the platform map and handle "special" custom platforms
var platformMap = new Dictionary<string, List<string>>();
foreach (var key in AkUtilities.PlatformMapping.Keys)
{
platformMap.Add(key, new List<string>(AkUtilities.PlatformMapping[key]));
foreach (var customPF in AkUtilities.PlatformMapping[key])
{
if (customPF != key && (AkWwiseInitializationSettings.PlatformSettings.IsDistinctPlatform(customPF)))
{
platformMap.Add(customPF, new List<string> { customPF });
platformMap[key].Remove(customPF);
}
}
if (platformMap[key].Count==0)
{
platformMap.Remove(key);
}
}
//Go through all BasePlatforms
foreach (var pairPF in platformMap)
{
//Go through all custom platforms related to that base platform and check if any of the bank files were updated.
var bParse = forceUpdate;
var fullPaths = new System.Collections.Generic.List<string>();
foreach (var customPF in pairPF.Value)
{
string bankPath;
if (!allPaths.TryGetValue(customPF, out bankPath))
continue;
var pluginFile = "";
try
{
pluginFile = System.IO.Path.Combine(projectDir, System.IO.Path.Combine(bankPath, "PluginInfo.xml"));
pluginFile = pluginFile.Replace('/', System.IO.Path.DirectorySeparatorChar);
if (!System.IO.File.Exists(pluginFile))
{
//Try in StreamingAssets too.
pluginFile = System.IO.Path.Combine(System.IO.Path.Combine(baseSoundBankPath, customPF), "PluginInfo.xml");
if (!System.IO.File.Exists(pluginFile))
continue;
}
fullPaths.Add(pluginFile);
var t = System.IO.File.GetLastWriteTime(pluginFile);
var lastTime = System.DateTime.MinValue;
bool bParsedBefore = s_LastParsed.TryGetValue(customPF, out lastTime);
if (!bParsedBefore || lastTime < t)
{
bParse = true;
s_LastParsed[customPF] = t;
}
}
catch (System.Exception ex)
{
WwiseLogger.Error(pluginFile + " could not be parsed. " + ex.Message);
}
}
if (bParse)
{
var platform = pairPF.Key;
var newDlls = ParsePlugins(platform);
System.Collections.Generic.HashSet<AkPluginInfo> oldDlls = null;
s_PerPlatformPlugins.TryGetValue(platform, out oldDlls);
s_PerPlatformPlugins[platform] = newDlls;
//Check if there was any change.
if (!bNeedRefresh && oldDlls != null)
{
if (oldDlls.Count == newDlls.Count)
{
oldDlls.IntersectWith(newDlls);
}
bNeedRefresh |= oldDlls.Count != newDlls.Count;
}
else
{
bNeedRefresh |= newDlls.Count > 0;
}
}
}
if (bNeedRefresh)
{
AkPluginActivator.ActivatePluginsForEditor();
}
}
private static bool PlatformUsesStaticLibs(string platform)
{
var pair = AkPluginActivator.BuildTargetToPlatformPluginActivator.FirstOrDefault(x => x.Value.WwisePlatformName == platform);
if (pair.Equals(default(KeyValuePair<BuildTarget, AkPlatformPluginActivator>)))
{
// Platform not found
return false;
}
return pair.Value.RequiresStaticPluginRegistration;
}
private static HashSet<AkPluginInfo> ParsePlugins(string platform)
{
var newPlugins = new System.Collections.Generic.HashSet<AkPluginInfo>();
var usesStaticLibs = PlatformUsesStaticLibs(platform);
try
{
WwisePluginRefArray pluginRefArray = new WwisePluginRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetPluginCount(); i++)
{
var pluginRef = pluginRefArray[i];
var rawPluginID = pluginRef.Id;
if (rawPluginID == 0)
{
continue;
}
AkPluginActivatorConstants.PluginID pluginID = (AkPluginActivatorConstants.PluginID)rawPluginID;
if (AkPluginActivatorConstants.alwaysSkipPluginsIDs.Contains(pluginID))
{
continue;
}
var dll = string.Empty;
if (!usesStaticLibs && AkPluginActivatorConstants.builtInPluginIDs.Contains(pluginID))
{
continue;
}
if (string.IsNullOrEmpty(dll))
{
dll = pluginRef.DLL;
}
var staticLibName = pluginRef.StaticLib;
AkPluginInfo newPluginInfo = new AkPluginInfo();
newPluginInfo.PluginID = rawPluginID;
newPluginInfo.DllName = dll;
newPluginInfo.StaticLibName = staticLibName;
if (string.IsNullOrEmpty(newPluginInfo.StaticLibName) && !AkPluginActivatorConstants.PluginIDToStaticLibName.TryGetValue(pluginID, out newPluginInfo.StaticLibName))
{
newPluginInfo.StaticLibName = dll;
}
newPlugins.Add(newPluginInfo);
}
}
catch (System.Exception ex)
{
WwiseLogger.Error("Plugins could not be parsed. " + ex.Message);
}
return newPlugins;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7a2902d2209b5cd48a0f4314a7199ff4
@@ -0,0 +1,319 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using AK.Wwise.Unity.Logging;
[InitializeOnLoad]
public class AkPluginActivator : UnityEditor.AssetPostprocessor
{
private const string EditorConfiguration = AkPluginActivatorConstants.CONFIG_PROFILE;
private static bool bIsAlreadyActivating = false;
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess() || bIsAlreadyActivating)
{
return;
}
if (didDomainReload)
{
ActivatePluginsForEditor();
}
}
public static string GetCurrentConfig()
{
var CurrentConfig = AkWwiseProjectInfo.GetData().CurrentPluginConfig;
if (string.IsNullOrEmpty(CurrentConfig))
{
CurrentConfig = AkPluginActivatorConstants.CONFIG_PROFILE;
}
return CurrentConfig;
}
public static Dictionary<BuildTarget, AkPlatformPluginActivator> BuildTargetToPlatformPluginActivator = new Dictionary<BuildTarget, AkPlatformPluginActivator>();
public static void RegisterPlatformPluginActivator(BuildTarget target, AkPlatformPluginActivator platformPluginActivator)
{
WwiseLogger.Verbose("Adding platform " + target.ToString() + " to PluginActivator");
BuildTargetToPlatformPluginActivator.Add(target, platformPluginActivator);
}
internal static string GetPluginInfoPlatform(string path)
{
var indexOfPluginFolder = path.IndexOf(AkPluginActivatorConstants.WwisePluginFolder, StringComparison.OrdinalIgnoreCase);
if (indexOfPluginFolder == -1)
{
return null;
}
return path.Substring(indexOfPluginFolder + AkPluginActivatorConstants.WwisePluginFolder.Length + 1).Split('/')[0];
}
internal static List<PluginImporter> GetWwisePluginImporters(string platformFilter = "")
{
PluginImporter[] pluginImporters = PluginImporter.GetAllImporters();
List<PluginImporter> wwisePlugins = new List<PluginImporter>();
foreach (var pluginImporter in pluginImporters)
{
if (pluginImporter.assetPath.Contains("Wwise/API/"))
{
if (string.IsNullOrEmpty(platformFilter) || platformFilter == GetPluginInfoPlatform(pluginImporter.assetPath))
{
wwisePlugins.Add(pluginImporter);
}
}
}
return wwisePlugins;
}
public class PluginImporterInformation
{
public string PluginName;
public string PluginArch;
public string PluginSDKVersion;
public string PluginConfig;
public string EditorOS;
public string EditorCPU;
public bool IsX86 => PluginArch == "x86";
public bool IsX64 => PluginArch == "x86_64";
public bool IsSupportLibrary => AkPluginActivatorConstants.SupportLibraries.Contains(PluginName);
}
public static void ActivatePluginsForDeployment(BuildTarget target, bool Activate)
{
if (!BuildTargetToPlatformPluginActivator.TryGetValue(target, out var platformPluginActivator))
{
WwiseLogger.Error("Unable to find Plugin Activator for Build Target " + target + ". Check that platform " + target + " has been installed as part of your Wwise Integration.");
return;
}
if (!platformPluginActivator.IsBuildEnvironmentValid())
{
WwiseLogger.Error("Build Environment for platform " + platformPluginActivator.WwisePlatformName + " is not valid. Current BuildTarget is " + EditorUserBuildSettings.activeBuildTarget);
return;
}
bIsAlreadyActivating = true;
if (Activate)
{
StaticPluginRegistration.Setup(target, platformPluginActivator);
}
var importers = GetWwisePluginImporters();
var assetChanged = false;
foreach (var pluginImporter in importers)
{
if (pluginImporter.GetCompatibleWithAnyPlatform())
{
WwiseLogger.Log("Plugin" + pluginImporter.assetPath + " was compatible with the \"any\" platform, deactivating.");
pluginImporter.SetCompatibleWithAnyPlatform(false);
assetChanged = true;
}
var pluginPlatform = GetPluginInfoPlatform(pluginImporter.assetPath);
if (pluginPlatform != platformPluginActivator.PluginDirectoryName)
{
if (Activate)
{
platformPluginActivator.FilterOutPlatformIfNeeded(target, pluginImporter, pluginPlatform);
}
continue;
}
var pluginInfo = platformPluginActivator.GetPluginImporterInformation(pluginImporter);
var bShouldActivatePlugin = platformPluginActivator.ConfigurePlugin(pluginImporter, pluginInfo);
if (pluginInfo.PluginConfig == "DSP")
{
if (!pluginInfo.IsSupportLibrary && !AkPlatformPluginList.IsPluginUsed(platformPluginActivator, pluginPlatform, Path.GetFileNameWithoutExtension(pluginImporter.assetPath)))
{
WwiseLogger.Verbose("Plugin" + pluginImporter.assetPath + " is not used, skipping.");
bShouldActivatePlugin = false;
}
}
else if (pluginInfo.PluginConfig != GetCurrentConfig())
{
WwiseLogger.Verbose("Plugin" + pluginImporter.assetPath + " does not match current config (" + GetCurrentConfig() + "). Skipping.");
bShouldActivatePlugin = false;
}
if (!string.IsNullOrEmpty(pluginInfo.PluginSDKVersion))
{
var sdkCompatible = platformPluginActivator.IsPluginSDKVersionCompatible(pluginInfo.PluginSDKVersion);
WwiseLogger.Verbose("Plugin " + pluginImporter.assetPath + " is " + (sdkCompatible ? "" : "NOT ") + "compatible with current platform SDK");
bShouldActivatePlugin &= sdkCompatible;
}
bool isCompatibleWithPlatform = bShouldActivatePlugin && Activate;
WwiseLogger.Verbose("Will set plugin " + pluginImporter.assetPath + " as " + (isCompatibleWithPlatform ? "" : "NOT ") + "compatible with platform.");
assetChanged |= pluginImporter.GetCompatibleWithPlatform(target) != isCompatibleWithPlatform;
pluginImporter.SetCompatibleWithPlatform(target, isCompatibleWithPlatform);
if (assetChanged)
{
WwiseLogger.Verbose("Changed plugin " + pluginImporter.assetPath + ", saving and reimporting.");
pluginImporter.SaveAndReimport();
}
}
bIsAlreadyActivating = false;
}
public static void ActivatePluginsForEditor()
{
var importers = GetWwisePluginImporters();
var changedSomeAssets = false;
bIsAlreadyActivating = true;
AssetDatabase.StartAssetEditing();
foreach (var pluginImporter in importers)
{
var pluginPlatform = GetPluginInfoPlatform(pluginImporter.assetPath);
if (string.IsNullOrEmpty(pluginPlatform) || (pluginPlatform != "Mac" && pluginPlatform != "Windows" && pluginPlatform != "Linux"))
{
pluginImporter.SetCompatibleWithEditor(false);
changedSomeAssets = true;
continue;
}
BuildTarget pluginBuildTarget;
switch (pluginPlatform)
{
case "Windows":
pluginBuildTarget = BuildTarget.StandaloneWindows64;
break;
case "Mac":
pluginBuildTarget = BuildTarget.StandaloneOSX;
break;
case "Linux":
pluginBuildTarget = BuildTarget.StandaloneLinux64;
break;
default:
pluginBuildTarget = BuildTarget.StandaloneWindows64;
break;
}
if (!BuildTargetToPlatformPluginActivator.TryGetValue(pluginBuildTarget, out var platformPluginActivator))
{
WwiseLogger.Log("Build Target " + pluginBuildTarget + " not supported.");
bIsAlreadyActivating = false;
AssetDatabase.StopAssetEditing();
return;
}
var pluginInfo = platformPluginActivator.GetPluginImporterInformation(pluginImporter);
var assetChanged = false;
if (pluginImporter.GetCompatibleWithAnyPlatform())
{
WwiseLogger.Verbose("ActivatePluginsForEditor: Plugin" + pluginImporter.assetPath + " was compatible with the \"any\" platform, deactivating.");
pluginImporter.SetCompatibleWithAnyPlatform(false);
assetChanged = true;
}
var bActivate = false;
if (!string.IsNullOrEmpty(pluginInfo.EditorOS))
{
if (pluginInfo.PluginConfig == "DSP")
{
if (!AkPlatformPluginList.ContainsPlatform(platformPluginActivator.WwisePlatformName))
{
continue;
}
bActivate = AkPlatformPluginList.IsPluginUsed(platformPluginActivator, pluginPlatform,
Path.GetFileNameWithoutExtension(pluginImporter.assetPath));
}
else
{
bActivate = pluginInfo.PluginConfig == EditorConfiguration;
}
if (bActivate)
{
WwiseLogger.Verbose("ActivatePluginsForEditor: Activating " + pluginImporter.assetPath);
pluginImporter.SetEditorData("CPU", pluginInfo.EditorCPU);
pluginImporter.SetEditorData("OS", pluginInfo.EditorOS);
}
assetChanged |= pluginImporter.GetCompatibleWithEditor() != bActivate;
pluginImporter.SetCompatibleWithEditor(bActivate);
}
else
{
WwiseLogger.Verbose("ActivatePluginsForEditor: Could not determine EditorOS for " + pluginImporter.assetPath);
}
if (assetChanged)
{
changedSomeAssets = true;
WwiseLogger.Verbose("ActivatePluginsForEditor: Changed plugin " + pluginImporter.assetPath + ", saving and reimporting.");
}
}
AssetDatabase.StopAssetEditing();
if (changedSomeAssets)
{
WwiseLogger.Log("Plugins successfully activated for " + EditorConfiguration + " in Editor.");
AssetDatabase.Refresh();
}
bIsAlreadyActivating = false;
}
public static void DeactivateAllPlugins()
{
var importers = GetWwisePluginImporters();
foreach (var pluginImporter in importers)
{
if (pluginImporter.assetPath.IndexOf(AkPluginActivatorConstants.WwisePluginFolder, StringComparison.OrdinalIgnoreCase) == -1)
{
continue;
}
pluginImporter.SetCompatibleWithAnyPlatform(false);
pluginImporter.SaveAndReimport();
}
}
public static void ForceUpdate()
{
AkPlatformPluginList.Update(true);
Update();
}
public static void Update()
{
AkPluginActivatorMenus.CheckMenuItems(GetCurrentConfig());
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7ee9c63a2f8292a4297f0e882f20094a
@@ -0,0 +1,194 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
public class AkPluginActivatorConstants
{
internal const string WwisePluginFolder = "Runtime/Plugins";
public const string CONFIG_DEBUG = "Debug";
public const string CONFIG_PROFILE = "Profile";
public const string CONFIG_RELEASE = "Release";
internal static readonly System.Collections.Generic.HashSet<PluginID> builtInPluginIDs =
new System.Collections.Generic.HashSet<PluginID>
{
PluginID.AkCompressor,
PluginID.AkDelay,
PluginID.AkExpander,
PluginID.AkGain,
PluginID.AkMatrixReverb,
PluginID.AkParametricEQ,
PluginID.AkPeakLimiter,
PluginID.AkRoomVerb,
PluginID.AkReflect,
#if !UNITY_2018_3_OR_NEWER
PluginID.VitaReverb,
PluginID.VitaCompressor,
PluginID.VitaDelay,
PluginID.VitaDistortion,
PluginID.VitaEQ,
#endif
};
internal static readonly System.Collections.Generic.HashSet<PluginID> alwaysSkipPluginsIDs =
new System.Collections.Generic.HashSet<PluginID>
{
PluginID.SineGenerator,
PluginID.SinkAuxiliary,
PluginID.SinkCommunication,
PluginID.SinkControllerHeadphones,
PluginID.SinkControllerSpeaker,
PluginID.SinkDVRByPass,
PluginID.SinkNoOutput,
PluginID.SinkSystem,
PluginID.ToneGenerator,
PluginID.WwiseSilence,
PluginID.AkAudioInput,
};
internal static readonly System.Collections.Generic.Dictionary<PluginID, string> PluginIDToStaticLibName =
new System.Collections.Generic.Dictionary<PluginID, string>
{
{ PluginID.Ak3DAudioBedMixer, "Ak3DAudioBedMixerFX" },
{ PluginID.AkAudioInput, "AkAudioInputSource" },
{ PluginID.AkCompressor, "AkCompressorFX" },
{ PluginID.AkRouterMixer, "AkRouterMixerFX" },
{ PluginID.AkChannelRouter, "AkChannelRouterFX" },
{ PluginID.AkConvolutionReverb, "AkConvolutionReverbFX" },
{ PluginID.AkDelay, "AkDelayFX" },
{ PluginID.AkExpander, "AkCompressorFX" }, // Compressor lib contains Expander
{ PluginID.AkFlanger, "AkFlangerFX" },
{ PluginID.AkGain, "AkGainFX" },
{ PluginID.AkGuitarDistortion, "AkGuitarDistortionFX" },
{ PluginID.AkHarmonizer, "AkHarmonizerFX" },
{ PluginID.AkMatrixReverb, "AkMatrixReverbFX" },
{ PluginID.AkMeter, "AkMeterFX" },
{ PluginID.AkMultibandMeter, "AkMeterFX" }, // Meter lib contains MultibandMeter
{ PluginID.AkMotionSink, "AkMotionSink" },
{ PluginID.AkMotionSource, "AkMotionSourceSource" },
{ PluginID.AkParametricEQ, "AkParametricEQFX" },
{ PluginID.AkPeakLimiter, "AkPeakLimiterFX" },
{ PluginID.AkPitchShifter, "AkPitchShifterFX" },
{ PluginID.AkRecorder, "AkRecorderFX" },
{ PluginID.AkReflect, "AkReflectFX" },
{ PluginID.AkRoomVerb, "AkRoomVerbFX" },
{ PluginID.AkSoundSeedGrain, "AkSoundSeedGrainSource" },
{ PluginID.AkSoundSeedWind, "AkSoundSeedWindSource" },
{ PluginID.AkSoundSeedWoosh, "AkSoundSeedWooshSource" },
{ PluginID.AkStereoDelay, "AkStereoDelayFX" },
{ PluginID.AkSynthOne, "AkSynthOneSource" },
{ PluginID.AkTimeStretch, "AkTimeStretchFX" },
{ PluginID.AkTremolo, "AkTremoloFX" },
{ PluginID.AuroHeadphone, "AuroHeadphoneFX" },
{ PluginID.CrankcaseAudioREVModelPlayer, "CrankcaseAudioREVModelPlayerSource" },
{ PluginID.iZHybridReverb, "iZHybridReverbFX" },
{ PluginID.iZTrashBoxModeler, "iZTrashBoxModelerFX" },
{ PluginID.iZTrashDelay, "iZTrashDelayFX" },
{ PluginID.iZTrashDistortion, "iZTrashDistortionFX" },
{ PluginID.iZTrashDynamics, "iZTrashDynamicsFX" },
{ PluginID.iZTrashFilters, "iZTrashFiltersFX" },
{ PluginID.iZTrashMultibandDistortion, "iZTrashMultibandDistortionFX" },
{ PluginID.MasteringSuite, "MasteringSuiteFX" },
{ PluginID.AkImpacterSource, "AkImpacterSource" },
{ PluginID.McDSPFutzBox, "McDSPFutzBoxFX" },
{ PluginID.McDSPLimiter, "McDSPLimiterFX" },
{ PluginID.ResonanceAudioRenderer, "ResonanceAudioFX" },
{ PluginID.ResonanceAudioRoomEffect, "ResonanceAudioFX" },
{ PluginID.IgniterLive, "IgniterLiveSource" },
{ PluginID.IgniterLiveSynth, "IgniterLiveSource" }
};
// Support libraries are DLLs that do not have an associated Wwise plug-in ID; they are meant to be loaded manually by the application
internal static readonly System.Collections.Generic.List<string> SupportLibraries =
new System.Collections.Generic.List<string>
{
"AkVorbisHwAccelerator"
};
internal enum PluginID
{
// Built-in plugins
Ak3DAudioBedMixer = 0x00BE0003, // Wwise 3D Audio Bed Mixer
AkCompressor = 0x006C0003, //Wwise Compressor
AkRouterMixer = 0x00AC0006, //Wwise RouterMixer
AkChannelRouter = 0x00BF0003, // Wwise Channel Router
AkDelay = 0x006A0003, //Delay
AkExpander = 0x006D0003, //Wwise Expander
AkGain = 0x008B0003, //Gain
AkMatrixReverb = 0x00730003, //Matrix Reverb
AkMeter = 0x00810003, //Wwise Meter
AkMultibandMeter = 0x00C40003, //Wwise Multiband Meter
AkParametricEQ = 0x00690003, //Wwise Parametric EQ
AkPeakLimiter = 0x006E0003, //Wwise Peak Limiter
AkRoomVerb = 0x00760003, //Wwise RoomVerb
SineGenerator = 0x00640002, //Sine
SinkAuxiliary = 0xB40007,
SinkCommunication = 0xB00007,
SinkControllerHeadphones = 0xB10007,
SinkControllerSpeaker = 0xB30007,
SinkDVRByPass = 0xAF0007,
SinkNoOutput = 0xB50007,
SinkSystem = 0xAE0007,
ToneGenerator = 0x00660002, //Tone Generator
WwiseSilence = 0x00650002, //Wwise Silence
#if !UNITY_2018_3_OR_NEWER
VitaReverb = 0x008C0003, //Vita Reverb
VitaCompressor = 0x008D0003, //Vita Compressor
VitaDelay = 0x008E0003, //Vita Delay
VitaDistortion = 0x008F0003, //Vita Distortion
VitaEQ = 0x00900003, //Vita EQ
#endif
// Static or DLL plugins
AkAudioInput = 0xC80002,
AkConvolutionReverb = 0x7F0003,
AkFlanger = 0x7D0003,
AkGuitarDistortion = 0x7E0003,
AkHarmonizer = 0x8A0003,
AkMotionSink = 0x1FB0007,
AkMotionSource = 0x1990002,
AkPitchShifter = 0x880003,
AkRecorder = 0x840003,
AkReflect = 0xAB0003,
AkSoundSeedGrain = 0xB70002,
AkSoundSeedWind = 0x770002,
AkSoundSeedWoosh = 0x780002,
AkStereoDelay = 0x870003,
AkSynthOne = 0x940002,
AkTimeStretch = 0x820003,
AkTremolo = 0x830003,
AuroHeadphone = 0x44C1073,
CrankcaseAudioREVModelPlayer = 0x1A01052,
iZHybridReverb = 0x21033,
iZTrashBoxModeler = 0x71033,
iZTrashDelay = 0x41033,
iZTrashDistortion = 0x31033,
iZTrashDynamics = 0x51033,
iZTrashFilters = 0x61033,
iZTrashMultibandDistortion = 0x91033,
MasteringSuite = 0xBA0003,
AkImpacterSource = 0xB80002,
McDSPFutzBox = 0x6E1003,
McDSPLimiter = 0x671003,
ResonanceAudioRenderer = 0x641103,
ResonanceAudioRoomEffect = 0xC81106,
IgniterLive = 0x5110D2,
IgniterLiveSynth = 0x5210D2
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cfb04570cf048bb45a9630875dc77f66
@@ -0,0 +1,60 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
public class AkPluginActivatorMenus
{
private const string MENU_PATH = "Assets/Wwise/Activate Plugins/";
[UnityEditor.MenuItem(MENU_PATH + AkPluginActivatorConstants.CONFIG_DEBUG)]
public static void ActivateDebug()
{
ActivateConfig(AkPluginActivatorConstants.CONFIG_DEBUG);
}
[UnityEditor.MenuItem(MENU_PATH + AkPluginActivatorConstants.CONFIG_PROFILE)]
public static void ActivateProfile()
{
ActivateConfig(AkPluginActivatorConstants.CONFIG_PROFILE);
}
[UnityEditor.MenuItem(MENU_PATH + AkPluginActivatorConstants.CONFIG_RELEASE)]
public static void ActivateRelease()
{
ActivateConfig(AkPluginActivatorConstants.CONFIG_RELEASE);
}
public static void CheckMenuItems(string config)
{
UnityEditor.Menu.SetChecked(MENU_PATH + AkPluginActivatorConstants.CONFIG_DEBUG, config == AkPluginActivatorConstants.CONFIG_DEBUG);
UnityEditor.Menu.SetChecked(MENU_PATH + AkPluginActivatorConstants.CONFIG_PROFILE, config == AkPluginActivatorConstants.CONFIG_PROFILE);
UnityEditor.Menu.SetChecked(MENU_PATH + AkPluginActivatorConstants.CONFIG_RELEASE, config == AkPluginActivatorConstants.CONFIG_RELEASE);
}
private static void SetCurrentConfig(string config)
{
var data = AkWwiseProjectInfo.GetData();
data.CurrentPluginConfig = config;
}
private static void ActivateConfig(string config)
{
SetCurrentConfig(config);
AkPluginActivatorMenus.CheckMenuItems(config);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c4a930db9f9a6f04aadd6f4935deb96d
@@ -0,0 +1,35 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
internal class AkPluginInfo
{
public uint PluginID;
public string DllName;
public string StaticLibName;
public override int GetHashCode()
{
return PluginID.GetHashCode();
}
public override bool Equals(object obj)
{
return PluginID.Equals(obj);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8f2a22fee1f1c5a46a423275042bd02e
@@ -0,0 +1,196 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using System.IO;
using AK.Wwise.Unity.Logging;
internal class StaticPluginRegistration
{
private readonly System.Collections.Generic.HashSet<string> FactoriesHeaderFilenames =
new System.Collections.Generic.HashSet<string>();
private readonly UnityEditor.BuildTarget Target;
public static void Setup(UnityEditor.BuildTarget target, AkPlatformPluginActivator platformPluginActivator)
{
if (!platformPluginActivator.RequiresStaticPluginRegistration)
return;
string deploymentTargetName = platformPluginActivator.WwisePlatformName;
var staticPluginRegistration = new StaticPluginRegistration(target);
var importers = AkPluginActivator.GetWwisePluginImporters(platformPluginActivator.PluginDirectoryName);
foreach (var pluginImporter in importers)
{
var pluginInfo = platformPluginActivator.GetPluginImporterInformation(pluginImporter);
var pluginPlatform = AkPluginActivator.GetPluginInfoPlatform(pluginImporter.assetPath);
if (pluginPlatform != platformPluginActivator.PluginDirectoryName)
continue;
if (platformPluginActivator.Architectures != null && platformPluginActivator.Architectures.Count != 0)
{
if (!platformPluginActivator.Architectures.Contains(pluginInfo.PluginArch))
{
WwiseLogger.Log("Architecture not found: " + pluginInfo.PluginArch);
continue;
}
}
if (pluginInfo.PluginConfig != "DSP")
continue;
if (!AkPlatformPluginList.IsPluginUsed(platformPluginActivator, pluginPlatform, Path.GetFileNameWithoutExtension(pluginImporter.assetPath)))
continue;
staticPluginRegistration.TryAddLibrary(platformPluginActivator, pluginImporter.assetPath);
}
System.Collections.Generic.HashSet<AkPluginInfo> plugins;
AkPlatformPluginList.GetPluginsUsedForPlatform(deploymentTargetName, out plugins);
var missingPlugins = staticPluginRegistration.GetMissingPlugins(plugins);
if (missingPlugins.Count == 0)
{
if (plugins == null)
WwiseLogger.WarningFormat("The activated Wwise plug-ins may not be correct. Could not read PluginInfo.xml for platform: {0}", deploymentTargetName);
staticPluginRegistration.TryWriteToFile(platformPluginActivator);
}
else
{
WwiseLogger.ErrorFormat(
"These plugins used by the Wwise project are missing from the Unity project: {0}. Please check folder Assets/Wwise/API/Runtime/Plugin/{1}.",
string.Join(", ", missingPlugins.ToArray()), deploymentTargetName);
}
}
private StaticPluginRegistration(UnityEditor.BuildTarget target)
{
Target = target;
}
private void TryAddLibrary(AkPlatformPluginActivator config, string AssetPath)
{
if (AssetPath.EndsWith(".a"))
{
//Extract the lib name, generate the registration code.
var begin = AssetPath.LastIndexOf('/') + 4;
var end = AssetPath.LastIndexOf('.') - begin;
var LibName = AssetPath.Substring(begin, end); //Remove the lib prefix and the .a extension
if (!LibName.Contains("AkUnitySoundEngine"))
{
string headerFilename = LibName + "Factory.h";
string fullPath = Path.GetFullPath(AkUtilities.GetPathInPackage(Path.Combine(AkPluginActivatorConstants.WwisePluginFolder, config.DSPDirectoryPath, headerFilename)));
if (File.Exists(fullPath))
{
FactoriesHeaderFilenames.Add(headerFilename);
}
else
{
WwiseLogger.ErrorFormat("Could not find '{0}', required for building plugin.", fullPath);
}
}
}
else if (AssetPath.EndsWith("Factory.h"))
{
FactoriesHeaderFilenames.Add(Path.GetFileName(AssetPath));
}
}
private void TryWriteToFile(AkPlatformPluginActivator config)
{
System.Text.StringBuilder CppText = new System.Text.StringBuilder(2000);
string RelativePath = Path.Combine(config.DSPDirectoryPath, config.StaticPluginRegistrationName + ".cpp");
CppText.AppendLine("#define " + config.StaticPluginDefine);
// The purpose of this cpp file is to force the linker to recognize the usage of AK::PluginRegistration global objects
// so that the static constructors for these objects are executed when the binary is being loaded in.
// However, some platforms (e.g. WebGL) have a really aggressive LTO (link-time optimization) pass that will strip these
// symbols even when they are defined as extern here.
// To avoid any stripping, we call from C# a native function (AkVerifyPluginRegistration)
// that looks at these symbols, forcing the linker to recognize that these symbols are required for proper program execution.
CppText.AppendLine(@"namespace AK { class PluginRegistration; };");
CppText.AppendLine(@"class AkUnityStaticPlugin;");
CppText.AppendLine(@"AkUnityStaticPlugin * g_pAkUnityStaticPluginList = nullptr;");
CppText.AppendLine(@"class AkUnityStaticPlugin {");
CppText.AppendLine("\tpublic:");
CppText.AppendLine("\tAkUnityStaticPlugin(AK::PluginRegistration* pReg) : m_pNext(g_pAkUnityStaticPluginList), m_pReg(pReg) { g_pAkUnityStaticPluginList = this; }");
CppText.AppendLine("\tAkUnityStaticPlugin *m_pNext;");
CppText.AppendLine("\tAK::PluginRegistration * m_pReg;");
CppText.AppendLine(@"};");
CppText.AppendLine(@"#define AK_STATIC_LINK_PLUGIN(_pluginName_) \");
CppText.AppendLine(@"extern AK::PluginRegistration _pluginName_##Registration; \");
CppText.AppendLine(@"AkUnityStaticPlugin _pluginName_##UnityStaticPlugin(&_pluginName_##Registration);");
foreach (var filename in FactoriesHeaderFilenames)
{
CppText.AppendLine("#include \"" + filename + "\"");
}
CppText.AppendLine("extern \"C\" {");
CppText.AppendLine("\t__attribute__ ((visibility(\"default\"))) bool AkVerifyPluginRegistration() {");
CppText.AppendLine("\t\tbool bReg = true;");
CppText.AppendLine("\t\tAkUnityStaticPlugin * pNext = g_pAkUnityStaticPluginList;");
CppText.AppendLine("\t\twhile (pNext != nullptr) { bReg = bReg && pNext->m_pReg != nullptr; pNext = pNext->m_pNext; }");
CppText.AppendLine("\t\treturn bReg;");
CppText.AppendLine("\t}");
CppText.AppendLine("}");
try
{
var FullPath = Path.GetFullPath(AkUtilities.GetPathInPackage(Path.Combine(AkPluginActivatorConstants.WwisePluginFolder, RelativePath)));
File.WriteAllText(FullPath, CppText.ToString());
}
catch (System.Exception e)
{
WwiseLogger.Error("Could not write <" + RelativePath + ">. Exception: " + e.Message);
return;
}
UnityEditor.AssetDatabase.Refresh();
}
private System.Collections.Generic.List<string> GetMissingPlugins(System.Collections.Generic.HashSet<AkPluginInfo> usedPlugins)
{
var pluginList = new System.Collections.Generic.List<string>();
if (usedPlugins == null)
return pluginList;
foreach (var plugin in usedPlugins)
{
if (string.IsNullOrEmpty(plugin.StaticLibName))
{
continue;
}
string includeFilename = plugin.StaticLibName + "Factory.h";
if (!FactoriesHeaderFilenames.Contains(includeFilename))
{
pluginList.Add(plugin.StaticLibName);
}
}
return pluginList;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 40533e511c51acb4f9b7fe6d47b7855a
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 794f0925934d2a84ba8cca191ac7d3f2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,58 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using UnityEditor;
[UnityEditor.InitializeOnLoad]
public class AkMacPluginActivator : AkPlatformPluginActivator
{
public override string WwisePlatformName => "Mac";
public override string PluginDirectoryName => "Mac";
static AkMacPluginActivator()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
AkPluginActivator.RegisterPlatformPluginActivator(BuildTarget.StandaloneOSX, new AkMacPluginActivator());
}
private const int CONFIG_INDEX = 1;
public override AkPluginActivator.PluginImporterInformation GetPluginImporterInformation(PluginImporter pluginImporter)
{
return new AkPluginActivator.PluginImporterInformation
{
PluginConfig = GetPluginPathParts(pluginImporter.assetPath)[CONFIG_INDEX],
EditorOS = "OSX",
EditorCPU = "AnyCPU"
};
}
internal override bool ConfigurePlugin(PluginImporter pluginImporter, AkPluginActivator.PluginImporterInformation pluginImporterInformation)
{
pluginImporter.SetPlatformData(BuildTarget.StandaloneLinux64, "CPU", "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneWindows, "CPU", "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneWindows64, "CPU", "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneOSX, "CPU", "AnyCPU");
return true;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f0078b6cee531cf47a76bf7978500f51
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 15549a8355d379843aa7ee8792e7d5e2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
using UnityEditor;
using AK.Wwise.Unity.Logging;
[UnityEditor.InitializeOnLoad]
public class AkWindowsPluginActivator : AkPlatformPluginActivator
{
public override string WwisePlatformName => "Windows";
public override string PluginDirectoryName => "Windows";
static AkWindowsPluginActivator()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
AkPluginActivator.RegisterPlatformPluginActivator(BuildTarget.StandaloneWindows, new AkWindowsPluginActivator());
AkPluginActivator.RegisterPlatformPluginActivator(BuildTarget.StandaloneWindows64, new AkWindowsPluginActivator());
}
private const int ARCH_INDEX = 1;
private const int CONFIG_INDEX = 2;
private const int EDITOR_CPU_INDEX = 1;
public override AkPluginActivator.PluginImporterInformation GetPluginImporterInformation(PluginImporter pluginImporter)
{
var parts = GetPluginPathParts(pluginImporter.assetPath);
return new AkPluginActivator.PluginImporterInformation
{
PluginConfig = parts[CONFIG_INDEX],
PluginArch = parts[ARCH_INDEX],
EditorOS = "Windows",
EditorCPU = parts[EDITOR_CPU_INDEX]
};
}
internal override bool ConfigurePlugin(PluginImporter pluginImporter, AkPluginActivator.PluginImporterInformation pluginImporterInformation)
{
if (pluginImporterInformation.PluginArch != "x86" && pluginImporterInformation.PluginArch != "x86_64")
{
WwiseLogger.Log("Architecture not found: " + pluginImporterInformation.PluginArch);
return false;
}
pluginImporter.SetPlatformData(BuildTarget.StandaloneLinux64, "CPU", "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneWindows, "CPU", pluginImporterInformation.IsX86 ? "AnyCPU" : "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneWindows64, "CPU", pluginImporterInformation.IsX64 ? "AnyCPU" : "None");
pluginImporter.SetPlatformData(BuildTarget.StandaloneOSX, "CPU", "None");
return true;
}
public override void FilterOutPlatformIfNeeded(BuildTarget target, PluginImporter pluginImporter,
string pluginPlatform)
{
pluginImporter.SetCompatibleWithPlatform(target, false);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d07a21f4872187e4ca59da771dc15ca8
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b5ab8476d2586b4aab61c7304cf1f53
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cdc4ae63f9b977e4bb3e612dd6ce3059
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,147 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
public class AkUnityIntegrationBuilderBase
{
private readonly string m_progTitle = "Rebuilding Unity Integration Progress";
protected string m_assetsDir = "Undefined";
protected string m_assetsPluginsDir = "Undefined";
protected string m_buildScriptDir = "Undefined";
protected string m_buildScriptFile = "Undefined";
protected string m_platform = "Undefined";
protected string m_shell = "python";
protected string m_wwiseSdkDir = "";
public AkUnityIntegrationBuilderBase()
{
var unityProjectRoot = System.IO.Directory.GetCurrentDirectory();
m_assetsDir = System.IO.Path.Combine(unityProjectRoot, "Assets");
m_assetsPluginsDir = System.IO.Path.Combine(m_assetsDir, "Plugins");
m_buildScriptDir =
System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(m_assetsDir, "Wwise"), "AkUnitySoundEngine"),
"Common");
m_buildScriptFile = "BuildWwiseUnityIntegration.py";
}
public void BuildByConfig(string config, string arch)
{
if (UnityEditor.EditorApplication.isPlaying)
{
WwiseLogger.Warning("Editor is in play mode. Stop playing any scenes and retry. Aborted.");
return;
}
// Try to parse config to get Wwise location.
var configPath = System.IO.Path.Combine(m_buildScriptDir, "BuildWwiseUnityIntegration.json");
var fi = new System.IO.FileInfo(configPath);
if (fi.Exists)
{
var msg = string.Format("Found preference file: {0}. Use build variables defined in it.", configPath);
WwiseLogger.Log(msg);
}
else
{
var msg = string.Format("Preference file: {0} is unavailable. Need user input.", configPath);
WwiseLogger.Log(msg);
m_wwiseSdkDir = UnityEditor.EditorUtility.OpenFolderPanel("Choose Wwise SDK folder", ".", "");
var isUserCancelledBuild = m_wwiseSdkDir == "";
if (isUserCancelledBuild)
{
WwiseLogger.Log("User cancelled the build.");
return;
}
}
if (!PreBuild())
return;
// On Windows, separate shell console window will open. When building is done, close the Window yourself if it stays active. Usually at the end you will see the last line says "Build succeeded" or "Build failed".
var progMsg = string.Format("Rebuilding Wwise Unity Integration for {0} ({1}) ...", m_platform, config);
WwiseLogger.Log(progMsg);
var start = new System.Diagnostics.ProcessStartInfo();
start.FileName = m_shell;
start.Arguments = GetProcessArgs(config, arch);
if (start.Arguments == "")
return;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 0.5f);
using (var process = System.Diagnostics.Process.Start(start))
{
using (var reader = process.StandardOutput)
{
process.WaitForExit();
try
{
//ExitCode throws InvalidOperationException if the process is hanging
var isBuildSucceeded = process.ExitCode == 0;
if (isBuildSucceeded)
{
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 1.0f);
WwiseLogger.Log("Build succeeded. Check detailed logs under the Logs folder.");
}
else
WwiseLogger.Error("Build failed. Check detailed logs under the Logs folder.");
UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorUtility.ClearProgressBar();
}
catch (System.Exception ex)
{
UnityEditor.AssetDatabase.Refresh();
WwiseLogger.Error(string.Format(
"Build process failed with exception: {}. Check detailed logs under the Logs folder.", ex));
UnityEditor.EditorUtility.ClearProgressBar();
}
}
}
}
protected virtual string GetProcessArgs(string config, string arch)
{
var scriptPath = System.IO.Path.Combine(m_buildScriptDir, m_buildScriptFile);
var args = string.Format("\"{0}\" -p {1} -c {2}", scriptPath, m_platform, config);
if (arch != null)
args += string.Format(" -a {0}", arch);
if (m_wwiseSdkDir != "")
args += string.Format(" -w \"{0}\" -u", m_wwiseSdkDir);
return args;
}
protected virtual bool PreBuild()
{
return true;
}
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b72e52440a9c479499e9c2ad00c5b5d7
@@ -0,0 +1,404 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
public class AkUnityAssetsInstaller
{
public string[] m_arches = { };
protected string m_assetsDir = UnityEngine.Application.dataPath;
protected System.Collections.Generic.List<string> m_excludes = new System.Collections.Generic.List<string> { ".meta" };
protected string m_platform = "Undefined";
protected string m_pluginDir = System.IO.Path.Combine(UnityEngine.Application.dataPath, "Plugins");
// Copy file to destination directory and create the directory when none exists.
public static bool CopyFileToDirectory(string srcFilePath, string destDir)
{
var fi = new System.IO.FileInfo(srcFilePath);
if (!fi.Exists)
{
WwiseLogger.Error(string.Format("Failed to copy. Source is missing: {0}.", srcFilePath));
return false;
}
var di = new System.IO.DirectoryInfo(destDir);
if (!di.Exists)
di.Create();
const bool IsToOverwrite = true;
try
{
fi.CopyTo(System.IO.Path.Combine(di.FullName, fi.Name), IsToOverwrite);
}
catch (System.Exception ex)
{
WwiseLogger.Error(string.Format("Error during installation: {0}.", ex.Message));
return false;
}
return true;
}
// Copy or overwrite destination file with source file.
public static bool OverwriteFile(string srcFilePath, string destFilePath)
{
var fi = new System.IO.FileInfo(srcFilePath);
if (!fi.Exists)
{
WwiseLogger.Error(string.Format("Failed to overwrite. Source is missing: {0}.", srcFilePath));
return false;
}
var di = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(destFilePath));
if (!di.Exists)
di.Create();
const bool IsToOverwrite = true;
try
{
fi.CopyTo(destFilePath, IsToOverwrite);
}
catch (System.Exception ex)
{
WwiseLogger.Error(string.Format("Error during installation: {0}.", ex.Message));
return false;
}
return true;
}
// Move file to destination directory and create the directory when none exists.
public static void MoveFileToDirectory(string srcFilePath, string destDir)
{
var fi = new System.IO.FileInfo(srcFilePath);
if (!fi.Exists)
{
WwiseLogger.Error(string.Format("Failed to move. Source is missing: {0}.", srcFilePath));
return;
}
var di = new System.IO.DirectoryInfo(destDir);
if (!di.Exists)
di.Create();
var destFilePath = System.IO.Path.Combine(di.FullName, fi.Name);
try
{
fi.MoveTo(destFilePath);
}
catch (System.Exception ex)
{
WwiseLogger.Error(string.Format("Error during installation: {0}.", ex.Message));
}
}
// Recursively copy a directory to its destination.
public static bool RecursiveCopyDirectory(System.IO.DirectoryInfo srcDir, System.IO.DirectoryInfo destDir,
System.Collections.Generic.List<string> excludeExtensions = null)
{
if (!srcDir.Exists)
{
WwiseLogger.Error(string.Format("Failed to copy. Source is missing: {0}.", srcDir));
return false;
}
if (!destDir.Exists)
destDir.Create();
// Copy all files.
var files = srcDir.GetFiles();
foreach (var file in files)
{
if (excludeExtensions != null)
{
var fileExt = System.IO.Path.GetExtension(file.Name);
var isFileExcluded = false;
foreach (var ext in excludeExtensions)
{
if (fileExt.ToLower() == ext)
{
isFileExcluded = true;
break;
}
}
if (isFileExcluded)
continue;
}
const bool IsToOverwrite = true;
try
{
file.CopyTo(System.IO.Path.Combine(destDir.FullName, file.Name), IsToOverwrite);
}
catch (System.Exception ex)
{
WwiseLogger.Error(string.Format("Error during installation: {0}.", ex.Message));
return false;
}
}
// Process subdirectories.
var dirs = srcDir.GetDirectories();
foreach (var dir in dirs)
{
// Get destination directory.
var destFullPath = System.IO.Path.Combine(destDir.FullName, dir.Name);
// Recurse
var isSuccess = RecursiveCopyDirectory(dir, new System.IO.DirectoryInfo(destFullPath), excludeExtensions);
if (!isSuccess)
return false;
}
return true;
}
}
public class AkUnityPluginInstallerBase : AkUnityAssetsInstaller
{
private readonly string m_progTitle = "Plugin Installation Progress";
public bool InstallPluginByConfig(string config)
{
var pluginSrc = GetPluginSrcPathByConfig(config);
var pluginDest = GetPluginDestPath("");
var progMsg = string.Format("Installing plugin for {0} ({1}) from {2} to {3}.", m_platform, config, pluginSrc,
pluginDest);
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 0.5f);
var isSuccess = RecursiveCopyDirectory(new System.IO.DirectoryInfo(pluginSrc),
new System.IO.DirectoryInfo(pluginDest), m_excludes);
if (!isSuccess)
{
WwiseLogger.Error(string.Format("Failed to install plugin for {0} ({1}) from {2} to {3}.",
m_platform, config, pluginSrc, pluginDest));
UnityEditor.EditorUtility.ClearProgressBar();
return false;
}
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 1.0f);
UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorUtility.ClearProgressBar();
WwiseLogger.Log(string.Format("Plugin for {0} {1} installed from {2} to {3}.", m_platform, config,
pluginSrc, pluginDest));
return true;
}
public virtual bool InstallPluginByArchConfig(string arch, string config)
{
var pluginSrc = GetPluginSrcPathByArchConfig(arch, config);
var pluginDest = GetPluginDestPath(arch);
var progMsg = string.Format("Installing plugin for {0} ({1}, {2}) from {3} to {4}.", m_platform, arch, config,
pluginSrc, pluginDest);
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 0.5f);
var isSuccess = RecursiveCopyDirectory(new System.IO.DirectoryInfo(pluginSrc),
new System.IO.DirectoryInfo(pluginDest), m_excludes);
if (!isSuccess)
{
WwiseLogger.Error(string.Format("Failed to install plugin for {0} ({1}, {2}) from {3} to {4}.",
m_platform, arch, config, pluginSrc, pluginDest));
UnityEditor.EditorUtility.ClearProgressBar();
return false;
}
UnityEditor.EditorUtility.DisplayProgressBar(m_progTitle, progMsg, 1.0f);
UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorUtility.ClearProgressBar();
WwiseLogger.Log(string.Format("Plugin for {0} {1} {2} installed from {3} to {4}.", m_platform, arch,
config, pluginSrc, pluginDest));
return true;
}
protected string GetPluginSrcPathByConfig(string config)
{
return System.IO.Path.Combine(
System.IO.Path.Combine(
System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(m_assetsDir, "Wwise"), "API", "Runtime"),
"Plugins"), m_platform), config);
}
protected string GetPluginSrcPathByArchConfig(string arch, string config)
{
return System.IO.Path.Combine(
System.IO.Path.Combine(
System.IO.Path.Combine(
System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(m_assetsDir, "Wwise"), "API", "Runtime"),
"Plugins"), m_platform), arch), config);
}
protected virtual string GetPluginDestPath(string arch)
{
return m_pluginDir;
}
}
public class AkUnityPluginInstallerMultiArchBase : AkUnityPluginInstallerBase
{
protected override string GetPluginDestPath(string arch)
{
return System.IO.Path.Combine(System.IO.Path.Combine(m_pluginDir, m_platform), arch);
}
}
public class AkDocHelper
{
private static string m_WwiseVersionString = string.Empty;
public static void OpenDoc(string platform)
{
if (m_WwiseVersionString == string.Empty)
{
var temp = AkUnitySoundEngine.GetMajorMinorVersion();
var temp2 = AkUnitySoundEngine.GetSubminorBuildVersion();
m_WwiseVersionString = (temp >> 16) + "." + (temp & 0xFFFF);
if (temp2 >> 16 != 0)
m_WwiseVersionString += "." + (temp2 >> 16);
m_WwiseVersionString += "_" + (temp2 & 0xFFFF);
}
var docUrl = "http://www.audiokinetic.com/library/" + m_WwiseVersionString + "/?source=Unity&id=index.html";
var isConnected = false;
try
{
var request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://www.audiokinetic.com/robots.txt");
request.Timeout = 1000;
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
var response = (System.Net.HttpWebResponse) request.GetResponse();
isConnected = response.StatusCode == System.Net.HttpStatusCode.OK;
}
catch (System.Exception)
{
isConnected = false;
}
if (!isConnected)
{
// Can't access audiokinetic.com, open local doc.
docUrl = GetLocalDocUrl(platform);
if (string.IsNullOrEmpty(docUrl))
return;
}
UnityEngine.Application.OpenURL(docUrl);
}
private static string GetLocalDocUrl(string platform)
{
var docUrl = string.Empty;
var docPath = string.Empty;
var dataPath = UnityEngine.Application.dataPath;
#if UNITY_EDITOR_WIN
var format = (platform == "Windows")
? "{0}/Wwise/Documentation/{1}/en/WwiseUnityIntegrationHelp_en.chm"
: "{0}/Wwise/Documentation/{1}/en/WwiseUnityIntegrationHelp_{1}_en.chm";
docPath = string.Format(format, dataPath, platform);
#else
string DestPath = AkUtilities.GetFullPath(dataPath, "../WwiseUnityIntegrationHelp_en");
docPath = string.Format ("{0}/html/index.html", DestPath);
if (!System.IO.File.Exists(docPath))
UnzipHelp(DestPath);
if (!System.IO.File.Exists(docPath))
{
WwiseLogger.Log("Unable to show documentation. Please unzip WwiseUnityIntegrationHelp_AppleCommon_en.zip manually.");
return string.Empty;
}
#endif
var fi = new System.IO.FileInfo(docPath);
if (!fi.Exists)
{
WwiseLogger.Error(string.Format("Failed to find documentation: {0}. Aborted.", docPath));
return string.Empty;
}
docUrl = string.Format("file:///{0}", docPath.Replace(" ", "%20"));
return docUrl;
}
public static void UnzipHelp(string DestPath)
{
// Start by extracting the zip, if it exists
var ZipPath = System.IO.Path.Combine(
System.IO.Path.Combine(
System.IO.Path.Combine(
System.IO.Path.Combine(System.IO.Path.Combine(UnityEngine.Application.dataPath, "Wwise"), "Documentation"),
"AppleCommon"), "en"), "WwiseUnityIntegrationHelp_en.zip");
if (System.IO.File.Exists(ZipPath))
{
var start = new System.Diagnostics.ProcessStartInfo();
start.FileName = "unzip";
start.Arguments = "\"" + ZipPath + "\" -d \"" + DestPath + "\"";
start.UseShellExecute = true;
start.RedirectStandardOutput = false;
var progMsg = "Unzipping documentation...";
var progTitle = "Unzipping Wwise documentation";
UnityEditor.EditorUtility.DisplayProgressBar(progTitle, progMsg, 0.5f);
using (var process = System.Diagnostics.Process.Start(start))
{
while (!process.WaitForExit(1000))
System.Threading.Thread.Sleep(100);
try
{
//ExitCode throws InvalidOperationException if the process is hanging
var returnCode = process.ExitCode;
var isBuildSucceeded = returnCode == 0;
if (isBuildSucceeded)
{
UnityEditor.EditorUtility.DisplayProgressBar(progTitle, progMsg, 1.0f);
WwiseLogger.Log("Documentation extraction succeeded. ");
}
else
WwiseLogger.Error("Extraction failed.");
UnityEditor.EditorUtility.ClearProgressBar();
}
catch (System.Exception ex)
{
UnityEditor.EditorUtility.ClearProgressBar();
WwiseLogger.Error(ex.ToString());
UnityEditor.EditorUtility.ClearProgressBar();
}
}
}
}
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 96e7d02a32d0293408ecd5b7422f985c
@@ -0,0 +1,82 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
internal static class AkWwiseIDConverter
{
private static readonly string s_bankDir = UnityEngine.Application.dataPath;
private static readonly string s_converterScript = System.IO.Path.Combine(
System.IO.Path.Combine(System.IO.Path.Combine(UnityEngine.Application.dataPath, "Wwise"), "Tools"),
"WwiseIDConverter.py");
private static readonly string s_progTitle = "Converting SoundBank IDs";
[UnityEditor.MenuItem("Assets/Wwise/Convert Wwise SoundBank IDs", false, (int) AkWwiseMenuOrder.ConvertIDs)]
public static void ConvertWwiseSoundBankIDs()
{
var bankIdHeaderPath =
UnityEditor.EditorUtility.OpenFilePanel("Choose Wwise SoundBank ID C++ header", s_bankDir, "h");
if (string.IsNullOrEmpty(bankIdHeaderPath))
{
WwiseLogger.Log("User canceled the action.");
return;
}
var start = new System.Diagnostics.ProcessStartInfo();
start.FileName = "python";
start.Arguments = string.Format("\"{0}\" \"{1}\"", s_converterScript, bankIdHeaderPath);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
var progMsg = "Converting C++ SoundBank IDs into C# ...";
UnityEditor.EditorUtility.DisplayProgressBar(s_progTitle, progMsg, 0.5f);
using (var process = System.Diagnostics.Process.Start(start))
{
process.WaitForExit();
try
{
//ExitCode throws InvalidOperationException if the process is hanging
if (process.ExitCode == 0)
{
UnityEditor.EditorUtility.DisplayProgressBar(s_progTitle, progMsg, 1.0f);
WwiseLogger.Log(string.Format(
"SoundBank ID conversion succeeded. Find generated Unity script under {0}.", s_bankDir));
}
else
WwiseLogger.Error("Conversion failed.");
UnityEditor.AssetDatabase.Refresh();
}
catch (System.Exception ex)
{
UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorUtility.ClearProgressBar();
WwiseLogger.Error(string.Format(
"SoundBank ID conversion process failed with exception: {}. Check detailed logs under the folder: Assets/Wwise/Logs.",
ex));
}
UnityEditor.EditorUtility.ClearProgressBar();
}
}
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3207b7fb81f2c374ab51cdcef9e39171
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 36ce7f91732abfe4f946f26cf83019c3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
public class AkWwiseMenu_Mac
{
private const string MENU_PATH = "Help/Wwise Help/";
private const string Platform = "Mac";
[UnityEditor.MenuItem(MENU_PATH + Platform, false, (int) AkWwiseHelpOrder.WwiseHelpOrder)]
public static void OpenDoc()
{
AkDocHelper.OpenDoc(Platform);
}
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c6a28cb1bccd6b343a4dc8b2609c148b
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 64c517c792b2d084a8ba9d448c83da49
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_EDITOR
public class AkWwiseMenu_Windows
{
private const string MENU_PATH = "Help/Wwise Help/";
private const string Platform = "Windows";
[UnityEditor.MenuItem(MENU_PATH + Platform, false, (int) AkWwiseHelpOrder.WwiseHelpOrder)]
public static void OpenDoc()
{
AkDocHelper.OpenDoc(Platform);
}
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 30d28f9d707b0004880ee69f3e2c67a4
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 384ef023d7859de49873bebc3903fcea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,31 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(AcousticTexture))]
public class AcousticTextureDrawer : BaseTypeDrawer
{
protected override string GetComponentName(UnityEditor.SerializedProperty wwiseObjectReference)
{
var componentName = base.GetComponentName(wwiseObjectReference);
return string.IsNullOrEmpty(componentName) ? "None" : componentName;
}
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.AcousticTexture; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e2c9aae5ed5f601459ad7cc770a18c66
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(AuxBus))]
public class AuxBusDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.AuxBus; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d15b4d1370bf50c42be4e67a9ac98e70
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(Bank))]
public class BankDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.Soundbank; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 11dd3d54cd3509d47b1e5a7bd44befd0
@@ -0,0 +1,133 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
public abstract class BaseTypeDrawer : UnityEditor.PropertyDrawer
{
public override void OnGUI(UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label)
{
// Get unique control Id
int controlId = UnityEngine.GUIUtility.GetControlID(label, UnityEngine.FocusType.Passive);
UnityEditor.EditorGUI.BeginProperty(position, label, property);
var wwiseObjectReference = property.FindPropertyRelative("WwiseObjectReference");
HandleDragAndDrop(wwiseObjectReference, position);
position = UnityEditor.EditorGUI.PrefixLabel(position, controlId, label);
var style = new UnityEngine.GUIStyle(UnityEngine.GUI.skin.button);
style.alignment = UnityEngine.TextAnchor.MiddleLeft;
style.fontStyle = UnityEngine.FontStyle.Normal;
var componentName = GetComponentName(wwiseObjectReference);
if (string.IsNullOrEmpty(componentName))
{
componentName = "No " + WwiseObjectType + " is currently selected";
style.normal.textColor = UnityEngine.Color.red;
}
if (UnityEngine.GUI.Button(position, componentName, style))
{
new AkWwiseComponentPicker.PickerCreator
{
objectType = WwiseObjectType,
wwiseObjectReference = wwiseObjectReference,
serializedObject = property.serializedObject,
//Current selected object
currentWwiseObjectReference = GetWwiseObjectReference(wwiseObjectReference),
//We're currently clicking focus windows must be the right
pickedSourceEditorWindow = UnityEditor.EditorWindow.focusedWindow,
//Useful to control event source
pickedSourceControlId = controlId,
pickerPosition = UnityEditor.EditorGUIUtility.GUIToScreenRect(position),
};
}
// Check picker window close event and we're in the right drawer instance using control ID
if (UnityEngine.Event.current.commandName == AkWwiseComponentPicker.PickerClosedEventName &&
controlId == AkWwiseComponentPicker.GetObjectPickerControlID())
{
var oldValue = GetWwiseObjectReference(wwiseObjectReference);
var newValue = AkWwiseComponentPicker.GetObjectPickerObjectReference();
if (oldValue != newValue)
{
// Serialized object updating
wwiseObjectReference.serializedObject.Update();
SetSerializedObject(wwiseObjectReference, newValue);
wwiseObjectReference.serializedObject.ApplyModifiedProperties();
// Force GUI modification, to send back to the base component drawer
UnityEngine.GUI.changed = true;
}
}
UnityEditor.EditorGUI.EndProperty();
}
protected abstract WwiseObjectType WwiseObjectType { get; }
protected virtual string GetComponentName(UnityEditor.SerializedProperty wwiseObjectReference)
{
var reference = wwiseObjectReference.objectReferenceValue as WwiseObjectReference;
return reference ? reference.DisplayName : string.Empty;
}
// These are to be able use other type instead of WwiseObjectReference
protected virtual WwiseObjectReference GetWwiseObjectReference(UnityEditor.SerializedProperty serializedProperty)
{
return serializedProperty.objectReferenceValue as WwiseObjectReference;
}
protected virtual void SetSerializedObject(UnityEditor.SerializedProperty serializedProperty, WwiseObjectReference wwiseObjectReference)
{
serializedProperty.objectReferenceValue = wwiseObjectReference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
private void HandleDragAndDrop(UnityEditor.SerializedProperty wwiseObjectReference, UnityEngine.Rect dropArea)
{
var currentEvent = UnityEngine.Event.current;
if (!dropArea.Contains(currentEvent.mousePosition))
return;
if (currentEvent.type != UnityEngine.EventType.DragUpdated && currentEvent.type != UnityEngine.EventType.DragPerform)
return;
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference != null && reference.WwiseObjectType != WwiseObjectType)
reference = null;
UnityEditor.DragAndDrop.visualMode = reference != null ? UnityEditor.DragAndDropVisualMode.Link : UnityEditor.DragAndDropVisualMode.Rejected;
if (currentEvent.type == UnityEngine.EventType.DragPerform)
{
UnityEditor.DragAndDrop.AcceptDrag();
if (reference != null)
{
SetSerializedObject(wwiseObjectReference, reference);
}
UnityEngine.GUIUtility.hotControl = 0;
}
currentEvent.Use();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d24896c32f827364abbbddbe1328e15c
@@ -0,0 +1,73 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using UnityEditor;
using UnityEngine;
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(Event))]
public class EventDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.Event; } }
public override void OnGUI(UnityEngine.Rect position, UnityEditor.SerializedProperty property,
UnityEngine.GUIContent label)
{
position.height = UnityEditor.EditorGUI.GetPropertyHeight(property, label, true);
base.OnGUI(position, property, label);
position.y += UnityEditor.EditorGUIUtility.standardVerticalSpacing + position.height;
var wwiseObjectReferenceProperty = property.FindPropertyRelative("WwiseObjectReference");
var wwiseProjectFullPath = AkWwiseEditorSettings.WwiseProjectAbsolutePath;
if (wwiseObjectReferenceProperty.objectReferenceValue)
{
var assetObject = new UnityEditor.SerializedObject(wwiseObjectReferenceProperty.objectReferenceValue);
var userBankProperty = assetObject.FindProperty("IsInUserDefinedSoundBank");
if (userBankProperty != null)
{
bool shouldGreyOut = !AkUtilities.IsAutoBankEnabled();
EditorGUI.BeginDisabledGroup(shouldGreyOut);
UnityEditor.EditorGUI.PropertyField(position, userBankProperty, new GUIContent("Is In User-Defined SoundBank:"));
EditorGUI.EndDisabledGroup();
assetObject.ApplyModifiedProperties();
}
}
}
public override float GetPropertyHeight(UnityEditor.SerializedProperty property, UnityEngine.GUIContent label)
{
float totalHeight = UnityEditor.EditorGUI.GetPropertyHeight(property, label, true) + UnityEditor.EditorGUIUtility.standardVerticalSpacing;
var wwiseObjectReferenceProperty = property.FindPropertyRelative("WwiseObjectReference");
if (wwiseObjectReferenceProperty.objectReferenceValue)
{
var assetObject = new UnityEditor.SerializedObject(wwiseObjectReferenceProperty.objectReferenceValue);
var userBankProperty = assetObject.FindProperty("IsInUserDefinedSoundBank");
if (userBankProperty != null)
{
totalHeight += UnityEditor.EditorGUI.GetPropertyHeight(userBankProperty) +
UnityEditor.EditorGUIUtility.standardVerticalSpacing;
}
}
return totalHeight;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 261069da404ca8049a388c19e437da7e
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(RTPC))]
public class RTPCDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.GameParameter; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 000dee8b690a6a04785cdb02b02d67d2
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(State))]
public class StateDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.State; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9591ebfbe6a92254fad679203fd6b898
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(Switch))]
public class SwitchDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.Switch; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4cf965fcdd45d3b4ea523e83c26beae9
@@ -0,0 +1,25 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
namespace AK.Wwise.Editor
{
[UnityEditor.CustomPropertyDrawer(typeof(Trigger))]
public class TriggerDrawer : BaseTypeDrawer
{
protected override WwiseObjectType WwiseObjectType { get { return WwiseObjectType.Trigger; } }
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 642fad177d62881448044f6dd73bf118
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62be49cb249a4ae43a0a805ff5f0d0d7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,470 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System;
using UnityEditor;
using UnityEngine;
using AK.Wwise.Unity.Logging;
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;
#else
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState;
#endif
#if UNITY_EDITOR
public class AkWwiseBrowser : UnityEditor.EditorWindow
{
[UnityEngine.SerializeField] WwiseTreeViewState m_treeViewState;
public static AkWwiseTreeView m_treeView;
UnityEditor.IMGUI.Controls.SearchField m_SearchField;
private Rect m_filterMenuRect;
private static bool s_canRefresh = true;
private static bool s_controlKeyDown = false;
private static bool s_altKeyDown = false;
private static bool s_shiftKeyDown = false;
private bool isConnectedToWaapi = false;
private static GUIStyle s_expansionButtonStyle;
private static Texture2D s_textureCollapseAllIcon;
private static Texture2D s_textureExpandAllIcon;
[UnityEditor.MenuItem("Window/Wwise Browser", false, (int)AkWwiseWindowOrder.WwisePicker)]
public static void InitBrowserWindow()
{
AkWwiseBrowser window = (AkWwiseBrowser)EditorWindow.GetWindow(typeof(AkWwiseBrowser));
if (window == null)
{
window = GetWindow<AkWwiseBrowser>("Wwise Browser", true,typeof(EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow"));
}
LoadWindowTexture(window);
window.Show();
}
private static void LoadWindowTexture(AkWwiseBrowser window)
{
Texture2D originalIcon = EditorGUIUtility.Load("Assets/Wwise/API/Editor/WwiseWindows/BrowserIcon.png") as Texture2D;
if (originalIcon != null)
{
int newWidth = 32;
int newHeight = 32;
Texture2D scaledIcon = ScaleTexture(originalIcon, newWidth, newHeight);
window.titleContent = new GUIContent("Wwise Browser", scaledIcon);
}
else
{
window.titleContent = new GUIContent("Wwise Browser");
}
}
private static Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight)
{
RenderTexture rt = RenderTexture.GetTemporary(targetWidth, targetHeight);
RenderTexture.active = rt;
Graphics.Blit(source, rt);
Texture2D result = new Texture2D(targetWidth, targetHeight);
result.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0);
result.Apply();
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(rt);
return result;
}
public void OnEnable()
{
if (m_treeViewState == null)
{
m_treeViewState = new WwiseTreeViewState();
}
AkWwiseBrowser window = (AkWwiseBrowser)EditorWindow.GetWindow(typeof(AkWwiseBrowser));
if (window != null)
{
LoadWindowTexture(window);
}
var multiColumnHeaderState = AkWwiseTreeView.CreateDefaultMultiColumnHeaderState();
var multiColumnHeader = new UnityEditor.IMGUI.Controls.MultiColumnHeader(multiColumnHeaderState);
m_treeView = new AkWwiseTreeView(m_treeViewState, multiColumnHeader, AkWwiseProjectInfo.GetTreeData());
m_treeView.SetDoubleClickFunction(OnDoubleClick);
m_treeView.dirtyDelegate = RequestRepaint;
if (m_treeView.dataSource.Data.ItemDict.Count == 0)
{
Refresh();
RequestRepaint();
}
m_SearchField = new UnityEditor.IMGUI.Controls.SearchField();
m_SearchField.downOrUpArrowKeyPressed += m_treeView.SetFocusAndEnsureSelectedItem;
m_SearchField.SetFocus();
LoadIcons();
AkWwiseEditorSettings.OnWaapiSettingsChanged += RefreshWaapi;
}
public void LoadIcons()
{
var tempBrowserPath = "Assets/Wwise/API/Editor/WwiseWindows/BrowserIcons/";
s_textureCollapseAllIcon = AkWwisePickerIcons.GetTexture(tempBrowserPath + "GraphNode_CollapseAll.png");
s_textureExpandAllIcon = AkWwisePickerIcons.GetTexture(tempBrowserPath + "GraphNode_ExpandAll.png");
}
public void OnDisable()
{
m_treeView.SaveExpansionStatus();
}
private void RefreshWaapi()
{
Refresh();
}
public static void Refresh(bool ignoreIfWaapi = false)
{
if (m_treeView != null)
{
m_treeView.dataSource.FetchData();
};
}
private void OnDoubleClick(AkWwiseTreeViewItem item)
{
if (item == null)
{
return;
}
if (item.objectType == WwiseObjectType.Event)
{
PlayPauseItem(item);
return;
}
if (item.hasChildren)
{
m_treeView.SetExpanded(item.id, !m_treeView.IsExpanded(item.id));
}
}
private void SetItemAndChildrenExpansion(AkWwiseTreeViewItem item, bool expanded)
{
m_treeView.SetExpanded(item.id, expanded);
foreach (AkWwiseTreeViewItem child in item.children)
{
SetItemAndChildrenExpansion(child, expanded);
}
}
private void PlayPauseItem(AkWwiseTreeViewItem item)
{
if (m_treeView != null && m_treeView.CheckWaapi())
{
AkWaapiUtilities.TogglePlayEvent(item.objectType, item.objectGuid);
}
}
private bool isDirty;
public void RequestRepaint()
{
isDirty = true;
}
void Update()
{
if (isDirty)
{
Repaint();
m_treeView.Reload();
isDirty = false;
}
if (AkWwiseEditorSettings.Instance.UseWaapi)
{
AkWwiseProjectInfo.WaapiBrowserData.Update();
}
}
private void GenerateSoundbank(bool currentPlatformOnly = false)
{
System.Collections.Generic.List<string> platform = new System.Collections.Generic.List<string>();
if (currentPlatformOnly)
{
platform.Add(AkBasePathGetter.GetPlatformName());
platform.Add(AkBasePathGetter.GetTargetPlatformName(EditorUserBuildSettings.activeBuildTarget));
}
if (AkWaapiUtilities.IsConnected())
{
AkWaapiUtilities.GenerateSoundbank(platform.ToArray());
}
else
{
GenerateSoundbanks(platform);
}
}
void OnLostFocus()
{
s_altKeyDown = false;
s_controlKeyDown = false;
s_shiftKeyDown = false;
}
public void OnGUI()
{
if (isConnectedToWaapi != AkWaapiUtilities.IsConnected())
{
isConnectedToWaapi = AkWaapiUtilities.IsConnected();
Refresh();
}
const int buttonWidth = 150;
const int iconButtonWidth = 30;
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
Event e = Event.current;
if(e.isKey)
{
bool isKeyDown = e.type == EventType.KeyDown;
if (e.keyCode == KeyCode.LeftAlt || e.keyCode == KeyCode.RightAlt)
{
s_altKeyDown = isKeyDown;
}
else if (e.keyCode == KeyCode.LeftControl || e.keyCode == KeyCode.RightControl)
{
s_controlKeyDown = isKeyDown;
}
else if (e.keyCode == KeyCode.LeftShift || e.keyCode == KeyCode.RightShift)
{
s_shiftKeyDown = isKeyDown;
}
else if (e.keyCode == KeyCode.F5)
{
if(isKeyDown)
{
if(s_canRefresh)
{
Refresh();
s_canRefresh = false;
Event.current.Use();
}
}
else
{
s_canRefresh = true;
}
}
else if (isKeyDown)
{
if (e.keyCode == KeyCode.F7)
{
if (s_controlKeyDown && s_altKeyDown)
{
GenerateSoundbank();
}
else if (s_controlKeyDown && s_shiftKeyDown)
{
GenerateSoundbank(true);
}
Event.current.Use();
}
}
}
var buttonPressed = GUILayout.Button("Filters", new GUIStyle(GUI.skin.button));
if (Event.current.type == EventType.Repaint)
{
m_filterMenuRect = GUILayoutUtility.GetLastRect();
m_filterMenuRect.x += m_filterMenuRect.width - 25;
}
if (buttonPressed)
{
var screenRect = GUIUtility.GUIToScreenRect(m_filterMenuRect);
AkWwiseBrowserFilter.Init(screenRect);
}
if (s_expansionButtonStyle == null)
{
s_expansionButtonStyle = new GUIStyle(GUI.skin.button);
s_expansionButtonStyle.padding = new RectOffset(2, 2, 2, 2);
}
float expansionIconSize = 20.0f;
GUIContent expandAllButton = new GUIContent(s_textureExpandAllIcon);
expandAllButton.tooltip = "Expand All";
if (GUILayout.Button(expandAllButton, s_expansionButtonStyle, GUILayout.Height(expansionIconSize), GUILayout.Width(expansionIconSize)))
{
SetItemAndChildrenExpansion(m_treeView.dataSource.ProjectRoot, true);
}
GUIContent collapseAllButton = new GUIContent(s_textureCollapseAllIcon);
collapseAllButton.tooltip = "Collapse All";
if (GUILayout.Button(collapseAllButton, s_expansionButtonStyle, GUILayout.Height(expansionIconSize), GUILayout.Width(expansionIconSize)))
{
SetItemAndChildrenExpansion(m_treeView.dataSource.ProjectRoot, false);
}
var search_width = System.Math.Max(position.width / 3, buttonWidth * 2);
m_treeView.StoredSearchString = m_SearchField.OnGUI(UnityEngine.GUILayoutUtility.GetRect(search_width, 30), m_treeView.StoredSearchString);
UnityEngine.GUILayout.FlexibleSpace();
var RefreshContent = new GUIContent(EditorGUIUtility.IconContent("Refresh"));
RefreshContent.tooltip = "Refresh the Wwise Browser (F5)";
if (UnityEngine.GUILayout.Button(RefreshContent, UnityEngine.GUILayout.Width(iconButtonWidth)))
{
Refresh();
}
var GenerateContent = new GUIContent("Generate SoundBanks", "Generate all : Ctrl+Alt+F7\nGenerate for the current platform : Ctrl+Shift+F7");
if (UnityEngine.GUILayout.Button(GenerateContent, UnityEngine.GUILayout.Width(buttonWidth), UnityEngine.GUILayout.Height(20)))
{
GenerateSoundbank();
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.FlexibleSpace();
UnityEngine.Rect lastRect = UnityEngine.GUILayoutUtility.GetLastRect();
if (m_treeView.dataSource.isRefreshing)
{
GUILayout.Label("... LOADING WAAPI DATA ...", EditorStyles.boldLabel);
}
else
{
m_treeView.OnGUI(new UnityEngine.Rect(lastRect.x, lastRect.y, position.width, lastRect.height));
}
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
bool bConnected;
string tooltip = AkWaapiUtilities.GetStatusString(out bConnected);
var ConnectionContent = new GUIContent(EditorGUIUtility.IconContent(bConnected ? "Linked" : "Unlinked"));
ConnectionContent.tooltip = tooltip;
UnityEngine.GUILayout.Label(ConnectionContent, UnityEngine.GUILayout.Width(iconButtonWidth));
UnityEngine.GUILayout.Label("Root Output Path: " + AkWwiseEditorSettings.GetRootOutputPath());
var HelpContent = new GUIContent(EditorGUIUtility.IconContent("_Help"));
HelpContent.tooltip = "Open the Wwise Unity Integration Documentation";
if (UnityEngine.GUILayout.Button(HelpContent, UnityEngine.GUILayout.Width(iconButtonWidth)))
{
Application.OpenURL("https://www.audiokinetic.com/library/edge/?source=Unity&id=index.html");
}
var ProjectSettingsContent = new GUIContent(EditorGUIUtility.IconContent("_Popup"));
ProjectSettingsContent.tooltip = $"Open the Wwise Unity Project Settings{Environment.NewLine}" + $"Integration Version : {AkUnitySoundEngine.IntegrationVersion}{Environment.NewLine}" + $"SoundEngine Version : {AkUnitySoundEngine.WwiseVersion}";
if (UnityEngine.GUILayout.Button(ProjectSettingsContent, UnityEngine.GUILayout.Width(iconButtonWidth)))
{
OpenProjectSettings();
}
}
}
private void GenerateSoundbanks(System.Collections.Generic.List<string> platforms = null)
{
if (AkUtilities.IsSoundbankGenerationAvailable(AkWwiseEditorSettings.Instance.WwiseInstallationPath) && !AkUtilities.GeneratingSoundBanks)
{
AkUtilities.GenerateSoundbanks(AkWwiseEditorSettings.Instance.WwiseInstallationPath, AkWwiseEditorSettings.WwiseProjectAbsolutePath, platforms);
}
else if (!AkUtilities.GeneratingSoundBanks)
{
WwiseLogger.Error("Access to Wwise is required to generate the SoundBanks. Please go to Edit > Project Settings... and set the Wwise Application Path found in the Wwise Integration view.");
}
}
void OpenProjectSettings()
{
SettingsService.OpenProjectSettings("Project/Wwise Integration");
}
static public void SelectInWwiseBrowser(System.Guid guid)
{
InitBrowserWindow();
m_treeView.SelectItem(guid);
}
[UnityEditor.MenuItem("CONTEXT/AkBank/Select in Wwise Browser")]
[UnityEditor.MenuItem("CONTEXT/AkAmbient/Select in Wwise Browser")]
[UnityEditor.MenuItem("CONTEXT/AkEvent/Select in Wwise Browser")]
[UnityEditor.MenuItem("CONTEXT/AkState/Select in Wwise Browser")]
[UnityEditor.MenuItem("CONTEXT/AkSwitch/Select in Wwise Browser")]
[UnityEditor.MenuItem("CONTEXT/AkWwiseTrigger/Select in Wwise Browser")]
static void SelectItemInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkTriggerHandler component = (AkTriggerHandler)command.context;
try
{
var data = component.GetType().GetField("data");
var guid = (data.GetValue(component) as AK.Wwise.BaseType).ObjectReference.Guid;
SelectInWwiseBrowser(guid);
}
catch { }
}
[UnityEditor.MenuItem("CONTEXT/AkRoom/Select Aux Bus in Wwise Browser")]
static void SelectAkRoomAuxBusInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkRoom component = (AkRoom)command.context;
SelectInWwiseBrowser(component.reverbAuxBus.ObjectReference.Guid);
}
[UnityEditor.MenuItem("CONTEXT/AkRoom/Select Event in Wwise Browser")]
static void SelectAkRoomEventInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkRoom component = (AkRoom)command.context;
SelectInWwiseBrowser(component.roomToneEvent.ObjectReference.Guid);
}
[UnityEditor.MenuItem("CONTEXT/AkSurfaceReflector/Select in Wwise Browser")]
static void SelectReflectorTextureItemInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkSurfaceReflector component = (AkSurfaceReflector)command.context;
if (component.AcousticTextures.Length >0 && component.AcousticTextures[0].ObjectReference !=null)
{
SelectInWwiseBrowser(component.AcousticTextures[0].ObjectReference.Guid);
}
}
[UnityEditor.MenuItem("CONTEXT/AkEnvironment/Select in Wwise Browser")]
static void SelectEnvironmentItemInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkEnvironment component = (AkEnvironment)command.context;
SelectInWwiseBrowser(component.data.ObjectReference.Guid);
}
[UnityEditor.MenuItem("CONTEXT/AkEarlyReflections/Select in Wwise Browser")]
static void SelectReflectionsItemInWwiseBrowser(UnityEditor.MenuCommand command)
{
AkEarlyReflections component = (AkEarlyReflections)command.context;
SelectInWwiseBrowser(component.reflectionsAuxBus.ObjectReference.Guid);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0f90a5199ea669740a46cd278d4cf734
@@ -0,0 +1,255 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using UnityEditor;
using UnityEngine;
public class AkWwiseBrowserFilter : EditorWindow
{
private BrowserFilter Filters;
class BrowserFilterInfo
{
public bool Checked;
public string Label;
public BrowserFilter Filter;
public BrowserFilterInfo(string in_Label, BrowserFilter in_Filter)
{
Checked = false;
Label = in_Label;
Filter = in_Filter;
}
}
BrowserFilterInfo [] statusInfos = new BrowserFilterInfo[6];
BrowserFilterInfo [] typeInfos = new BrowserFilterInfo[8];
private bool allStatusSelected = false;
private bool allTypeSelected = false;
private bool m_close = false;
void InitBrowserFilterInfos()
{
statusInfos[0] = new BrowserFilterInfo("New in Wwise", BrowserFilter.NewInWwise);
statusInfos[1] = new BrowserFilterInfo("Deleted in Wwise", BrowserFilter.DeletedInWwise);
statusInfos[2] = new BrowserFilterInfo("Renamed in Wwise", BrowserFilter.RenamedInWwise);
statusInfos[3] = new BrowserFilterInfo("Moved in Wwise", BrowserFilter.MovedInWwise);
statusInfos[4] = new BrowserFilterInfo("SoundBanks need Update", BrowserFilter.SoundBankNeedsUpdate);
statusInfos[5] = new BrowserFilterInfo("SoundBanks Up to Date", BrowserFilter.SoundBanksUpToDate);
typeInfos[0] = new BrowserFilterInfo("Event", BrowserFilter.Event);
typeInfos[1] = new BrowserFilterInfo("Bus", BrowserFilter.Bus);
typeInfos[2] = new BrowserFilterInfo("Switch", BrowserFilter.Switch);
typeInfos[3] = new BrowserFilterInfo("State", BrowserFilter.State);
typeInfos[4] = new BrowserFilterInfo("Game Parameter", BrowserFilter.GameParameter);
typeInfos[5] = new BrowserFilterInfo("SoundBank", BrowserFilter.SoundBank);
typeInfos[6] = new BrowserFilterInfo("Trigger", BrowserFilter.Trigger);
typeInfos[7] = new BrowserFilterInfo("Acoustic Texture", BrowserFilter.AcousticTexture);
}
AkWwiseBrowserFilter()
{
InitBrowserFilterInfos();
SetCheckboxes();
}
public static void Init(Rect position)
{
EditorWindow window = CreateInstance<AkWwiseBrowserFilter>();
Vector2 windowSize = new Vector2(225, 390);
window.minSize = windowSize;
window.maxSize = windowSize;
window.ShowAsDropDown(position, windowSize);
}
void AllSelectedCheck()
{
allStatusSelected = true;
foreach (var status in statusInfos)
{
if (!status.Checked)
{
allStatusSelected = false;
}
}
allTypeSelected = true;
foreach (var type in typeInfos)
{
if (!type.Checked)
{
allTypeSelected = false;
}
}
ApplyFilters();
}
private void Update()
{
//Unity sometimes generates an error when the window is closed from the OnGUI function.
//So We close it here
if (m_close)
{
Close();
}
}
bool DisplayFilter(bool value, string Name)
{
const int iconButtonWidth = 20;
using (new UnityEngine.GUILayout.HorizontalScope())
{
EditorGUILayout.Space(5);
bool prev = value;
value = EditorGUILayout.Toggle(value, UnityEngine.GUILayout.Width(iconButtonWidth));
EditorGUILayout.LabelField(Name);
if (value != prev)
{
ApplyFilters();
}
}
return value;
}
void ApplyFilters()
{
if (AkWwiseBrowser.m_treeView == null)
{
return;
}
BrowserFilter newFilter = BrowserFilter.None;
foreach (var status in statusInfos)
{
if (status.Checked)
{
newFilter |= status.Filter;
}
}
foreach (var type in typeInfos)
{
if (type.Checked)
{
newFilter |= type.Filter;
}
}
if (AkWwiseBrowser.m_treeView.Filters != newFilter)
{
AkWwiseBrowser.m_treeView.Filters = newFilter;
AkWwiseBrowser.m_treeView.FiltersChanged = true;
AkWwiseBrowser.m_treeView.Repaint();
}
}
void SetCheckboxes()
{
if (AkWwiseBrowser.m_treeView == null)
{
return;
}
BrowserFilter Filter = AkWwiseBrowser.m_treeView.Filters;
foreach (var status in statusInfos)
{
if ((Filter & status.Filter) != 0)
{
status.Checked = true;
}
}
foreach (var type in typeInfos)
{
if ((Filter & type.Filter) != 0)
{
type.Checked = true;
}
}
}
void OnGUI()
{
const string SOUNDBANK_STATUS = "SoundBanks Status:";
const string OBJECT_TYPE = "Object Type:";
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
EditorGUILayout.LabelField(SOUNDBANK_STATUS);
}
foreach (var status in statusInfos)
{
status.Checked = DisplayFilter(status.Checked, status.Label);
AllSelectedCheck();
}
var Style = new GUIStyle();
var content = new GUIContent("SoundBank Not Up to Date");
content.tooltip = "Checks every filters in SoundBank Status except for \"SoundBanks Up to Date\"";
Style.normal.textColor = GUI.skin.button.normal.textColor;
Style.contentOffset = new Vector2(32, 5);
if (GUILayout.Button(content, Style, GUILayout.Height(20)))
{
allStatusSelected = true;
foreach (var status in statusInfos)
{
if (status.Filter != BrowserFilter.SoundBanksUpToDate)
{
status.Checked = true;
}
}
}
}
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
EditorGUILayout.LabelField(OBJECT_TYPE);
}
foreach (var type in typeInfos)
{
type.Checked = DisplayFilter(type.Checked, type.Label);
AllSelectedCheck();
}
}
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
if (UnityEngine.GUILayout.Button("Reset"))
{
foreach (var status in statusInfos)
{
status.Checked = false;
}
foreach (var type in typeInfos)
{
type.Checked = false;
}
}
if (UnityEngine.GUILayout.Button("Close"))
{
m_close = true;
}
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5672e1e9e0dc244469951118b8103c69
@@ -0,0 +1,225 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;
#else
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState;
#endif
public class AkWwiseComponentPicker : UnityEditor.EditorWindow
{
/// <summary>
/// Return the last picked object
/// </summary>
public static WwiseObjectReference GetObjectPickerObjectReference()
{
return s_componentPicker != null ? s_componentPicker.m_CurrentObjectReference : default;
}
/// <summary>
/// Return last control Id which opened the window
/// </summary>
public static int GetObjectPickerControlID()
{
return s_componentPicker != null ? s_componentPicker.m_ObjectSelectorId : default;
}
public const string PickerClosedEventName = "AkWwiseComponentPickerClosed";
public static AkWwiseComponentPicker s_componentPicker;
private AkWwiseTreeView m_treeView;
private bool m_close;
private UnityEditor.SerializedProperty m_WwiseObjectReference;
private UnityEditor.SerializedObject m_serializedObject;
private WwiseObjectType m_type;
UnityEditor.IMGUI.Controls.SearchField m_SearchField;
private WwiseObjectReference m_CurrentObjectReference;
private UnityEditor.EditorWindow m_PickedSourceEditorWindow;
private int m_ObjectSelectorId = 0;
/// <summary>
/// The window to repaint after closing the picker
/// </summary>
public static UnityEditor.EditorWindow LastFocusedWindow = null;
private void Update()
{
//Unity sometimes generates an error when the window is closed from the OnGUI function.
//So We close it here
if (m_close)
{
Close();
if (LastFocusedWindow)
{
UnityEditor.EditorApplication.delayCall += LastFocusedWindow.Repaint;
LastFocusedWindow = null;
}
}
}
private void OnGUI()
{
using (new UnityEngine.GUILayout.VerticalScope())
{
UnityEngine.GUILayout.Space(10);
m_treeView.StoredSearchString = m_SearchField.OnGUI(UnityEngine.GUILayoutUtility.GetRect(position.width - 60, 20), m_treeView.StoredSearchString);
UnityEngine.GUILayout.FlexibleSpace();
UnityEngine.Rect lastRect = UnityEngine.GUILayoutUtility.GetLastRect();
m_treeView.OnGUI(new UnityEngine.Rect(lastRect.x, lastRect.y, position.width, lastRect.height));
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
if (UnityEngine.GUILayout.Button("Ok"))
{
//Get the selected item
var selectedItem = m_treeView.dataSource.FindById(m_treeView.state.lastClickedID);
SetGuid(selectedItem);
}
else if (UnityEngine.GUILayout.Button("Cancel"))
m_close = true;
else if (UnityEngine.GUILayout.Button("Reset"))
{
ResetGuid();
m_close = true;
}
}
}
}
private void SetGuid(AkWwiseTreeViewItem in_element)
{
if (in_element == null || m_type != in_element.objectType) return;
if (m_serializedObject != null)
{
m_serializedObject.Update();
}
var reference = WwiseObjectReference.FindOrCreateWwiseObject(m_type, in_element.name, in_element.objectGuid);
var groupReference = reference as WwiseGroupValueObjectReference;
if (groupReference)
{
var parent = in_element.parent as AkWwiseTreeViewItem;
groupReference.SetupGroupObjectReference(parent.name, parent.objectGuid);
}
m_CurrentObjectReference = reference;
if (m_PickedSourceEditorWindow)
{
m_PickedSourceEditorWindow.SendEvent(UnityEditor.EditorGUIUtility.CommandEvent(PickerClosedEventName));
}
else
{
if (m_serializedObject != null)
{
m_serializedObject.Update();
}
m_WwiseObjectReference.objectReferenceValue = reference;
m_serializedObject.ApplyModifiedProperties();
}
AkWwiseBrowser.SelectInWwiseBrowser(in_element.objectGuid);
m_close = true;
}
private void ResetGuid()
{
m_CurrentObjectReference = null;
if (m_PickedSourceEditorWindow)
{
m_PickedSourceEditorWindow.SendEvent(UnityEditor.EditorGUIUtility.CommandEvent(PickerClosedEventName));
}
else
{
m_serializedObject.Update();
m_WwiseObjectReference.objectReferenceValue = null;
m_serializedObject.ApplyModifiedProperties();
}
}
public class PickerCreator
{
public UnityEditor.SerializedProperty wwiseObjectReference;
public WwiseObjectType objectType;
public UnityEngine.Rect pickerPosition;
public UnityEditor.SerializedObject serializedObject;
public WwiseObjectReference currentWwiseObjectReference;
public UnityEditor.EditorWindow pickedSourceEditorWindow;
public int pickedSourceControlId = 0;
private int minPickerWidth = 300;
internal PickerCreator()
{
UnityEditor.EditorApplication.delayCall += DelayCall;
}
private void DelayCall()
{
if (s_componentPicker != null)
return;
s_componentPicker = CreateInstance<AkWwiseComponentPicker>();
//position the window below the button
var pos = new UnityEngine.Rect(pickerPosition.x, pickerPosition.yMax, 0, 0);
//If the window gets out of the screen, we place it on top of the button instead
if (pickerPosition.yMax > UnityEngine.Screen.currentResolution.height / 2)
pos.y = pickerPosition.y - UnityEngine.Screen.currentResolution.height / 2;
//We show a drop down window which is automatically destroyed when focus is lost
s_componentPicker.ShowAsDropDown(pos,
new UnityEngine.Vector2(pickerPosition.width >= minPickerWidth ? pickerPosition.width : minPickerWidth,
UnityEngine.Screen.currentResolution.height / 2));
s_componentPicker.m_WwiseObjectReference = wwiseObjectReference;
s_componentPicker.m_serializedObject = serializedObject;
s_componentPicker.m_type = objectType;
s_componentPicker.m_CurrentObjectReference = currentWwiseObjectReference;
s_componentPicker.m_PickedSourceEditorWindow = pickedSourceEditorWindow;
s_componentPicker.m_ObjectSelectorId = pickedSourceControlId;
WwiseTreeViewState treeViewState = new WwiseTreeViewState();
s_componentPicker.m_treeView = new AkWwiseTreeView(treeViewState, AkWwiseProjectInfo.GetCurrentTreeData(), objectType);
s_componentPicker.m_treeView.DragDropEnabled = false;
s_componentPicker.m_treeView.SetDoubleClickFunction(s_componentPicker.SetGuid);
s_componentPicker.m_SearchField = new UnityEditor.IMGUI.Controls.SearchField();
s_componentPicker.m_SearchField.downOrUpArrowKeyPressed += s_componentPicker.m_treeView.SetFocusAndEnsureSelectedItem;
s_componentPicker.m_SearchField.SetFocus();
var reference = currentWwiseObjectReference;
if (reference)
{
s_componentPicker.m_treeView.dataSource.SelectItem(reference.Guid);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 444cbc4adb847784b812599b15aaa2d3
@@ -0,0 +1,372 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if !(UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using System.Linq;
using AK.Wwise.Unity.Logging;
#region GUI
#if UNITY_2018_3_OR_NEWER
class SettingsProvider : UnityEditor.SettingsProvider
#else
class EditorWindow : UnityEditor.EditorWindow
#endif
{
class Styles
{
public static string WwiseProject = "Wwise Project";
public static UnityEngine.GUIContent WwiseProjectPath = new UnityEngine.GUIContent("Wwise Project Path", "Location of the Wwise project associated with this game. It is recommended to put it in the Unity Project root folder, outside the Assets folder.");
public static string WwiseApplicationPath = "Wwise Application Path";
public static UnityEngine.GUIContent WwiseInstallationPath = new UnityEngine.GUIContent("Wwise Application Path", "Location of the Wwise application. This is required to generate the SoundBanks in Unity.");
public static string AssetManagement = "Asset Management";
public static UnityEngine.GUIContent SoundbankPath = new UnityEngine.GUIContent("SoundBanks Path", "Location of the SoundBanks relative to (and within) the StreamingAssets folder.");
public static UnityEngine.GUIContent CopySoundBanksAsPreBuildStep = new UnityEngine.GUIContent("Copy SoundBanks at pre-Build step", "Copies the SoundBanks in the appropriate location for building and deployment. It is recommended to leave this box checked.");
public static UnityEngine.GUIContent GenerateSoundBanksAsPreBuildStep = new UnityEngine.GUIContent("Generate SoundBanks at pre-Build step", "Generates the SoundBanks before copying them during pre-Build step. It is recommended to leave this box unchecked if SoundBanks are generated on a specific build machine.");
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
public static UnityEngine.GUIContent GeneratedSoundbankPath = new UnityEngine.GUIContent("Generated SoundBanks Path", "Destination folder for generated SoundBanks. Changing this will update your Wwise project settings");
#endif
public static string GlobalSettings = "Global Settings";
public static UnityEngine.GUIContent CreateWwiseGlobal = new UnityEngine.GUIContent("Create WwiseGlobal GameObject", "The WwiseGlobal object is a GameObject that contains the Initializing and Terminating scripts for the Wwise Sound Engine. In the Editor workflow, it is added to every scene, so that it can be properly previewed in the Editor. In the game, only one instance is created, in the first scene, and it is persisted throughout the game. It is recommended to leave this box checked.");
public static UnityEngine.GUIContent CreateWwiseListener = new UnityEngine.GUIContent("Add Listener to Main Camera", "In order for positioning to work, the AkAudioListener script needs to be attached to the main camera in every scene. If you wish for your listener to be attached to another GameObject, uncheck this box.");
public static UnityEngine.GUIContent ObjectReferenceAutoCleanup = new UnityEngine.GUIContent("Auto-delete WwiseObjectReferences", "Components that reference Wwise objects such as Events, Banks, and Busses track these references using WwiseObjectReference assets that are created in the Wwise/ScriptableObjects folder. If this option is checked and a Wwise Object has been removed from the Wwise Project, when parsing the Wwise project structure, the corresponding asset in the Wwise/ScriptableObjects folder will be deleted.");
public static UnityEngine.GUIContent LoadSoundEngineInEditMode = new UnityEngine.GUIContent("Load Sound Engine in Edit Mode", "Load the Sound Engine in Edit Mode. Disable this setting to verify the Sound Engine is properly enabled in-game.");
public static string InEditorWarnings = "In Editor Warnings";
public static UnityEngine.GUIContent ShowSpatialAudioWarningMsg = new UnityEngine.GUIContent("Show Spatial Audio Warnings", "Warnings will be displayed on Wwise components that are not configured for Spatial Audio to function properly. It is recommended to leave this box checked.");
public static string WaapiSection = "Wwise Authoring API (WAAPI)";
public static UnityEngine.GUIContent UseWaapi = new UnityEngine.GUIContent("Connect to Wwise");
public static UnityEngine.GUIContent WaapiIP = new UnityEngine.GUIContent("WAAPI IP address");
public static UnityEngine.GUIContent WaapiPort = new UnityEngine.GUIContent("WAAPI port");
public static UnityEngine.GUIContent AutosyncSelection = new UnityEngine.GUIContent("Autosync Wwise Browser Selection");
public static string TranslatorSection = "Wwise Error Message Translator";
public static UnityEngine.GUIContent XMLTranslatorTimeout = new UnityEngine.GUIContent("XML Translator Timeout", "Maximum time (ms) taken to convert numeric ID in errors through SoundBankInfo.xml. Set to 0 to disable. Change will be applied next time play mode is entered.");
public static UnityEngine.GUIContent WaapiTranslatorTimeout = new UnityEngine.GUIContent("WAAPI Translator Timeout", "Maximum time (ms) taken to convert numeric ID in errors through WAAPI. Set to 0 to disable. Change will be applied next time play mode is entered.");
public static UnityEngine.GUIContent AkLoggerLevel = new UnityEngine.GUIContent("AkLogger Level", "Log Verbosity.");
private static UnityEngine.GUIStyle version;
public static UnityEngine.GUIStyle Version
{
get
{
if (version != null)
return version;
version = new UnityEngine.GUIStyle(UnityEditor.EditorStyles.whiteLargeLabel);
if (!UnityEngine.Application.HasProLicense())
{
version.active.textColor =
version.focused.textColor =
version.hover.textColor =
version.normal.textColor = UnityEngine.Color.black;
}
return version;
}
}
private static UnityEngine.GUIStyle textField;
public static UnityEngine.GUIStyle TextField
{
get
{
if (textField == null)
textField = new UnityEngine.GUIStyle("textfield");
return textField;
}
}
}
private static bool Ellipsis()
{
return UnityEngine.GUILayout.Button("...", UnityEngine.GUILayout.Width(30));
}
private bool IsFolderWwiseApplicationPath(string path)
{
#if UNITY_EDITOR_OSX
return path.Contains("Wwise.app");
#else
string fullPath = Path.GetFullPath(Path.Combine(path, "Authoring\\x64\\Release\\bin\\Wwise.exe"));
return File.Exists(fullPath);
#endif
}
#if UNITY_2018_3_OR_NEWER
private SettingsProvider(string path) : base(path, UnityEditor.SettingsScope.Project) { }
public override void OnDeactivate()
{
base.OnDeactivate();
if(AkWwiseEditorSettings.Instance.LoadSoundEngineInEditMode && !AkUnitySoundEngine.IsInitialized())
{
AkUnitySoundEngineInitialization.Instance.InitializeSoundEngine();
}
else if (!AkWwiseEditorSettings.Instance.LoadSoundEngineInEditMode && AkUnitySoundEngine.IsInitialized())
{
AkUnitySoundEngineInitialization.Instance.TerminateSoundEngine();
}
}
public override void OnGUI(string searchContext)
#else
[UnityEditor.MenuItem("Edit/Wwise Settings...", false, (int)AkWwiseWindowOrder.WwiseSettings)]
public static void Init()
{
// Get existing open window or if none, make a new one:
var window = GetWindow(typeof(EditorWindow));
window.position = new UnityEngine.Rect(100, 100, 850, 360);
window.titleContent = new UnityEngine.GUIContent("Wwise Settings");
}
private void OnGUI()
#endif
{
bool changed = false;
var labelWidth = UnityEditor.EditorGUIUtility.labelWidth;
UnityEditor.EditorGUIUtility.labelWidth += 100;
var settings = AkWwiseEditorSettings.Instance;
UnityEngine.GUILayout.Label(string.Format("Wwise v{0} Settings.", AkUnitySoundEngine.WwiseVersion), Styles.Version);
UnityEngine.GUILayout.Label(Styles.WwiseProject, UnityEditor.EditorStyles.boldLabel);
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
UnityEditor.EditorGUILayout.PrefixLabel(Styles.WwiseProjectPath);
UnityEditor.EditorGUILayout.SelectableLabel(settings.WwiseProjectPath, Styles.TextField, UnityEngine.GUILayout.Height(17));
if (Ellipsis())
{
var OpenInPath = System.IO.Path.GetDirectoryName(AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.WwiseProjectPath));
var WwiseProjectPathNew = UnityEditor.EditorUtility.OpenFilePanel("Select your Wwise Project", OpenInPath, "wproj");
if (WwiseProjectPathNew.Length != 0)
{
if (WwiseProjectPathNew.EndsWith(".wproj") == false)
{
UnityEditor.EditorUtility.DisplayDialog("Error", "Please select a valid .wproj file", "Ok");
}
else
{
settings.WwiseProjectPath = AkUtilities.MakeRelativePath(UnityEngine.Application.dataPath, WwiseProjectPathNew);
changed = true;
}
}
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.WwiseApplicationPath, UnityEditor.EditorStyles.boldLabel);
using (new UnityEngine.GUILayout.HorizontalScope("box"))
{
UnityEditor.EditorGUILayout.PrefixLabel(Styles.WwiseInstallationPath);
UnityEditor.EditorGUILayout.SelectableLabel(settings.WwiseInstallationPath, Styles.TextField, UnityEngine.GUILayout.Height(17));
if (Ellipsis())
{
#if UNITY_EDITOR_OSX
var path = UnityEditor.EditorUtility.OpenFilePanel("Select your Wwise application.", "/Applications/", "");
#else
var path = UnityEditor.EditorUtility.OpenFolderPanel("Select your Wwise application.", System.Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "");
#endif
if (path != "" && !IsFolderWwiseApplicationPath(path))
{
EditorUtility.DisplayDialog("Wwise Application Path could not be set", $"{path} did not contain a Wwise Authoring application.", "OK");
}
else if (path.Length != 0)
{
settings.WwiseInstallationPath = System.IO.Path.GetFullPath(path);
changed = true;
}
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.AssetManagement, UnityEditor.EditorStyles.boldLabel);
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
using (new UnityEngine.GUILayout.HorizontalScope())
{
UnityEditor.EditorGUILayout.PrefixLabel(Styles.GeneratedSoundbankPath);
UnityEditor.EditorGUILayout.SelectableLabel(settings.RootOutputPath, Styles.TextField, UnityEngine.GUILayout.Height(17));
if (Ellipsis())
{
var FullPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.RootOutputPath);
var OpenInPath = System.IO.Path.GetDirectoryName(FullPath);
var path = UnityEditor.EditorUtility.OpenFolderPanel("Select your generated SoundBanks destination folder", OpenInPath, FullPath.Substring(OpenInPath.Length + 1));
if (path.Length != 0)
{
if (!path.Contains(UnityEngine.Application.dataPath))
{
UnityEditor.EditorUtility.DisplayDialog("Error", "The SoundBanks destination folder must be located within the Unity project 'Assets' folder.", "Ok");
}
else if (path == UnityEngine.Application.dataPath)
{
UnityEditor.EditorUtility.DisplayDialog("Error", "The SoundBanks destination folder cannot be the 'Assets' folder.", "Ok");
}
else
{
var newPath = AkUtilities.MakeRelativePath(UnityEngine.Application.dataPath, path);
var previousPath = settings.RootOutputPath;
if (previousPath != newPath)
{
settings.RootOutputPath = newPath;
var projectPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.WwiseProjectPath);
var relPath = AkUtilities.MakeRelativePath(System.IO.Path.GetDirectoryName(projectPath), path);
AkUtilities.SetSoundbanksDestinationFoldersInWproj(projectPath, relPath);
var fullPreviousPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, previousPath);
var appDataPath = UnityEngine.Application.dataPath.Replace(System.IO.Path.AltDirectorySeparatorChar, System.IO.Path.DirectorySeparatorChar);
if (!string.IsNullOrEmpty(previousPath) && System.IO.Directory.Exists(fullPreviousPath))
{
UnityEditor.AssetDatabase.Refresh();
if (fullPreviousPath.Contains(appDataPath))
{
var destination = System.IO.Path.Combine("Assets", newPath);
AkUtilities.MoveAssetsFromDirectory(fullPreviousPath, destination, true);
}
else
{
AkUtilities.DirectoryCopy(fullPreviousPath, path, true);
}
UnityEditor.AssetDatabase.Refresh();
}
changed = true;
}
}
}
}
}
}
#else
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
using (new UnityEngine.GUILayout.HorizontalScope())
{
UnityEditor.EditorGUILayout.PrefixLabel(Styles.SoundbankPath);
UnityEditor.EditorGUILayout.SelectableLabel(settings.WwiseStreamingAssetsPath, Styles.TextField, UnityEngine.GUILayout.Height(17));
if (Ellipsis())
{
var FullPath = AkUtilities.GetFullPath(UnityEngine.Application.streamingAssetsPath, settings.WwiseStreamingAssetsPath);
var OpenInPath = System.IO.Path.GetDirectoryName(FullPath);
var path = UnityEditor.EditorUtility.OpenFolderPanel("Select your SoundBanks destination folder", OpenInPath, FullPath.Substring(OpenInPath.Length + 1));
if (path.Length != 0)
{
var stremingAssetsIndex = UnityEngine.Application.dataPath.Split('/').Length;
var folders = path.Split('/');
if (folders.Length - 1 < stremingAssetsIndex || !string.Equals(folders[stremingAssetsIndex], "StreamingAssets", System.StringComparison.OrdinalIgnoreCase))
{
UnityEditor.EditorUtility.DisplayDialog("Error", "The SoundBank destination folder must be located within the Unity project 'StreamingAssets' folder.", "Ok");
}
else
{
var previousPath = settings.WwiseStreamingAssetsPath;
var newPath = AkUtilities.MakeRelativePath(UnityEngine.Application.streamingAssetsPath, path);
if (previousPath != newPath)
{
settings.WwiseStreamingAssetsPath = newPath;
changed = true;
}
}
}
}
}
UnityEditor.EditorGUI.BeginChangeCheck();
settings.CopySoundBanksAsPreBuildStep = UnityEditor.EditorGUILayout.Toggle(Styles.CopySoundBanksAsPreBuildStep, settings.CopySoundBanksAsPreBuildStep);
UnityEngine.GUI.enabled = settings.CopySoundBanksAsPreBuildStep;
settings.GenerateSoundBanksAsPreBuildStep = UnityEditor.EditorGUILayout.Toggle(Styles.GenerateSoundBanksAsPreBuildStep, settings.GenerateSoundBanksAsPreBuildStep);
UnityEngine.GUI.enabled = true;
if (UnityEditor.EditorGUI.EndChangeCheck())
changed = true;
}
#endif
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.GlobalSettings, UnityEditor.EditorStyles.boldLabel);
UnityEditor.EditorGUI.BeginChangeCheck();
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
settings.CreateWwiseGlobal = UnityEditor.EditorGUILayout.Toggle(Styles.CreateWwiseGlobal, settings.CreateWwiseGlobal);
settings.CreateWwiseListener = UnityEditor.EditorGUILayout.Toggle(Styles.CreateWwiseListener, settings.CreateWwiseListener);
settings.ObjectReferenceAutoCleanup = UnityEditor.EditorGUILayout.Toggle(Styles.ObjectReferenceAutoCleanup, settings.ObjectReferenceAutoCleanup);
settings.LoadSoundEngineInEditMode = UnityEditor.EditorGUILayout.Toggle(Styles.LoadSoundEngineInEditMode, settings.LoadSoundEngineInEditMode);
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.InEditorWarnings, UnityEditor.EditorStyles.boldLabel);
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
settings.ShowSpatialAudioWarningMsg = UnityEditor.EditorGUILayout.Toggle(Styles.ShowSpatialAudioWarningMsg, settings.ShowSpatialAudioWarningMsg);
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.WaapiSection, UnityEditor.EditorStyles.boldLabel);
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
settings.UseWaapi = UnityEditor.EditorGUILayout.Toggle(Styles.UseWaapi, settings.UseWaapi);
settings.WaapiPort = UnityEditor.EditorGUILayout.TextField(Styles.WaapiPort, settings.WaapiPort);
settings.WaapiIP = UnityEditor.EditorGUILayout.TextField(Styles.WaapiIP, settings.WaapiIP);
settings.AutoSyncWaapi = UnityEditor.EditorGUILayout.Toggle(Styles.AutosyncSelection, settings.AutoSyncWaapi);
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEngine.GUILayout.Label(Styles.TranslatorSection, UnityEditor.EditorStyles.boldLabel);
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
settings.XMLTranslatorTimeout = UnityEditor.EditorGUILayout.TextField(Styles.XMLTranslatorTimeout, settings.XMLTranslatorTimeout);
settings.WaapiTranslatorTimeout = UnityEditor.EditorGUILayout.TextField(Styles.WaapiTranslatorTimeout, settings.WaapiTranslatorTimeout);
}
if (UnityEditor.EditorGUI.EndChangeCheck())
changed = true;
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEditor.EditorGUIUtility.labelWidth = labelWidth;
if (changed)
{
settings.SaveSettings();
}
}
#endregion
}
#endif // UNITY_EDITOR
#endif // #if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9ae6e723419d0b24799d9704c15a5943
@@ -0,0 +1,583 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEditor.InitializeOnLoad]
public class AkWwiseJSONBuilder : UnityEditor.AssetPostprocessor
{
private static bool isSubscribedToInvokePopulate = false;
private static readonly System.DateTime s_LastParsed = System.DateTime.MinValue;
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
if (!isSubscribedToInvokePopulate)
{
WwiseProjectDatabase.SoundBankDirectoryUpdated += InvokePopulate;
isSubscribedToInvokePopulate = true;
}
if (didDomainReload)
{
UnityEditor.EditorApplication.playModeStateChanged += PlayModeChanged;
}
}
private static void PlayModeChanged(UnityEditor.PlayModeStateChange mode)
{
if (mode == UnityEditor.PlayModeStateChange.EnteredEditMode)
{
AkWwiseProjectInfo.Populate();
}
}
public static void InvokePopulate()
{
Populate();
WwiseProjectDatabase.SoundBankDirectoryUpdated -= InvokePopulate;
isSubscribedToInvokePopulate = false;
}
public static bool Populate()
{
if (UnityEditor.EditorApplication.isCompiling)
{
return false;
}
try
{
var bChanged = false;
WwiseSoundBankRefArray soundBankRefArray = new WwiseSoundBankRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetSoundBankCount(); i++)
{
var soundBankRef = soundBankRefArray[i];
bChanged = SerialiseSoundBank(soundBankRef) || bChanged;
}
WwiseEventRefArray eventRefArray = new WwiseEventRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetEventCount(); i++)
{
var eventRef = eventRefArray[i];
bChanged = SerialiseEventData(eventRef) || bChanged;
}
WwiseSwitchGroupRefArray switchGroupRefArray = new WwiseSwitchGroupRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetSwitchGroupCount(); i++)
{
var switchGroupRef = switchGroupRefArray[i];
bChanged = SerialiseSwitchGroupData(switchGroupRef) || bChanged;
}
WwiseSwitchRefArray switchRefArray = new WwiseSwitchRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetSwitchCount(); i++)
{
var switchRef = switchRefArray[i];
bChanged = SerialiseSwitchData(switchRef) || bChanged;
}
WwiseStateGroupRefArray stateGroupRefArray = new WwiseStateGroupRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetStateGroupCount(); i++)
{
var stateGroupRef = stateGroupRefArray[i];
bChanged = SerialiseStateGroupData(stateGroupRef) || bChanged;
}
WwiseStateRefArray stateRefArray = new WwiseStateRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetStateCount(); i++)
{
var stateRef = stateRefArray[i];
bChanged = SerialiseStateData(stateRef) || bChanged;
}
WwiseAcousticTextureRefArray acousticTextureRefArray = new WwiseAcousticTextureRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetAcousticTextureCount(); i++)
{
var acousticTextureRef = acousticTextureRefArray[i];
bChanged = SerialiseAcousticTextureData(acousticTextureRef) || bChanged;
}
WwiseGameParameterRefArray gameParameterRefArray = new WwiseGameParameterRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetGameParameterCount(); i++)
{
var gameParameterRef = gameParameterRefArray[i];
bChanged = SerialiseGameParameterData(gameParameterRef) || bChanged;
}
WwiseTriggerRefArray triggerRefArray = new WwiseTriggerRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetTriggerCount(); i++)
{
var triggerRef = triggerRefArray[i];
bChanged = SerialiseTriggerData(triggerRef) || bChanged;
}
WwiseBusRefArray busRefArray = new WwiseBusRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetBusCount(); i++)
{
var busRef = busRefArray[i];
bChanged = SerialiseBusData(busRef) || bChanged;
}
WwiseAuxBusRefArray auxBusRefArray = new WwiseAuxBusRefArray();
for (var i = 0; i < WwiseProjectDatabase.GetAuxBusCount(); i++)
{
var auxBusRef = auxBusRefArray[i];
bChanged = SerialiseAuxBusData(auxBusRef) || bChanged;
}
return bChanged;
}
catch (System.Exception e)
{
WwiseLogger.Log("Exception occured while parsing SoundbanksInfo.json: " + e.ToString());
return false;
}
}
private static bool SerialiseSoundBank(WwiseSoundBankRef soundBankRef)
{
var bChanged = false;
if (!soundBankRef.IsUserBank || soundBankRef.IsInitBank)
{
var eventCount = soundBankRef.EventsCount;
for (var i = 0; i < eventCount; i++)
{
var events = soundBankRef.Events[i];
bChanged = SerialiseEventData(events) || bChanged;
}
return bChanged;
}
AkWwiseProjectData.WwiseTreeObject wwiseSoundBank = new AkWwiseProjectData.WwiseTreeObject();
wwiseSoundBank.Name = soundBankRef.Name;
wwiseSoundBank.Path = soundBankRef.ObjectPath;
wwiseSoundBank.Guid = soundBankRef.Guid;
wwiseSoundBank.Type = WwiseObjectType.Soundbank;
var WorkUnit = BuildFolderHierarchy(soundBankRef.ObjectPath, AkWwiseProjectInfo.GetData().BankRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseSoundBank.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseSoundBank);
}
return bChanged;
}
private static List<AkWwiseProjectData.WwiseTreeObject> BuildFolderHierarchyRecursive(string[] Folders, List<AkWwiseProjectData.WwiseTreeObject> WorkUnits)
{
if (Folders.Length == 0)
{
return WorkUnits;
}
string FolderName = Folders[0];
if (FolderName.Length == 0)
{
return WorkUnits;
}
for (int i = 0; i < WorkUnits.Count; i++)
{
if (WorkUnits[i].Name == FolderName)
{
Folders = Folders.Skip(1).ToArray();
return BuildFolderHierarchyRecursive(Folders, WorkUnits[i].Children);
}
}
var CurrentWorkUnits = WorkUnits;
for (int i = 0; i < Folders.Length; i++)
{
AkWwiseProjectData.WwiseTreeObject newWorkUnit = new AkWwiseProjectData.WwiseTreeObject();
newWorkUnit.Name = Folders[i];
newWorkUnit.Children = new List<AkWwiseProjectData.WwiseTreeObject>();
CurrentWorkUnits.Add(newWorkUnit);
CurrentWorkUnits = CurrentWorkUnits[CurrentWorkUnits.Count - 1].Children;
}
return CurrentWorkUnits;
}
private static List<AkWwiseProjectData.WwiseTreeObject> BuildFolderHierarchy(string Path, List<AkWwiseProjectData.WwiseTreeObject> WorkUnits)
{
var Folders = Path.Split("\\");
if (Folders.Length < 2)
{
return WorkUnits;
}
Folders = Folders.Skip(2).ToArray();
Folders = Folders.Take(Folders.Length - 1).ToArray();
return BuildFolderHierarchyRecursive(Folders, WorkUnits);
}
private static float GetFloatFromString(string s)
{
if (string.Compare(s, "Infinite") == 0)
{
return UnityEngine.Mathf.Infinity;
}
else
{
System.Globalization.CultureInfo CultInfo = System.Globalization.CultureInfo.CurrentCulture.Clone() as System.Globalization.CultureInfo;
CultInfo.NumberFormat.NumberDecimalSeparator = ".";
CultInfo.NumberFormat.CurrencyDecimalSeparator = ".";
float Result;
if(float.TryParse(s, System.Globalization.NumberStyles.Float, CultInfo, out Result))
{
return Result;
}
else
{
WwiseLogger.Log("Could not parse float number " + s);
return 0.0f;
}
}
}
private static bool SerialiseEventData(WwiseEventRef eventRef)
{
float maxAttenuation = eventRef.MaxAttenuation;
var minDuration = eventRef.MinDuration;
var maxDuration = eventRef.MaxDuration;
var name = eventRef.Name;
var bChanged = false;
AkWwiseProjectData.Event wwiseEvent = new AkWwiseProjectData.Event();
wwiseEvent.maxAttenuation = maxAttenuation;
wwiseEvent.minDuration = minDuration;
wwiseEvent.maxDuration = maxDuration;
wwiseEvent.Name = name;
wwiseEvent.Guid = eventRef.Guid;
wwiseEvent.Path = eventRef.Path;
wwiseEvent.Type = WwiseObjectType.Event;
var WorkUnit = BuildFolderHierarchy(eventRef.Path, AkWwiseProjectInfo.GetData().EventRoot);
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseEvent.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseEvent);
}
return bChanged;
}
private static bool SerialiseSwitchGroupData(WwiseSwitchGroupRef switchRef)
{
var name = switchRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseSwitchGroup = new AkWwiseProjectData.WwiseTreeObject();
wwiseSwitchGroup.Name = name;
wwiseSwitchGroup.Path = switchRef.Path;
wwiseSwitchGroup.Guid = switchRef.Guid;
wwiseSwitchGroup.Type = WwiseObjectType.SwitchGroup;
wwiseSwitchGroup.Children = new List<AkWwiseProjectData.WwiseTreeObject>();
var workUnit = BuildFolderHierarchy(switchRef.Path, AkWwiseProjectInfo.GetData().SwitchRoot);
bool bIsDuplicate = false;
foreach (var Info in workUnit)
{
if (Info.Guid == wwiseSwitchGroup.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
workUnit.Add(wwiseSwitchGroup);
}
return bChanged;
}
private static bool SerialiseSwitchData(WwiseSwitchRef switchRef)
{
var name = switchRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseSwitch = new AkWwiseProjectData.WwiseTreeObject();
wwiseSwitch.Name = name;
wwiseSwitch.Path = switchRef.Path;
wwiseSwitch.Guid = switchRef.Guid;
wwiseSwitch.Type = WwiseObjectType.Switch;
var WorkUnit = BuildFolderHierarchy(switchRef.Path, AkWwiseProjectInfo.GetData().SwitchRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseSwitch.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseSwitch);
}
return bChanged;
}
private static bool SerialiseStateGroupData(WwiseStateGroupRef switchRef)
{
var name = switchRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseStateGroup = new AkWwiseProjectData.WwiseTreeObject();
wwiseStateGroup.Name = name;
wwiseStateGroup.Guid = switchRef.Guid;
wwiseStateGroup.Path = switchRef.Path;
wwiseStateGroup.Type = WwiseObjectType.StateGroup;
wwiseStateGroup.Children = new List<AkWwiseProjectData.WwiseTreeObject>();
var WorkUnit = BuildFolderHierarchy(switchRef.Path, AkWwiseProjectInfo.GetData().StateRoot);
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseStateGroup.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseStateGroup);
}
return bChanged;
}
private static bool SerialiseStateData(WwiseStateRef stateRef)
{
var name = stateRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseState = new AkWwiseProjectData.WwiseTreeObject();
wwiseState.Name = name;
wwiseState.Path = stateRef.Path;
wwiseState.Guid = stateRef.Guid;
wwiseState.Type = WwiseObjectType.State;
var WorkUnit = BuildFolderHierarchy(stateRef.Path, AkWwiseProjectInfo.GetData().StateRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseState.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseState);
}
return bChanged;
}
private static bool SerialiseAcousticTextureData(WwiseAcousticTextureRef acousticTextureRef)
{
var name = acousticTextureRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseAcousticTexture = new AkWwiseProjectData.WwiseTreeObject();
wwiseAcousticTexture.Name = name;
wwiseAcousticTexture.Path = acousticTextureRef.Path;
wwiseAcousticTexture.Guid = acousticTextureRef.Guid;
wwiseAcousticTexture.Type = WwiseObjectType.AcousticTexture;
var WorkUnit = BuildFolderHierarchy(acousticTextureRef.Path, AkWwiseProjectInfo.GetData().AcousticTextureRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseAcousticTexture.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseAcousticTexture);
}
return bChanged;
}
private static bool SerialiseGameParameterData(WwiseGameParameterRef GameParameterRef)
{
var name = GameParameterRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseGameParameter = new AkWwiseProjectData.WwiseTreeObject();
wwiseGameParameter.Name = name;
wwiseGameParameter.Path = GameParameterRef.Path;
wwiseGameParameter.Guid = GameParameterRef.Guid;
wwiseGameParameter.Type = WwiseObjectType.GameParameter;
var WorkUnit = BuildFolderHierarchy(GameParameterRef.Path, AkWwiseProjectInfo.GetData().GameParameterRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseGameParameter.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseGameParameter);
}
return bChanged;
}
private static bool SerialiseTriggerData(WwiseTriggerRef TriggerRef)
{
var name = TriggerRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseTrigger = new AkWwiseProjectData.WwiseTreeObject();
wwiseTrigger.Name = name;
wwiseTrigger.Path = TriggerRef.Path;
wwiseTrigger.Guid = TriggerRef.Guid;
wwiseTrigger.Type = WwiseObjectType.Trigger;
var WorkUnit = BuildFolderHierarchy(TriggerRef.Path, AkWwiseProjectInfo.GetData().TriggerRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseTrigger.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseTrigger);
}
return bChanged;
}
private static bool SerialiseBusData(WwiseBusRef BusRef)
{
var name = BusRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseBus = new AkWwiseProjectData.WwiseTreeObject();
wwiseBus.Name = name;
wwiseBus.Path = BusRef.Path;
wwiseBus.Guid = BusRef.Guid;
wwiseBus.Type = WwiseObjectType.Bus;
wwiseBus.Children = new List<AkWwiseProjectData.WwiseTreeObject>();
var WorkUnit = BuildFolderHierarchy(BusRef.Path, AkWwiseProjectInfo.GetData().BusRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseBus.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseBus);
}
return bChanged;
}
private static bool SerialiseAuxBusData(WwiseAuxBusRef AuxBusRef)
{
var name = AuxBusRef.Name;
var bChanged = false;
AkWwiseProjectData.WwiseTreeObject wwiseAuxBus = new AkWwiseProjectData.WwiseTreeObject();
wwiseAuxBus.Name = name;
wwiseAuxBus.Path = AuxBusRef.Path;
wwiseAuxBus.Guid = AuxBusRef.Guid;
wwiseAuxBus.Type = WwiseObjectType.AuxBus;
wwiseAuxBus.Children = new List<AkWwiseProjectData.WwiseTreeObject>();
var WorkUnit = BuildFolderHierarchy(AuxBusRef.Path, AkWwiseProjectInfo.GetData().BusRoot);
if (WorkUnit == null)
{
return false;
}
bool bIsDuplicate = false;
foreach (var Info in WorkUnit)
{
if (Info.Guid == wwiseAuxBus.Guid)
{
bIsDuplicate = true;
break;
}
}
if(!bIsDuplicate)
{
WorkUnit.Add(wwiseAuxBus);
}
return bChanged;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f2693fc737afd5a4cbd84eb2bdd915d4
@@ -0,0 +1,256 @@
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
public class AkWwiseProjectData
{
[FormerlySerializedAs("AcousticTextureWwu")] public System.Collections.Generic.List<WwiseTreeObject> AcousticTextureRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("AuxBusWwu")] public System.Collections.Generic.List<WwiseTreeObject> BusRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("BankWwu")] public System.Collections.Generic.List<WwiseTreeObject> BankRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("EventWwu")] public System.Collections.Generic.List<WwiseTreeObject> EventRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("RtpcWwu")] public System.Collections.Generic.List<WwiseTreeObject> GameParameterRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("StateWwu")] public System.Collections.Generic.List<WwiseTreeObject> StateRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("SwitchWwu")] public System.Collections.Generic.List<WwiseTreeObject> SwitchRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
[FormerlySerializedAs("TriggerWwu")] public System.Collections.Generic.List<WwiseTreeObject> TriggerRoot =
new System.Collections.Generic.List<WwiseTreeObject>();
////Contains the int id of all items that are expanded in the Wwise picker
public System.Collections.Generic.List<int> ExpandedFileSystemItemIds = new System.Collections.Generic.List<int>();
public System.Collections.Generic.List<int> ExpandedWaapiItemIds = new System.Collections.Generic.List<int>();
public bool AutoSyncSelection;
public string CurrentPluginConfig;
public float GetEventMaxAttenuation(uint eventID)
{
var Event = GetEventInfo(eventID);
return Event != null ? Event.maxAttenuation : 0.0f;
}
public Event GetEventInfo(uint eventID)
{
foreach (var root in EventRoot)
{
var found = root.Find(eventID);
if (found != null)
{
return found as Event;
}
}
return null;
}
public void Reset()
{
EventRoot = new System.Collections.Generic.List<WwiseTreeObject>();
StateRoot = new System.Collections.Generic.List<WwiseTreeObject>();
SwitchRoot = new System.Collections.Generic.List<WwiseTreeObject>();
BankRoot = new System.Collections.Generic.List<WwiseTreeObject>();
BusRoot = new System.Collections.Generic.List<WwiseTreeObject>();
GameParameterRoot = new System.Collections.Generic.List<WwiseTreeObject>();
TriggerRoot = new System.Collections.Generic.List<WwiseTreeObject>();
AcousticTextureRoot = new System.Collections.Generic.List<WwiseTreeObject>();
}
[System.Serializable]
public class ByteArrayWrapper
{
public byte[] bytes;
public ByteArrayWrapper(byte[] byteArray)
{
bytes = byteArray;
}
public static implicit operator ByteArrayWrapper(System.Guid guid) => new ByteArrayWrapper(guid.ToByteArray());
public static implicit operator System.Guid(ByteArrayWrapper bytes) => new System.Guid(bytes.bytes);
}
private static System.Guid GetGuid(byte[] bytes)
{
try
{
return new System.Guid(bytes);
}
catch
{
return System.Guid.Empty;
}
}
[System.Serializable]
public class AkBaseInformation : System.IComparable
{
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("Name")]
private string name;
public string Name
{
get { return name; }
set
{
name = value;
id = AkUtilities.ShortIDGenerator.Compute(value);
}
}
private System.Guid guid;
public System.Guid Guid
{
get { return guid; }
set { guid = value; }
}
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("ID")]
private uint id;
public uint Id
{
get { return id; }
set { id = value; }
}
[UnityEngine.HideInInspector]
public System.Collections.Generic.List<PathElement> PathAndIcons = new System.Collections.Generic.List<PathElement>();
int System.IComparable.CompareTo(object other)
{
if (other == null)
return 1;
var otherAkInformation = other as AkBaseInformation;
if (otherAkInformation == null)
throw new System.ArgumentException("Object is not of type AkBaseInformation");
return Name.CompareTo(otherAkInformation.Name);
}
private class _CompareByGuid : System.Collections.Generic.IComparer<AkBaseInformation>
{
int System.Collections.Generic.IComparer<AkBaseInformation>.Compare(AkBaseInformation a, AkBaseInformation b)
{
if (a == null)
return b == null ? 0 : -1;
return a.Guid.CompareTo(b.Guid);
}
}
public static System.Collections.Generic.IComparer<AkBaseInformation> CompareByGuid = new _CompareByGuid();
}
[System.Serializable]
public class WwiseTreeObject : AkBaseInformation
{
public string Path;
public List<WwiseTreeObject> Children;
public WwiseObjectType Type = WwiseObjectType.Folder;
public WwiseTreeObject Find(uint shortId)
{
if (Id == shortId)
{
return this;
}
if (Children == null)
{
return null;
}
foreach(var Child in Children)
{
var found = Child.Find(shortId);
if (found != null)
{
return found;
}
}
return null;
}
}
[System.Serializable]
public class Event : WwiseTreeObject
{
public float maxAttenuation;
public float maxDuration = -1;
public float minDuration = -1;
}
[System.Serializable]
public class PathElement
{
public string ElementName;
public WwiseObjectType ObjectType;
public string Path;
[UnityEngine.SerializeField]
[UnityEngine.HideInInspector]
private byte[] guid = null;
public System.Guid ObjectGuid
{
get { return GetGuid(guid); }
set { guid = value.ToByteArray(); }
}
public PathElement(string Name, WwiseObjectType objType, System.Guid guid)
{
ElementName = Name;
ObjectType = objType;
ObjectGuid = guid;
}
public static string GetProjectPathString(System.Collections.Generic.List<PathElement> pathElements, int index)
{
string path = "";
for (int i = 0; i<=index && i < pathElements.Count; i++)
{
path += $"/{pathElements[i].ElementName}";
}
return path;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f24341d45ff62b54d97d79a55c127611
@@ -0,0 +1,104 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
using UnityEditor;
using AK.Wwise.Unity.Logging;
public static class AkWwiseProjectInfo
{
public static AkWwiseProjectData ProjectData;
private static AkWwiseTreeWAAPIDataSource _waapiBrowserData = new AkWwiseTreeWAAPIDataSource();
private static AkWwiseTreeProjectDataSource _projectPickerData = new AkWwiseTreeProjectDataSource();
public static AkWwiseTreeWAAPIDataSource WaapiBrowserData
{
get
{
return _waapiBrowserData;
}
}
public static AkWwiseTreeProjectDataSource ProjectPickerData
{
get
{
return _projectPickerData;
}
}
public static AkWwiseTreeDataSource GetCurrentTreeData()
{
AkWwiseTreeMergedDataSource treeData = new AkWwiseTreeMergedDataSource();
treeData.MergeDataSources();
return treeData;
}
public static AkWwiseTreeDataSource GetTreeData()
{
GetData().Reset();
AkWwiseTreeMergedDataSource treeData = new AkWwiseTreeMergedDataSource();
treeData.FetchData();
return treeData;
}
private static bool WwiseFolderExists()
{
return System.IO.Directory.Exists(System.IO.Path.Combine(UnityEngine.Application.dataPath, "Wwise"));
}
public static AkWwiseProjectData GetData()
{
if (ProjectData == null && WwiseFolderExists())
{
try
{
CreateWwiseProjectData();
}
catch (System.Exception e)
{
WwiseLogger.Error("Unable to load Wwise Data: " + e);
}
}
return ProjectData;
}
private static void CreateWwiseProjectData()
{
ProjectData = new AkWwiseProjectData();
}
public static bool Populate()
{
var bDirty = false;
if (AkUtilities.IsWwiseProjectAvailable)
{
AkWwiseProjectInfo.GetData().Reset();
bDirty |= AkWwiseJSONBuilder.Populate();
}
if (AkWaapiUtilities.IsConnected())
{
_waapiBrowserData.FetchData();
}
return bDirty;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 14f75fd5cdf5b5f49b027e9fe54e5da6
@@ -0,0 +1,439 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEditor.IMGUI.Controls;
using AK.Wwise.Unity.Logging;
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;
#else
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem;
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState;
#endif
public enum BrowserFilter
{
None,
SoundBanksUpToDate = 1 << 0,
NewInWwise = 1 << 1,
DeletedInWwise = 1 << 2,
RenamedInWwise = 1 << 3,
MovedInWwise = 1 << 4,
SoundBankNeedsUpdate = 1 << 5,
Event = 1 << 6,
Bus = 1 << 7,
SoundBank = 1 << 8,
Switch = 1 << 9,
State = 1 << 10,
Trigger = 1 << 11,
AcousticTexture = 1 << 12,
GameParameter = 1 << 13
}
public class WwiseTreeStringKey
{
string name;
WwiseObjectType objectType;
public WwiseTreeStringKey(string name, WwiseObjectType objectType)
{
this.name = name;
this.objectType = objectType;
}
public override int GetHashCode()
{
return name.GetHashCode() | objectType.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is WwiseTreeStringKey)
{
WwiseTreeStringKey other = (WwiseTreeStringKey)obj;
return other.objectType == objectType && other.name == name;
}
return false;
}
}
public abstract class AkWwiseTreeDataSource
{
public class TreeItems
{
public Dictionary<System.Guid, AkWwiseTreeViewItem> ItemDict;
public Dictionary<WwiseTreeStringKey, AkWwiseTreeViewItem> ItemNameDict;
public TreeItems()
{
ItemDict = new Dictionary<System.Guid, AkWwiseTreeViewItem>();
ItemNameDict = new Dictionary<WwiseTreeStringKey, AkWwiseTreeViewItem>();
}
public void Clear()
{
ItemDict.Clear();
ItemNameDict.Clear();
}
public void Add(AkWwiseTreeViewItem item)
{
try
{
ItemDict[item.objectGuid] = item;
if (item.name != null)
{
ItemNameDict[new WwiseTreeStringKey(item.name, item.objectType)] = item;
}
}
catch (System.ArgumentException e)
{
WwiseLogger.Error(e.Message);
}
}
public void Remove(AkWwiseTreeViewItem item)
{
try
{
ItemDict.Remove(item.objectGuid);
ItemNameDict.Remove(new WwiseTreeStringKey(item.name, item.objectType));
}
catch (System.ArgumentException e)
{
WwiseLogger.Error(e.Message);
}
}
}
static public ReadOnlyDictionary<WwiseObjectType, string> FolderNames = new ReadOnlyDictionary<WwiseObjectType, string>(new Dictionary<WwiseObjectType, string>()
{
{ WwiseObjectType.AuxBus, "Busses" },
{ WwiseObjectType.Event, "Events" },
{ WwiseObjectType.State, "States"},
{ WwiseObjectType.StateGroup, "States"},
{ WwiseObjectType.Soundbank, "SoundBanks"},
{ WwiseObjectType.Switch, "Switches"},
{ WwiseObjectType.SwitchGroup, "Switches"},
{ WwiseObjectType.AcousticTexture, "Virtual Acoustics" },
{ WwiseObjectType.Trigger, "Triggers" },
{ WwiseObjectType.GameParameter, "Game Parameters" },
});
public TreeItems Data;
public AkWwiseTreeViewItem ProjectRoot { get; protected set; }
public Dictionary<WwiseObjectType, AkWwiseTreeViewItem> wwiseObjectFolders;
public AkWwiseTreeViewItem SearchRoot { get; protected set; }
public TreeItems SearchData;
protected AkWwiseTreeView TreeView { get; set; }
public event System.Action modelChanged;
public virtual AkWwiseTreeViewItem CreateProjectRootItem()
{
return new AkWwiseTreeViewItem(System.IO.Path.GetFileNameWithoutExtension(AkWwiseEditorSettings.Instance.WwiseProjectPath),
-1, GenerateUniqueID(), System.Guid.Empty, WwiseObjectType.Project);
}
protected int m_MaxID;
public int GenerateUniqueID()
{
return ++m_MaxID;
}
public AkWwiseTreeDataSource()
{
Data = new TreeItems();
wwiseObjectFolders = new Dictionary<WwiseObjectType, AkWwiseTreeViewItem>();
ProjectRoot = CreateProjectRootItem();
}
public WwiseTreeViewItem FindByIdRecursive(WwiseTreeViewItem item, int id)
{
if (item.id == id)
{
return item;
}
foreach (var element in item.children)
{
var found = FindByIdRecursive(element, id);
if (found != null)
{
return found;
}
}
return null;
}
public AkWwiseTreeViewItem FindById(int id)
{
if (m_MaxID < id)
{
return null;
}
foreach (var element in ProjectRoot.children)
{
var found = FindByIdRecursive(element, id);
if (found != null)
{
return found as AkWwiseTreeViewItem;
}
}
return Data.ItemDict.Values.FirstOrDefault(element => element.id == id);
}
public WwiseTreeViewItem FindByNameRecursive(WwiseTreeViewItem item, string name, WwiseObjectType objectType)
{
if ( (item as AkWwiseTreeViewItem).objectType == objectType && item.displayName == name)
{
return item;
}
foreach (var element in item.children)
{
var found = FindByNameRecursive(element, name, objectType);
if (found != null)
{
return found;
}
}
return null;
}
public AkWwiseTreeViewItem FindByName(string name, WwiseObjectType objectType)
{
var key = new WwiseTreeStringKey(name, objectType);
if (Data.ItemNameDict.ContainsKey(key))
{
return Data.ItemNameDict[key];
}
return null;
}
public AkWwiseTreeViewItem FindByGuid(System.Guid guid)
{
return TreeUtility.FindByGuid(Data, guid);
}
public AkWwiseTreeViewItem FindInSearchResults(System.Guid guid)
{
return TreeUtility.FindByGuid(SearchData, guid);
}
public IEnumerable<System.Guid> GetGuidsFromIds(IEnumerable<int> ids)
{
if (Data.ItemDict.Count == 0) return new List<System.Guid>();
return Data.ItemDict.Values.Where(el => ids.Contains(el.id)).Select(el => el.objectGuid);
}
public IEnumerable<int> GetIdsFromGuids(IEnumerable<System.Guid> guids)
{
if (Data.ItemDict.Count == 0) return new List<int>();
return Data.ItemDict.Values.Where(el => guids.Contains(el.objectGuid)).Select(el => el.id);
}
public IList<int> GetAncestors(int id)
{
var parents = new List<int>();
WwiseTreeViewItem el = FindById(id);
if (el != null)
{
while (el.parent != null)
{
parents.Add(el.parent.id);
el = el.parent;
}
}
return parents;
}
public IList<int> GetDescendantsThatHaveChildren(int id)
{
AkWwiseTreeViewItem searchFromThis = FindById(id);
if (searchFromThis != null)
{
return GetParentsBelowStackBased(searchFromThis);
}
return new List<int>();
}
public bool isRefreshing = false;
IList<int> GetParentsBelowStackBased(AkWwiseTreeViewItem searchFromThis)
{
Stack<AkWwiseTreeViewItem> stack = new Stack<AkWwiseTreeViewItem>();
stack.Push(searchFromThis);
var parentsBelow = new List<int>();
while (stack.Count > 0)
{
AkWwiseTreeViewItem current = stack.Pop();
if (current.hasChildren)
{
parentsBelow.Add(current.id);
foreach (AkWwiseTreeViewItem el in current.children)
{
stack.Push(el);
}
}
}
return parentsBelow;
}
abstract public AkWwiseTreeViewItem GetComponentDataRoot(WwiseObjectType objectType);
protected void Changed()
{
modelChanged?.Invoke();
}
public bool IsExpanded(WwiseTreeViewState state, int id)
{
if (ProjectRoot != null && id == ProjectRoot.id)
{
return true;
}
return state.expandedIDs.BinarySearch(id) >= 0;
}
public abstract void FetchData();
public static int GetDepthFromPath(string path)
{
return path.Split('\\').Length - 1;
}
public virtual void ScheduleRebuild()
{
}
public abstract void SaveExpansionStatus(List<int> itemIds);
public abstract List<int> LoadExpansionSatus();
public string currentSearchString;
public bool isSearching = false;
public abstract AkWwiseTreeViewItem GetSearchResults();
public abstract void UpdateSearchResults(string searchString, WwiseObjectType objectType, BrowserFilter Filters);
public virtual void SelectItem(System.Guid itemGuid)
{
bool success = TreeView.ExpandItem(itemGuid, true);
if (!success)
{
UnityEditor.EditorApplication.delayCall += () => { SelectItem(itemGuid); };
}
}
public virtual void SetWwiseTreeView(AkWwiseTreeView treeView)
{
TreeView = treeView;
}
public virtual void LoadComponentData(WwiseObjectType objectType) { }
public virtual void ItemSelected(AkWwiseTreeViewItem itemID) { }
public virtual void SelectObjectInAuthoring(System.Guid objectGuid) { }
public abstract void SetExpanded(IEnumerable<System.Guid> ids);
}
#region Utility Functions
public static class TreeUtility
{
public static void CopyTree(AkWwiseTreeViewItem sourceRoot, AkWwiseTreeViewItem destRoot)
{
for (int i = 0; i < sourceRoot.children.Count(); i++)
{
var currItem = sourceRoot.children[i];
var newItem = new AkWwiseTreeViewItem(currItem as AkWwiseTreeViewItem);
CopyTree(currItem as AkWwiseTreeViewItem, newItem);
destRoot.AddWwiseItemChild(newItem);
}
}
public static void TreeToList(AkWwiseTreeViewItem root, ref AkWwiseTreeDataSource.TreeItems result)
{
if (root == null)
return;
if (result == null)
return;
result.Clear();
Stack<AkWwiseTreeViewItem> stack = new Stack<AkWwiseTreeViewItem>();
stack.Push(root);
while (stack.Count > 0)
{
AkWwiseTreeViewItem current = stack.Pop();
result.Add(current);
if (current.children != null && current.children.Count > 0)
{
for (int i = current.children.Count - 1; i >= 0; i--)
{
if (current.children[i] != null)
{
stack.Push((AkWwiseTreeViewItem)current.children[i]);
}
}
}
}
}
public static void SortTreeIfNecessary(AkWwiseTreeViewItem rootElement)
{
if (rootElement.hasChildren)
{
if (!rootElement.isSorted)
{
rootElement.SortChildren();
}
foreach (AkWwiseTreeViewItem child in rootElement.children)
{
SortTreeIfNecessary(child);
}
}
}
public static AkWwiseTreeViewItem FindByGuid(IEnumerable<AkWwiseTreeViewItem> data, System.Guid guid)
{
return data.FirstOrDefault(element => element.objectGuid == guid);
}
public static AkWwiseTreeViewItem FindByGuid(AkWwiseTreeDataSource.TreeItems data, System.Guid guid)
{
if (!data.ItemDict.ContainsKey(guid))
{
return null;
}
return data.ItemDict[guid];
}
}
#endregion
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4c68fa97c71a9a8459c020bb4018f174
@@ -0,0 +1,684 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using AK.Wwise.Unity.Logging;
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
#else
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem;
#endif
public class AkWwiseTreeMergedDataSource : AkWwiseTreeDataSource
{
private AkWwiseTreeProjectDataSource SoundBanksDataSource;
private AkWwiseTreeWAAPIDataSource WaapiDataSource;
public AkWwiseTreeMergedDataSource() : base()
{
AkWwiseJSONBuilder.Populate();
SoundBanksDataSource = AkWwiseProjectInfo.ProjectPickerData;
WaapiDataSource = AkWwiseProjectInfo.WaapiBrowserData;
if (!SoundBanksDataSource.ProjectRoot.hasChildren)
{
FetchData();
}
WaapiDataSource.ObjectInfoLoaded+=OnWaapiDataLoaded;
SoundBanksDataSource.modelChanged+=MergeDataSources;
WaapiDataSource.modelChanged+=MergeDataSources;
}
public void OnWaapiDataLoaded()
{
MergeDataSources();
isRefreshing = false;
}
public AkWwiseTreeMergedDataSource(AkWwiseTreeProjectDataSource projectDataSource, AkWwiseTreeWAAPIDataSource waapiDataSource) : base()
{
SoundBanksDataSource = projectDataSource;
WaapiDataSource = waapiDataSource;
}
~AkWwiseTreeMergedDataSource()
{
SoundBanksDataSource.modelChanged-=MergeDataSources;
WaapiDataSource.modelChanged-=MergeDataSources;
WaapiDataSource.ObjectInfoLoaded-=OnWaapiDataLoaded;
}
public override void FetchData()
{
if (AkWaapiUtilities.IsConnected())
{
isRefreshing = true;
}
SoundBanksDataSource.FetchData();
WaapiDataSource.FetchData();
Changed();
}
private AkWwiseTreeViewItem GetCurrentWaapiParent(AkWwiseTreeViewItem Item, int index, int totalSize)
{
AkWwiseTreeViewItem currItem = Item;
var distanceFromParent = totalSize - 1 - index;
while (distanceFromParent > 0)
{
if (currItem.parent is AkWwiseTreeViewItem item)
{
currItem = item;
}
else
{
return null;
}
distanceFromParent--;
}
return currItem;
}
void AddItem(AkWwiseTreeViewItem Item)
{
var parts = Item.path.Split("\\");
var root = ProjectRoot;
int counter = 0;
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].Length == 0)
{
counter++;
continue;
}
AkWwiseTreeViewItem currentWaapiItem = GetCurrentWaapiParent(Item, i, parts.Length);
bool found = false;
foreach (var child in root.children)
{
// WG-79742: Even if the child exist, make sure that it's info is up to date, otherwise update it.
if (child.displayName == currentWaapiItem.displayName)
{
if (child is AkWwiseTreeViewItem currItem)
{
if (currItem.waapiPath != currentWaapiItem.waapiPath)
{
currItem.objectGuid = currentWaapiItem.objectGuid;
currItem.objectType = currentWaapiItem.objectType;
currItem.waapiPath = currentWaapiItem.waapiPath;
currItem.waapiName = currentWaapiItem.name;
}
}
}
if (child.displayName == parts[counter])
{
root = child as AkWwiseTreeViewItem;
found = true;
counter++;
break;
}
}
if (counter > parts.Length)
{
return;
}
if (!found)
{
break;
}
}
for (int currentItemIndex = counter; currentItemIndex < parts.Length; currentItemIndex++)
{
var Child = new AkWwiseTreeViewItem(parts[currentItemIndex], counter, 0, Guid.Empty, WwiseObjectType.Folder);
AkWwiseTreeViewItem currentWaapiItem = GetCurrentWaapiParent(Item, currentItemIndex, parts.Length);
// WG-79742: If the counter is smaller than parts.Length - 1, it means that even the new item parent(s) isn't (aren't) in the Data Source. Make sure to add the WAAPI information for the parents as well.
Child.objectGuid = currentWaapiItem.objectGuid;
Child.objectType = currentWaapiItem.objectType;
Child.path = "";
Child.waapiPath = currentWaapiItem.waapiPath;
Child.waapiName = currentWaapiItem.name;
Child.bNewInWwise = true;
Child.bNewInWwise = true;
root.AddWwiseItemChild(Child);
root = Child;
}
}
void MergeWaapiDataSource(AkWwiseTreeViewItem Item)
{
var ProjectDBObj = FindByGuid(Item.objectGuid);
if (ProjectDBObj != null && !ProjectDBObj.IsFolder())
{
ProjectDBObj.waapiName = Item.name;
ProjectDBObj.waapiPath = Item.path;
//An existing item was only moved in WAAPI.
//Due to the condition below, the parent will be flagged as having children and won't be added to the DataSource.
//In this special case, we need to directly add the parent to the DataSource
if (ProjectDBObj.parent != Item.parent)
{
if (Item.parent is AkWwiseTreeViewItem item)
{
AddItem(item);
}
}
return;
}
if (ProjectDBObj == null && !Item.hasChildren)
{
ProjectDBObj = FindByName(Item.name, Item.objectType);
if (ProjectDBObj == null)
{
AddItem(Item);
}
else
{
ProjectDBObj.waapiName = Item.name;
ProjectDBObj.waapiPath = Item.waapiPath;
ProjectDBObj.bDifferentGuid = true;
}
}
}
void UpdateIds(WwiseTreeViewItem Item, ref int Id)
{
Item.id = Id;
foreach (var child in Item.children)
{
Id++;
UpdateIds(child, ref Id);
}
}
void UpdateIds()
{
int counter = 1;
foreach (var child in ProjectRoot.children)
{
UpdateIds(child, ref counter);
counter++;
}
m_MaxID = counter;
}
public void MergeDataSources()
{
ProjectRoot = SoundBanksDataSource.ProjectRoot.Copy();
TreeUtility.TreeToList(ProjectRoot, ref Data);
foreach (var WaapiItem in WaapiDataSource.Data.ItemDict.Values)
{
MergeWaapiDataSource(WaapiItem);
}
// We do not want to sort the root object as the order is forced
ProjectRoot.isSorted = true;
foreach (var child in ProjectRoot.children)
{
(child as AkWwiseTreeViewItem).SortChildren();
}
UpdateIds();
TreeUtility.TreeToList(ProjectRoot, ref Data);
Changed();
}
public override AkWwiseTreeViewItem GetComponentDataRoot(WwiseObjectType objectType)
{
foreach (var child in ProjectRoot.children)
{
if (child.displayName == AkWwiseTreeDataSource.FolderNames[objectType])
{
var tempProjectRoot = new AkWwiseTreeViewItem(ProjectRoot);
tempProjectRoot.AddWwiseItemChild(child as AkWwiseTreeViewItem);
return tempProjectRoot;
}
}
return null;
}
protected AkWwiseTreeViewItem BuildObjectTypeTree(WwiseObjectType objectType)
{
var rootElement = new AkWwiseTreeViewItem();
switch (objectType)
{
case WwiseObjectType.AuxBus:
rootElement = BuildTree(FolderNames[WwiseObjectType.AuxBus], AkWwiseProjectInfo.GetData().BusRoot);
break;
case WwiseObjectType.Event:
rootElement = BuildTree(FolderNames[WwiseObjectType.Event], AkWwiseProjectInfo.GetData().EventRoot);
break;
case WwiseObjectType.Soundbank:
rootElement = BuildTree(FolderNames[WwiseObjectType.Soundbank], AkWwiseProjectInfo.GetData().BankRoot);
break;
case WwiseObjectType.State:
rootElement = BuildTree(FolderNames[WwiseObjectType.State], AkWwiseProjectInfo.GetData().StateRoot);
break;
case WwiseObjectType.Switch:
case WwiseObjectType.SwitchGroup:
rootElement = BuildTree(FolderNames[WwiseObjectType.Switch], AkWwiseProjectInfo.GetData().SwitchRoot);
break;
case WwiseObjectType.GameParameter:
rootElement = BuildTree(FolderNames[WwiseObjectType.GameParameter], AkWwiseProjectInfo.GetData().GameParameterRoot);
break;
case WwiseObjectType.Trigger:
rootElement = BuildTree(FolderNames[WwiseObjectType.Trigger], AkWwiseProjectInfo.GetData().TriggerRoot);
break;
case WwiseObjectType.AcousticTexture:
rootElement = BuildTree(FolderNames[WwiseObjectType.AcousticTexture], AkWwiseProjectInfo.GetData().AcousticTextureRoot);
break;
}
wwiseObjectFolders[objectType] = rootElement;
return rootElement;
}
AkWwiseTreeViewItem BuildTree(AkWwiseTreeViewItem treeViewItem, List<AkWwiseProjectData.WwiseTreeObject> childrenInfo, int depth)
{
if (childrenInfo == null)
{
return treeViewItem;
}
foreach (var children in childrenInfo)
{
var childItem = new AkWwiseTreeViewItem(children.Name, depth, GenerateUniqueID(), children.Guid, children.Type);
childItem = BuildTree(childItem, children.Children, depth++);
if (childItem != null)
{
treeViewItem.AddWwiseItemChild(childItem);
}
}
return treeViewItem;
}
public AkWwiseTreeViewItem BuildTree(string name,
List<AkWwiseProjectData.WwiseTreeObject> Events)
{
var rootFolder = new AkWwiseTreeViewItem(name, 1, GenerateUniqueID(), System.Guid.NewGuid(), WwiseObjectType.PhysicalFolder);
return BuildTree(rootFolder, Events, 1);
}
private AkWwiseTreeViewItem AddTreeItem(AkWwiseTreeViewItem parentWorkUnit, List<AkWwiseProjectData.PathElement> pathAndIcons)
{
var pathDepth = pathAndIcons.Count;
var treeDepth = pathDepth + 1;
AkWwiseTreeViewItem newItem;
AkWwiseProjectData.PathElement pathElem;
var parent = parentWorkUnit;
if (pathDepth > parentWorkUnit.depth)
{
var unaccountedDepth = pathDepth - parentWorkUnit.depth;
for (; unaccountedDepth > 0; unaccountedDepth--)
{
var pathIndex = pathAndIcons.Count - unaccountedDepth;
pathElem = pathAndIcons[pathIndex];
if (pathElem.ObjectGuid == System.Guid.Empty)
{
var path = AkWwiseProjectData.PathElement.GetProjectPathString(pathAndIcons, pathIndex);
newItem = Find(pathElem.ObjectGuid, pathElem.ElementName, path);
}
else
{
newItem = FindByGuid(pathElem.ObjectGuid);
}
if (newItem == null)
{
newItem = new AkWwiseTreeViewItem(pathElem.ElementName, treeDepth - unaccountedDepth, GenerateUniqueID(), pathElem.ObjectGuid, pathElem.ObjectType);
parent.AddWwiseItemChild(newItem);
Data.Add(newItem);
}
parent = newItem;
}
}
pathElem = pathAndIcons.Last();
newItem = FindByGuid(pathElem.ObjectGuid);
if (newItem == null)
{
newItem = new AkWwiseTreeViewItem(pathElem.ElementName, treeDepth, GenerateUniqueID(), pathElem.ObjectGuid, pathElem.ObjectType);
parent.AddWwiseItemChild(newItem);
Data.Add(newItem);
}
return newItem;
}
public AkWwiseTreeViewItem Find(System.Guid guid, string name, string path)
{
if (guid.Equals(System.Guid.Empty))
{
var results = Data.ItemDict.Values.ToList().FindAll(element => element.objectGuid == guid && element.name == name);
foreach (var r in results)
{
var itemPath = GetProjectPath(r, "");
if (itemPath == path)
{
return r;
}
}
}
else
{
return Data.ItemDict[guid];
}
return null;
}
public string GetProjectPath(AkWwiseTreeViewItem item, string currentpath)
{
currentpath = $"/{item.name}{currentpath}";
if (item.parent == null || item.parent == ProjectRoot)
{
return currentpath;
}
return GetProjectPath(item.parent as AkWwiseTreeViewItem, currentpath);
}
public override AkWwiseTreeViewItem GetSearchResults()
{
return SearchRoot;
}
public override void UpdateSearchResults(string searchString, WwiseObjectType objectType, BrowserFilter Filters)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
if (objectType != WwiseObjectType.None)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
var rootItemOfType = GetComponentDataRoot(objectType);
if (rootItemOfType != null)
{
var objectRoot = new AkWwiseTreeViewItem(rootItemOfType);
TreeUtility.CopyTree(rootItemOfType, objectRoot);
SearchRoot.AddWwiseItemChild(objectRoot);
}
}
else
{
TreeUtility.CopyTree(ProjectRoot, SearchRoot);
}
FilterTree(SearchRoot, searchString, Filters);
}
BrowserFilter GetParentFilter(AkWwiseTreeViewItem parent)
{
switch (parent.name)
{
case "Busses":
return BrowserFilter.Bus;
case "Events":
return BrowserFilter.Event;
case "Game Parameters":
return BrowserFilter.GameParameter;
case "SoundBanks":
return BrowserFilter.SoundBank;
case "States":
return BrowserFilter.State;
case "Switches":
return BrowserFilter.Switch;
case "Triggers":
return BrowserFilter.Trigger;
case "Virtual Acoustics":
return BrowserFilter.AcousticTexture;
}
return BrowserFilter.None;
}
bool IsFilteredTypes(AkWwiseTreeViewItem treeElement, BrowserFilter Filters)
{
if (treeElement.objectType == WwiseObjectType.Project)
{
return true;
}
AkWwiseTreeViewItem topElement = treeElement;
bool projectTypeFound = false;
while(!projectTypeFound)
{
AkWwiseTreeViewItem parent = (AkWwiseTreeViewItem)topElement.parent;
if (parent.objectType == WwiseObjectType.Project)
{
projectTypeFound = true;
}
else
{
topElement = parent;
}
}
BrowserFilter Expected = BrowserFilter.Bus | BrowserFilter.Event |
BrowserFilter.SoundBank | BrowserFilter.Switch
| BrowserFilter.State | BrowserFilter.GameParameter |
BrowserFilter.Trigger | BrowserFilter.AcousticTexture;
if (((ulong)Expected & (ulong)Filters) == 0)
{
return true;
}
BrowserFilter Filter = BrowserFilter.None;
switch (treeElement.objectType)
{
case WwiseObjectType.None:
Filter = BrowserFilter.None;
break;
case WwiseObjectType.AuxBus:
Filter = BrowserFilter.Bus;
break;
case WwiseObjectType.Bus:
Filter = BrowserFilter.Bus;
break;
case WwiseObjectType.Event:
Filter = BrowserFilter.Event;
break;
case WwiseObjectType.Folder:
case WwiseObjectType.WorkUnit:
Filter = GetParentFilter(topElement);
if (Filter == BrowserFilter.None || !treeElement.hasChildren)
{
return false;
}
break;
case WwiseObjectType.PhysicalFolder:
break;
case WwiseObjectType.Project:
break;
case WwiseObjectType.Soundbank:
Filter = BrowserFilter.SoundBank;
break;
case WwiseObjectType.State:
case WwiseObjectType.StateGroup: // When filtering for States we also want to include State groups.
Filter = BrowserFilter.State;
break;
case WwiseObjectType.Switch:
case WwiseObjectType.SwitchGroup: // When filtering for Switches we also want to include Switch groups.
Filter = BrowserFilter.Switch;
break;
case WwiseObjectType.GameParameter:
Filter = BrowserFilter.GameParameter;
break;
case WwiseObjectType.Trigger:
Filter = BrowserFilter.Trigger;
break;
case WwiseObjectType.AcousticTexture:
Filter = BrowserFilter.AcousticTexture;
break;
}
if (Filter == BrowserFilter.None)
{
return true;
}
return ((ulong)Filter & (ulong)Filters) != 0;
}
bool IsFilteredStatus(AkWwiseTreeViewItem treeElement, BrowserFilter Filters)
{
if (treeElement.IsFolder())
{
return true;
}
BrowserFilter Expected = BrowserFilter.SoundBanksUpToDate | BrowserFilter.NewInWwise |
BrowserFilter.DeletedInWwise | BrowserFilter.RenamedInWwise
| BrowserFilter.MovedInWwise | BrowserFilter.SoundBankNeedsUpdate;
if (((ulong)Expected & (ulong)Filters) == 0)
{
return true;
}
BrowserFilter Filter = BrowserFilter.None;
if (treeElement.IsUpToDate)
{
Filter = BrowserFilter.SoundBanksUpToDate;
}
else if (treeElement.bNewInWwise)
{
Filter = BrowserFilter.NewInWwise;
}
else if (treeElement.bDifferentGuid)
{
Filter = BrowserFilter.SoundBankNeedsUpdate;
}
else if (treeElement.IsDeletedInWwise)
{
Filter = BrowserFilter.DeletedInWwise;
}
else if (treeElement.IsRenamedInWwise)
{
Filter = BrowserFilter.RenamedInWwise;
}
else if (treeElement.IsMovedInWwise)
{
Filter = BrowserFilter.MovedInWwise;
}
if (Filter == BrowserFilter.None)
{
return true;
}
return ((ulong)Filter & (ulong)Filters) != 0;
}
bool ShouldRemove(AkWwiseTreeViewItem treeElement, BrowserFilter Filters)
{
if (Filters == BrowserFilter.None)
{
return false;
}
if (IsFilteredTypes(treeElement, Filters) && IsFilteredStatus(treeElement, Filters))
{
return false;
}
return true;
}
void FilterTree(AkWwiseTreeViewItem treeElement, string searchFilter, BrowserFilter Filters)
{
var ItemsToRemove = new List<AkWwiseTreeViewItem>();
for (int i = 0; i < treeElement.children.Count(); i++)
{
var current = treeElement.children[i] as AkWwiseTreeViewItem;
FilterTree(current, searchFilter, Filters);
if ((current.name.IndexOf(searchFilter, System.StringComparison.OrdinalIgnoreCase) == -1 && current.children.Count == 0) || ShouldRemove(current, Filters))
{
ItemsToRemove.Add(current);
}
}
for (int i = 0; i < ItemsToRemove.Count(); i++)
{
treeElement.children.Remove(ItemsToRemove[i]);
}
}
public override void SetExpanded(IEnumerable<System.Guid> ids)
{
if (TreeView != null)
{
TreeView.state.expandedIDs = GetIdsFromGuids(ids).ToList();
}
Changed();
}
public override void SaveExpansionStatus(List<int> expandedItems )
{
AkWwiseProjectInfo.GetData().ExpandedFileSystemItemIds = expandedItems;
}
public override List<int> LoadExpansionSatus()
{
return AkWwiseProjectInfo.GetData().ExpandedFileSystemItemIds;
}
public override void SetWwiseTreeView(AkWwiseTreeView treeView)
{
TreeView = treeView;
WaapiDataSource.SetWwiseTreeView(treeView);
SoundBanksDataSource.SetWwiseTreeView(treeView);
}
public override void ItemSelected(AkWwiseTreeViewItem item)
{
// WG-79742: The auto-sync selection feature do not support selecting folders that are part of the minimal structure of a Wwise Project (Just like in Unreal).
if (item.parent is AkWwiseTreeViewItem parent && parent.objectType == WwiseObjectType.Project)
{
return;
}
AkWaapiUtilities.GetStatusString(out var bConnected);
if (AkWwiseEditorSettings.Instance.AutoSyncWaapi && bConnected)
{
if (item.IsDeletedInWwise)
{
WwiseLogger.Log("Item has been deleted in Wwise. Nothing to sync in Wwise.");
return;
}
if (item.bDifferentGuid)
{
WwiseLogger.Log("Item has a different GUID in Wwise. Generate SoundBanks to sync selection.");
return;
}
WaapiDataSource.SelectObjectInAuthoring(item.objectGuid);
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fce54023ccaca2743acefe721e0ee318
@@ -0,0 +1,288 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System.Linq;
using System.Collections.Generic;
public class AkWwiseTreeProjectDataSource : AkWwiseTreeDataSource
{
public AkWwiseTreeProjectDataSource() : base()
{
WwiseProjectDatabase.SoundBankDirectoryUpdated += FetchData;
}
~AkWwiseTreeProjectDataSource()
{
WwiseProjectDatabase.SoundBankDirectoryUpdated -= FetchData;
}
public override void FetchData()
{
AkWwiseProjectInfo.GetData().Reset();
AkWwiseJSONBuilder.Populate();
Data.Clear();
m_MaxID = 0;
InitializeMinimal();
Changed();
}
protected void InitializeMinimal()
{
ProjectRoot = CreateProjectRootItem();
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.Event));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.AuxBus));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.Switch));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.State));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.GameParameter));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.Soundbank));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.Trigger));
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(WwiseObjectType.AcousticTexture));
TreeUtility.TreeToList(ProjectRoot, ref Data);
}
public override AkWwiseTreeViewItem GetComponentDataRoot(WwiseObjectType objectType)
{
if (!wwiseObjectFolders.ContainsKey(objectType))
ProjectRoot.AddWwiseItemChild(BuildObjectTypeTree(objectType));
var tempProjectRoot = new AkWwiseTreeViewItem(ProjectRoot);
tempProjectRoot.AddWwiseItemChild(wwiseObjectFolders[objectType]);
return tempProjectRoot;
}
virtual protected AkWwiseTreeViewItem BuildObjectTypeTree(WwiseObjectType objectType)
{
var rootElement = new AkWwiseTreeViewItem();
switch (objectType)
{
case WwiseObjectType.AuxBus:
rootElement = BuildTree(FolderNames[WwiseObjectType.AuxBus], AkWwiseProjectInfo.GetData().BusRoot);
break;
case WwiseObjectType.Event:
rootElement = BuildTree(FolderNames[WwiseObjectType.Event], AkWwiseProjectInfo.GetData().EventRoot);
break;
case WwiseObjectType.Soundbank:
rootElement = BuildTree(FolderNames[WwiseObjectType.Soundbank], AkWwiseProjectInfo.GetData().BankRoot);
break;
case WwiseObjectType.State:
rootElement = BuildTree(FolderNames[WwiseObjectType.State], AkWwiseProjectInfo.GetData().StateRoot);
break;
case WwiseObjectType.Switch:
case WwiseObjectType.SwitchGroup:
rootElement = BuildTree(FolderNames[WwiseObjectType.Switch], AkWwiseProjectInfo.GetData().SwitchRoot);
break;
case WwiseObjectType.GameParameter:
rootElement = BuildTree(FolderNames[WwiseObjectType.GameParameter], AkWwiseProjectInfo.GetData().GameParameterRoot);
break;
case WwiseObjectType.Trigger:
rootElement = BuildTree(FolderNames[WwiseObjectType.Trigger], AkWwiseProjectInfo.GetData().TriggerRoot);
break;
case WwiseObjectType.AcousticTexture:
rootElement = BuildTree(FolderNames[WwiseObjectType.AcousticTexture], AkWwiseProjectInfo.GetData().AcousticTextureRoot);
break;
}
wwiseObjectFolders[objectType] = rootElement;
return rootElement;
}
AkWwiseTreeViewItem BuildTree(AkWwiseTreeViewItem treeViewItem, List<AkWwiseProjectData.WwiseTreeObject> childrenInfo, int depth)
{
if (childrenInfo == null)
{
return treeViewItem;
}
foreach (var children in childrenInfo)
{
var childItem = new AkWwiseTreeViewItem(children.Name, depth, GenerateUniqueID(), children.Guid, children.Type);
childItem.path = children.Path;
childItem = BuildTree(childItem, children.Children, depth++);
if (childItem != null)
{
treeViewItem.AddWwiseItemChild(childItem);
}
}
return treeViewItem;
}
public AkWwiseTreeViewItem BuildTree(string name,
List<AkWwiseProjectData.WwiseTreeObject> wwiseTreeObjects)
{
var rootFolder = new AkWwiseTreeViewItem(name, 1, GenerateUniqueID(), new System.Guid(), WwiseObjectType.PhysicalFolder);
return BuildTree(rootFolder, wwiseTreeObjects, 1);
}
private AkWwiseTreeViewItem AddTreeItem(AkWwiseTreeViewItem parentWorkUnit, List<AkWwiseProjectData.PathElement> pathAndIcons)
{
var pathDepth = pathAndIcons.Count;
var treeDepth = pathDepth + 1;
AkWwiseTreeViewItem newItem;
AkWwiseProjectData.PathElement pathElem;
var parent = parentWorkUnit;
if (pathDepth > parentWorkUnit.depth)
{
var unaccountedDepth = pathDepth - parentWorkUnit.depth;
for (; unaccountedDepth > 0; unaccountedDepth--)
{
var pathIndex = pathAndIcons.Count - unaccountedDepth;
pathElem = pathAndIcons[pathIndex];
if (pathElem.ObjectGuid == System.Guid.Empty)
{
var path = AkWwiseProjectData.PathElement.GetProjectPathString(pathAndIcons, pathIndex);
newItem = Find(pathElem.ObjectGuid, pathElem.ElementName, path);
}
else
{
newItem = FindByGuid(pathElem.ObjectGuid);
}
if (newItem == null)
{
newItem = new AkWwiseTreeViewItem(pathElem.ElementName, treeDepth - unaccountedDepth, GenerateUniqueID(), pathElem.ObjectGuid, pathElem.ObjectType);
newItem.path = pathElem.ToString();
parent.AddWwiseItemChild(newItem);
Data.Add(newItem);
}
parent = newItem;
}
}
pathElem = pathAndIcons.Last();
newItem = FindByGuid(pathElem.ObjectGuid);
if (newItem == null)
{
newItem = new AkWwiseTreeViewItem(pathElem.ElementName, treeDepth, GenerateUniqueID(), pathElem.ObjectGuid, pathElem.ObjectType);
newItem.path = pathElem.ToString();
parent.AddWwiseItemChild(newItem);
Data.Add(newItem);
}
return newItem;
}
public AkWwiseTreeViewItem Find(System.Guid guid, string name, string path)
{
if (guid.Equals(System.Guid.Empty))
{
var results = Data.ItemDict.Values.ToList().FindAll(element => element.objectGuid == guid && element.name == name);
foreach (var r in results)
{
var itemPath = GetProjectPath(r, "");
if (itemPath == path)
{
return r;
}
}
}
else
{
return Data.ItemDict[guid];
}
return null;
}
public string GetProjectPath(AkWwiseTreeViewItem item, string currentpath)
{
currentpath = $"/{item.name}{currentpath}";
if (item.parent == null || item.parent == ProjectRoot)
{
return currentpath;
}
return GetProjectPath(item.parent as AkWwiseTreeViewItem, currentpath);
}
public override AkWwiseTreeViewItem GetSearchResults()
{
return SearchRoot;
}
public override void UpdateSearchResults(string searchString, WwiseObjectType objectType, BrowserFilter Filters)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
if (objectType != WwiseObjectType.None)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
var objectRoot = new AkWwiseTreeViewItem(wwiseObjectFolders[objectType]);
TreeUtility.CopyTree(wwiseObjectFolders[objectType], objectRoot);
SearchRoot.AddWwiseItemChild(objectRoot);
}
else
{
TreeUtility.CopyTree(ProjectRoot, SearchRoot);
}
FilterTree(SearchRoot, searchString);
}
void FilterTree(AkWwiseTreeViewItem treeElement, string searchFilter)
{
var ItemsToRemove = new List<AkWwiseTreeViewItem>();
for (int i = 0; i < treeElement.children.Count(); i++)
{
var current = treeElement.children[i] as AkWwiseTreeViewItem;
FilterTree(current, searchFilter);
if (current.name.IndexOf(searchFilter, System.StringComparison.OrdinalIgnoreCase) == -1 && current.children.Count == 0)
{
ItemsToRemove.Add(current);
}
}
for (int i = 0; i < ItemsToRemove.Count(); i++)
{
treeElement.children.Remove(ItemsToRemove[i]);
}
}
public override void SetExpanded(IEnumerable<System.Guid> ids)
{
if (TreeView != null)
{
TreeView.state.expandedIDs = GetIdsFromGuids(ids).ToList();
}
Changed();
}
public override void SaveExpansionStatus(List<int> expandedItems )
{
AkWwiseProjectInfo.GetData().ExpandedFileSystemItemIds = expandedItems;
}
public override List<int> LoadExpansionSatus()
{
return AkWwiseProjectInfo.GetData().ExpandedFileSystemItemIds;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a5779afe3143d204cbc6b45cad1e354a
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 95a1c911f0668f04f8fcd462a96884fd
@@ -0,0 +1,307 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System.Linq;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
#else
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem;
#endif
public class AkWwiseTreeViewItem : WwiseTreeViewItem, System.IEquatable<AkWwiseTreeViewItem>
{
public bool IsUpToDate
{
get
{
if (objectType == WwiseObjectType.Soundbank)
{
return displayName == waapiName && !bNewInWwise && !bDifferentGuid;
}
return waapiPath == path && displayName == waapiName && !bNewInWwise && !bDifferentGuid;
}
}
public bool IsFolder()
{
return objectType == WwiseObjectType.Folder || objectType == WwiseObjectType.PhysicalFolder || objectType == WwiseObjectType.WorkUnit;
}
public string status
{
get
{
if (IsFolder() || !AkWaapiUtilities.IsConnected())
{
return "";
}
if (IsUpToDate)
{
return "SoundBank Up to Date";
}
if (IsDeletedInWwise)
{
return "Deleted in Wwise";
}
if (bNewInWwise)
{
return "New in Wwise";
}
if (IsRenamedInWwise)
{
return "Renamed in Wwise";
}
if (IsMovedInWwise)
{
return "Moved in Wwise";
}
if (bDifferentGuid)
{
return "SoundBank needs Update";
}
return "";
}
}
public bool IsMovedInWwise
{
get { return waapiPath != path; }
}
public bool IsDeletedInWwise
{
get { return waapiName.Length == 0; }
}
public bool IsRenamedInWwise
{
get { return waapiName != name; }
}
static public GUIStyle OutOfDateStyle
{
get
{
var style = new GUIStyle();
style.normal.textColor = new Color(1, 0.33f, 0);
return style;
}
}
public System.Guid objectGuid;
public WwiseObjectType objectType;
public int numChildren;
public bool isSorted;
public string path = "";
public string waapiPath = "";
public string waapiName = "";
public bool bNewInWwise = false;
public bool bDifferentGuid = false;
public string name
{
get { return displayName; }
set {
displayName = value;
if (parent != null)
{
(parent as AkWwiseTreeViewItem).SortChildren();
}
}
}
private int m_depth;
public override int depth
{
get { return m_depth; }
set {
m_depth= value;
if (children != null)
{
foreach (var child in this.children)
{
if (child != null && child.depth != depth + 1)
child.depth = depth + 1;
}
}
}
}
public AkWwiseTreeViewItem(WwiseObjectInfo info, int id, int depth) : base(id, depth, info.name)
{
objectGuid = info.objectGUID;
objectType = info.type;
numChildren = info.childrenCount;
path = info.path;
waapiPath = info.path;
if (objectType == WwiseObjectType.Event)
{
numChildren = 0;
}
children = new List<WwiseTreeViewItem>();
this.depth = depth;
}
public AkWwiseTreeViewItem(string displayName, int depth, int id, System.Guid objGuid, WwiseObjectType objType) : base(id, depth, displayName)
{
objectGuid = objGuid;
objectType = objType;
children = new List<WwiseTreeViewItem>();
this.depth = depth;
}
public AkWwiseTreeViewItem()
{
objectGuid = System.Guid.Empty;
objectType = WwiseObjectType.None;
children = new List<WwiseTreeViewItem>();
}
public AkWwiseTreeViewItem(AkWwiseTreeViewItem other) : base(other.id, other.depth, other.displayName)
{
objectGuid = other.objectGuid;
objectType = other.objectType;
path = other.path;
waapiPath = other.waapiPath;
waapiName = other.waapiName;
bDifferentGuid = other.bDifferentGuid;
bNewInWwise = other.bNewInWwise;
children = new List<WwiseTreeViewItem>();
this.depth = other.depth;
}
public bool Equals(AkWwiseTreeViewItem other)
{
return objectGuid == other.objectGuid && displayName == other.displayName && objectType == other.objectType;
}
public void AddWwiseItemChild(AkWwiseTreeViewItem child)
{
child.depth = this.depth + 1;
child.parent = this;
children.Add(child);
isSorted = false;
numChildren = children.Count;
}
public void SortChildren()
{
children.Sort();
isSorted = true;
}
public override int CompareTo(WwiseTreeViewItem B)
{
return CompareTo(this, B as AkWwiseTreeViewItem);
}
public int CompareTo(AkWwiseTreeViewItem A, AkWwiseTreeViewItem B)
{
// Items are sorted like so:
// 1- Physical folders, sorted alphabetically
// 1- WorkUnits, sorted alphabetically (with default work unit first)
// 2- Virtual folders, sorted alphabetically
// 3- Normal items, sorted alphabetically
if (A.objectType == B.objectType)
{
if (A.objectType == WwiseObjectType.WorkUnit)
{
if (A.displayName == "Default Work Unit")
return -1;
else if (B.displayName == "Default Work Unit")
return 1;
}
return string.Compare(A.displayName, B.displayName, System.StringComparison.OrdinalIgnoreCase);
}
else if (A.objectType == WwiseObjectType.PhysicalFolder)
{
return -1;
}
else if (B.objectType == WwiseObjectType.PhysicalFolder)
{
return 1;
}
else if (A.objectType == WwiseObjectType.WorkUnit || A.objectType == WwiseObjectType.WorkUnit)
{
return -1;
}
else if (B.objectType == WwiseObjectType.WorkUnit || B.objectType == WwiseObjectType.WorkUnit)
{
return 1;
}
else if (A.objectType == WwiseObjectType.Folder)
{
return -1;
}
else if (B.objectType == WwiseObjectType.Folder)
{
return 1;
}
else if (A.objectType == WwiseObjectType.Bus || B.objectType == WwiseObjectType.AuxBus)
{
return -1;
}
else if (A.objectType == WwiseObjectType.AuxBus || B.objectType == WwiseObjectType.Bus)
{
return 1;
}
else
{
return 1;
}
}
public bool WwiseTypeInChildren(WwiseObjectType t)
{
if (this.objectType == t) return true;
if (!hasChildren)
{
return false;
}
foreach (var child in children)
{
if ((child as AkWwiseTreeViewItem).WwiseTypeInChildren(t)) return true;
}
return false;
}
public AkWwiseTreeViewItem Copy()
{
AkWwiseTreeViewItem copy = new AkWwiseTreeViewItem(this);
foreach (var child in children)
{
copy.AddWwiseItemChild((child as AkWwiseTreeViewItem).Copy());
}
return copy;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 410863fd5a70f0e41bb3adf7e3fbeb83
@@ -0,0 +1,858 @@
#if UNITY_EDITOR
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using UnityEditor.IMGUI.Controls;
using AK.Wwise.Unity.Logging;
#if UNITY_6000_2_OR_NEWER
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState<int>;
#else
using WwiseTreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem;
using WwiseTreeViewState = UnityEditor.IMGUI.Controls.TreeViewState;
#endif
/// <summary>
/// This class communicates with Wwise Authoring via AkWaapiUtilities to keep track of the Wwise object hierarchy in the project.
/// This hierarchy information is stored in a tree structure and is used by the Wwise Picker when it is in WAAPI mode.
/// Changes to the project are received via WAAPI subscriptions.
/// </summary>
public class AkWwiseTreeWAAPIDataSource : AkWwiseTreeDataSource
{
private System.Timers.Timer selectTimer;
private System.Timers.Timer searchTimer;
private int counter = 0;
public System.Action ObjectInfoLoaded;
private ReturnOptions waapiWwiseObjectOptions =
new ReturnOptions(new string[] { "id", "name", "type", "childrenCount", "path", "workunitType", "parent" });
public bool WaitingForSearchResults;
public AkWwiseTreeWAAPIDataSource() : base()
{
Connect();
selectTimer = new System.Timers.Timer();
selectTimer.Interval = 200;
selectTimer.AutoReset = false;
selectTimer.Elapsed += FireSelect;
searchTimer = new System.Timers.Timer();
searchTimer.Interval = 200;
searchTimer.AutoReset = false;
searchTimer.Elapsed += FireSearch;
}
public override void FetchData()
{
Data.Clear();
m_MaxID = 0;
ProjectRoot = CreateProjectRootItem();
counter = 0;
foreach (var type in FolderNames.Keys)
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
AddBaseFolder(AkWaapiUtilities.ParseObjectInfo(items), type);
counter++;
if (counter >= FolderNames.Count)
{
ObjectInfoLoaded?.Invoke();
counter = 0;
}
};
AkWaapiUtilities.GetWwiseObjectAndDescendants("\\" + FolderNames[type], waapiWwiseObjectOptions, -1, callback);
}
Changed();
}
public override AkWwiseTreeViewItem GetComponentDataRoot(WwiseObjectType objectType)
{
var tempProjectRoot = new AkWwiseTreeViewItem(ProjectRoot);
if (!wwiseObjectFolders.ContainsKey(objectType))
{
return tempProjectRoot;
}
tempProjectRoot.AddWwiseItemChild(wwiseObjectFolders[objectType]);
return tempProjectRoot;
}
WwiseObjectType componentObjectType;
public override void LoadComponentData(WwiseObjectType objectType)
{
componentObjectType = objectType;
LoadComponentDataDelayed();
}
public void LoadComponentDataDelayed()
{
//Delay call until data has been fetched
if (!wwiseObjectFolders.ContainsKey(componentObjectType))
{
UnityEditor.EditorApplication.delayCall += LoadComponentDataDelayed;
}
else
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
AddItems(AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetWwiseObjectAndDescendants(wwiseObjectFolders[componentObjectType].objectGuid,
waapiWwiseObjectOptions, -1, callback);
}
}
private string searchString;
private WwiseObjectType searchObjectTypeFilter;
public override void UpdateSearchResults(string searchFilter, WwiseObjectType objectType = WwiseObjectType.None, BrowserFilter Filters = BrowserFilter.None)
{
searchTimer.Stop();
searchString = searchFilter;
searchObjectTypeFilter = objectType;
searchTimer.Enabled = true;
searchTimer.Start();
}
private void FireSearch(object sender, System.Timers.ElapsedEventArgs e)
{
if (WaitingForSearchResults) return;
if (SearchRoot == null)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
}
SearchRoot.children.Clear();
SearchData = new TreeItems();
TreeUtility.TreeToList(SearchRoot, ref SearchData);
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
AddSearchResults(AkWaapiUtilities.ParseObjectInfo(items));
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Expand(SearchRoot.objectGuid, false)));
WaitingForSearchResults = false;
};
AkWaapiUtilities.Search(searchString, searchObjectTypeFilter, waapiWwiseObjectOptions, callback);
WaitingForSearchResults = true;
}
public override AkWwiseTreeViewItem GetSearchResults()
{
if (SearchRoot == null)
{
SearchRoot = new AkWwiseTreeViewItem(ProjectRoot);
}
return SearchRoot;
}
public void AddSearchResults(IEnumerable<WwiseObjectInfo> matchList)
{
try
{
foreach (var info in matchList)
{
if (!FilterPath(info.path))
{
continue;
}
var match = FindInSearchResults(info.objectGUID);
if (match != null)
{
continue;
}
var matchItem = FindByGuid(info.objectGUID);
if (matchItem == null)
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
AddItemWithAncestorsToSearch(AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetWwiseObjectAndAncestors(info.objectGUID, waapiWwiseObjectOptions, callback);
continue;
}
AddItemToSearch(matchItem);
}
}
catch (System.Exception e)
{
WwiseLogger.Error("Search died");
WwiseLogger.Error(e.Message);
}
}
private void AddItemToSearch(AkWwiseTreeViewItem sourceItem)
{
var matchItem = new AkWwiseTreeViewItem(sourceItem);
SearchData.Add(matchItem);
var sourceParent = sourceItem.parent as AkWwiseTreeViewItem;
var parentCopy = FindInSearchResults(sourceParent.objectGuid);
if (parentCopy != null)
{
parentCopy.AddWwiseItemChild(matchItem);
return;
}
else
{
parentCopy = new AkWwiseTreeViewItem(sourceParent);
parentCopy.AddWwiseItemChild(matchItem);
SearchData.Add(parentCopy);
var nextParent = sourceParent.parent as AkWwiseTreeViewItem;
while (nextParent != null)
{
var parentInSearchItems = FindInSearchResults(nextParent.objectGuid);
if (parentInSearchItems != null)
{
parentInSearchItems.AddWwiseItemChild(parentCopy);
break;
}
parentInSearchItems = new AkWwiseTreeViewItem(nextParent);
parentInSearchItems.AddWwiseItemChild(parentCopy);
SearchData.Add(parentInSearchItems);
parentCopy = parentInSearchItems;
nextParent = nextParent.parent as AkWwiseTreeViewItem;
}
}
}
public void AddItemWithAncestors(List<WwiseObjectInfo> infoItems, bool selectAfterCreated = false)
{
var parent = ProjectRoot;
//Items obtained from the WAAPI call are sorted by path so we can simply iterate over them
foreach (var infoItem in infoItems)
{
var newItem = FindByGuid(infoItem.objectGUID);
if (newItem == null)
{
newItem = new AkWwiseTreeViewItem(infoItem, GenerateUniqueID(), parent.depth + 1);
Data.Add(newItem);
parent.AddWwiseItemChild(newItem);
}
if (!CheckIfFullyLoaded(parent))
{
System.Guid guid = new System.Guid(parent.objectGuid.ToString());
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
UpdateParentWithLoadedChildren(guid, AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetChildren(parent.objectGuid, waapiWwiseObjectOptions, callback);
}
parent = newItem;
}
if (selectAfterCreated)
{
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Expand(parent.objectGuid, true)));
}
}
public void AddItemWithAncestorsToSearch(List<WwiseObjectInfo> infoItems)
{
AddItemWithAncestors(infoItems, false);
var item = FindByGuid(infoItems.Last().objectGUID);
AddItemToSearch(item);
}
public void AddItems(List<WwiseObjectInfo> infoItems)
{
foreach (var infoItem in infoItems)
{
if (infoItem.type == WwiseObjectType.None)
{
continue;
}
var tParent = FindByGuid(infoItem.parentID);
if (tParent == null || tParent == ProjectRoot)
{
tParent = ProjectRoot;
}
var tChild = FindByGuid(infoItem.objectGUID);
if (tChild == null)
{
tChild = new AkWwiseTreeViewItem(infoItem, GenerateUniqueID(), tParent.depth + 1);
Data.Add(tChild);
tParent.AddWwiseItemChild(tChild);
}
}
}
public void AddBaseFolder(List<WwiseObjectInfo> infoItems, WwiseObjectType oType)
{
if (infoItems != null && infoItems.Count > 0)
{
AddItems(infoItems);
var folder = FindByGuid(infoItems[0].objectGUID);
wwiseObjectFolders[oType] = folder;
}
}
public void UpdateParentWithLoadedChildren(System.Guid parentGuid, List<WwiseObjectInfo> children)
{
if (children == null)
{
return;
}
var parent = FindByGuid(parentGuid);
if (parent == null)
{
return;
}
parent.children.Remove(null);
parent.numChildren = children.Count;
if (parent.children.Count > children.Count)
{
parent.children.Clear();
}
foreach (var child in children)
{
if (parent.children.Any(c => ((AkWwiseTreeViewItem)c).objectGuid == child.objectGUID))
continue;
else
parent.AddWwiseItemChild(new AkWwiseTreeViewItem(child, GenerateUniqueID(), parent.depth + 1));
}
}
public void SetChildren(System.Guid parentGuid, List<WwiseObjectInfo> children)
{
if (children == null)
{
return;
}
var parent = FindByGuid(parentGuid);
parent.children.Clear();
parent.children.Remove(null);
parent.numChildren = children.Count;
foreach (var child in children)
{
parent.AddWwiseItemChild(new AkWwiseTreeViewItem(child, GenerateUniqueID(), parent.depth + 1));
}
}
bool CheckIfFullyLoaded(AkWwiseTreeViewItem item)
{
if (item == ProjectRoot)
{
return true;
}
if (item.objectType == WwiseObjectType.Event)
{
return true;
}
if (item.numChildren != item.children.Count)
{
return false;
}
if (item.children.Contains(null))
{
return false;
}
return true;
}
static List<AkWaapiUtilities.SubscriptionInfo> subscriptions = new List<AkWaapiUtilities.SubscriptionInfo>();
/// <summary>
/// Subscribes to nameChanged, childAdded, childRemoved, and selectionChanged WAAPI events in order to keep the picker in sync with the Wwise project explorer.
/// </summary>
public void SubscribeTopics()
{
var options = new ReturnOptions(new string[] { "id", "parent", "name", "type", "childrenCount", "path", "workunitType" });
AkWaapiUtilities.Subscribe(ak.wwise.core.@object.structureChanged, OnWaapiStructureChanged, SubscriptionHandshake, options);
AkWaapiUtilities.Subscribe(ak.wwise.ui.selectionChanged, OnWwiseSelectionChanged, SubscriptionHandshake, options);
}
public void SubscriptionHandshake(AkWaapiUtilities.SubscriptionInfo sub)
{
subscriptions.Add(sub);
}
/// <summary>
/// Unsubscribes from currently active subscriptions.
/// </summary>
void UnsubscribeTopics()
{
var tSubs = subscriptions;
foreach (var sub in tSubs)
{
if (sub.SubscriptionId != 0)
{
AkWaapiUtilities.Unsubscribe(sub.SubscriptionId);
}
}
subscriptions.Clear();
}
void OnWaapiRenamed(string json)
{
var renamedItem = AkWaapiUtilities.ParseRenameObject(json);
//An object was added. This will be handled in OnWaapiChildAdded
if (renamedItem.newName == renamedItem.objectInfo.path)
{
return;
}
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Rename(renamedItem.objectInfo.objectGUID, renamedItem.newName, renamedItem.objectInfo.path)));
}
class WwiseStructureChangeRenameInfo : System.IComparable
{
public WwiseObjectInfoJsonObject @object;
public string newName;
public int CompareTo(object obj)
{
if (obj is WwiseStructureChangeRenameInfo)
{
return @object.CompareTo((obj as WwiseStructureChangeRenameInfo).@object);
}
return 0;
}
}
class WwiseStructureChangeMoveInfo : System.IComparable
{
public WwiseObjectInfoJsonObject @object;
public WwiseObjectInfoJsonObject oldParent;
public WwiseObjectInfoJsonObject newParent;
public int CompareTo(object obj)
{
if (obj is WwiseStructureChangeMoveInfo)
{
return @object.CompareTo((obj as WwiseStructureChangeMoveInfo).@object);
}
return 0;
}
}
void OnWaapiStructureChanged(string json)
{
List<WwiseObjectInfoJsonObject> createOperations = new List<WwiseObjectInfoJsonObject>();
List<WwiseStructureChangeRenameInfo> renameOperations = new List<WwiseStructureChangeRenameInfo>();
List<WwiseStructureChangeMoveInfo> moveOperations = new List<WwiseStructureChangeMoveInfo>();
var changes = AkWaapiUtilities.ParseStructureChange(json);
foreach (var change in changes)
{
foreach (var operation in change.changes)
{
if (operation.type == "create")
{
createOperations.Add(change.@object);
}
if (operation.type == "nameChange")
{
renameOperations.Add(new WwiseStructureChangeRenameInfo { @object = change.@object, newName = operation.nameChange.newName });
}
if (operation.type == "parentChange")
{
moveOperations.Add(new WwiseStructureChangeMoveInfo { @object = change.@object, oldParent = operation.parentChange.oldParent, newParent = operation.parentChange.newParent});
}
}
}
createOperations.Sort();
renameOperations.Sort();
moveOperations.Sort();
foreach (var moveOp in moveOperations)
{
OnWaapiMoved(moveOp.@object, moveOp.oldParent, moveOp.newParent);
}
foreach (var createOp in createOperations)
{
OnWaapiChildAdded(createOp);
}
foreach (var renameOp in renameOperations)
{
OnWaapiRenamed(renameOp.@object, renameOp.newName);
}
ScheduleRebuild();
}
void OnWaapiChildAdded(WwiseObjectInfoJsonObject jsonInfo)
{
WwiseObjectInfo info = WwiseObjectInfoJsonObject.ToObjectInfo(jsonInfo);
if (info.type == WwiseObjectType.None)
return;
var parent = FindByGuid(info.parentID);
// New object created, but parent is not loaded yet, so we can ignore it
if (parent == null)
{
return;
}
var child = FindByGuid(info.objectGUID);
if (child == null)
{
child = new AkWwiseTreeViewItem(info, GenerateUniqueID(), parent.depth + 1);
}
else
{
child.numChildren = info.childrenCount;
child.displayName = info.name;
}
child.path = info.path;
child.waapiPath = info.path;
child.waapiName = info.name;
child.objectGuid = info.objectGUID;
parent.AddWwiseItemChild(child);
Data.Add(child);
child.depth = parent.depth + 1;
if (!CheckIfFullyLoaded(parent))
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
UpdateParentWithLoadedChildren(parent.objectGuid, AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetChildren(parent.objectGuid, waapiWwiseObjectOptions, callback);
}
if (!CheckIfFullyLoaded(child))
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
UpdateParentWithLoadedChildren(child.objectGuid, AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetChildren(child.objectGuid, waapiWwiseObjectOptions, callback);
}
}
void OnWaapiRenamed(WwiseObjectInfoJsonObject jsonInfo, string newName)
{
WwiseObjectInfo info = WwiseObjectInfoJsonObject.ToObjectInfo(jsonInfo);
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Rename(info.objectGUID, newName, info.path)));
}
void OnWaapiMoved(WwiseObjectInfoJsonObject jsonInfo, WwiseObjectInfoJsonObject oldParentJson, WwiseObjectInfoJsonObject newParentJson)
{
WwiseObjectInfo info = WwiseObjectInfoJsonObject.ToObjectInfo(jsonInfo);
WwiseObjectInfo oldParentInfo = WwiseObjectInfoJsonObject.ToObjectInfo(oldParentJson);
WwiseObjectInfo newParentInfo = WwiseObjectInfoJsonObject.ToObjectInfo(newParentJson);
var child = FindByGuid(info.objectGUID);
if (child == null)
{
return;
}
var oldParent = FindByGuid(oldParentInfo.objectGUID);
AkWwiseTreeViewItem newParent = null;
if (newParentInfo.objectGUID != System.Guid.Empty)
{
newParent = FindByGuid(newParentInfo.objectGUID);
}
if (oldParent != null)
{
oldParent.children.Remove(child);
Data.Remove(child);
oldParent.numChildren--;
}
//If newParent is null, it means the item was deleted.
if (newParent != null)
{
newParent.AddWwiseItemChild(child);
child.path = newParent.path + "\\" + child.name;
Data.Add(child);
}
}
void OnWwiseSelectionChanged(string json)
{
if (AkWwiseEditorSettings.Instance.AutoSyncWaapi)
{
var objects = AkWaapiUtilities.ParseSelectedObjects(json);
if (objects.Count > 0)
{
if (FilterPath(objects[0].path))
{
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => SelectItem(objects[0].objectGUID)));
}
}
}
}
public void Rename(System.Guid objectGuid, string newName, string newPath)
{
var item = FindByGuid(objectGuid);
if (item != null)
{
item.name = newName;
item.path = newPath;
item.waapiPath = newPath;
}
else
{
toRequeue.Enqueue(new TreeViewCommand(() => Rename(objectGuid, newName, newPath)));
}
ScheduleRebuild();
}
public void Expand(System.Guid objectGuid, bool select)
{
if (TreeView == null || !TreeView.ExpandItem(objectGuid, select))
{
toRequeue.Enqueue(new TreeViewCommand(() => Expand(objectGuid, select)));
}
}
public override void SelectItem(System.Guid itemGuid)
{
if (TreeView == null)
{
return;
}
if (TreeView.m_storedSearchString != string.Empty)
{
return;
}
if (!TreeView.ExpandItem(itemGuid, true))
{
var item = FindByGuid(itemGuid);
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Expand(itemGuid, true)));
if (item == null)
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
AddItemWithAncestors(AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetWwiseObjectAndAncestors(itemGuid, waapiWwiseObjectOptions, callback);
}
}
}
public bool FilterPath(string path)
{
var splitpath = path.Split('\\');
if (splitpath.Length > 1)
{
var folder = splitpath[1];
if (FolderNames.Values.Contains(folder) || WaapiKeywords.FolderDisplaynames.Values.Contains(folder))
{
return true;
}
}
return false;
}
public override void ItemSelected(AkWwiseTreeViewItem item)
{
if (AkWwiseEditorSettings.Instance.AutoSyncWaapi)
{
SelectObjectInAuthoring(item.objectGuid);
}
}
private System.Guid guidToSelect;
public override void SelectObjectInAuthoring(System.Guid objectGuid)
{
selectTimer.Stop();
guidToSelect = objectGuid;
selectTimer.Enabled = true;
selectTimer.Start();
}
private void FireSelect(object sender, System.Timers.ElapsedEventArgs e)
{
AkWaapiUtilities.SelectObjectInAuthoring(guidToSelect);
}
//Make a single command queue
private ConcurrentQueue<TreeViewCommand> treeviewCommandQueue = new ConcurrentQueue<TreeViewCommand>();
private Queue<TreeViewCommand> toRequeue = new Queue<TreeViewCommand>();
public class TreeViewCommand
{
public System.Action payload;
public TreeViewCommand(System.Action payload)
{
this.payload = payload;
}
public void Execute()
{
payload.Invoke();
}
}
public override void ScheduleRebuild()
{
rebuildFlag = true;
}
private bool rebuildFlag = false;
private bool refreshFlag = false;
public void Update()
{
while (treeviewCommandQueue.Count > 0)
{
if (treeviewCommandQueue.TryDequeue(out TreeViewCommand cmd))
{
cmd.Execute();
refreshFlag = true;
}
}
while (toRequeue.Count > 0)
{
treeviewCommandQueue.Enqueue(toRequeue.Dequeue());
}
//Preemptively load items in hierarchy that are close to being exposed ( up to grandchildren of unexpanded items)
if (rebuildFlag)
{
TreeUtility.TreeToList(ProjectRoot, ref Data);
refreshFlag = true;
rebuildFlag = false;
}
//Updates treeView data and sets repaint flag
if (refreshFlag)
{
Changed();
refreshFlag = false;
}
}
void Preload(AkWwiseTreeViewItem parent, WwiseTreeViewState treeState)
{
if (parent == null)
{
return;
}
if (!CheckIfFullyLoaded(parent))
{
AkWaapiUtilities.GetResultListDelegate<WwiseObjectInfoJsonObject> callback = (List<WwiseObjectInfoJsonObject> items) =>
{
UpdateParentWithLoadedChildren(parent.objectGuid, AkWaapiUtilities.ParseObjectInfo(items));
};
AkWaapiUtilities.GetChildren(parent.objectGuid, waapiWwiseObjectOptions, callback);
}
//Preload one level of hidden items.
if (IsExpanded(treeState, parent.id) || (parent.parent != null && IsExpanded(treeState, parent.parent.id)) ||
parent.id == ProjectRoot.id )
{
foreach (AkWwiseTreeViewItem childItem in parent.children)
{
Preload(childItem, treeState);
}
}
}
public override void SetExpanded(IEnumerable<System.Guid> ids)
{
if (TreeView != null)
{
foreach (var id in ids)
{
treeviewCommandQueue.Enqueue(new TreeViewCommand(() => Expand(id, false)));
}
TreeView.state.expandedIDs.Clear();
}
}
public void Connect()
{
AkWaapiUtilities.Connected += OnConnection;
AkWaapiUtilities.QueueConsumed += ScheduleRebuild;
AkWaapiUtilities.Disconnecting += Disconnect;
}
public void OnConnection()
{
SubscribeTopics();
FetchData();
}
public void Disconnect(bool still_connected)
{
this.treeviewCommandQueue = new ConcurrentQueue<TreeViewCommand>();
if (ProjectRoot != null)
ProjectRoot.children = new List<WwiseTreeViewItem>();
if (still_connected)
{
UnsubscribeTopics();
}
else
{
subscriptions.Clear();
}
Changed();
}
public void Cleanup()
{
subscriptions.Clear();
}
~AkWwiseTreeWAAPIDataSource()
{
Disconnect(true);
}
public override void SaveExpansionStatus(List<int> expandedItems)
{
AkWwiseProjectInfo.GetData().ExpandedWaapiItemIds = expandedItems;
}
public override List<int> LoadExpansionSatus()
{
return AkWwiseProjectInfo.GetData().ExpandedWaapiItemIds;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 48a0aa7a6dfcfb14ba99a2b28f77b64c
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,117 @@
fileFormatVersion: 2
guid: 6cb0098dba264bb4e9a1327d82922f95
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c43301f5a03706f4a86ee6ad26867f18
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

@@ -0,0 +1,117 @@
fileFormatVersion: 2
guid: ebf668890a31b774491fe33dd00e7e4e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

@@ -0,0 +1,117 @@
fileFormatVersion: 2
guid: bfc3a6e7cf015034ba72712fb40318f0
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 23c64ffc5d19bb4498162b6767785ced
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

@@ -0,0 +1,117 @@
fileFormatVersion: 2
guid: 435768b79245f294eb213d510f16cc40
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More