947 lines
32 KiB
C#
947 lines
32 KiB
C#
#if UNITY_EDITOR
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2014 Audiokinetic Inc. / All Rights Reserved
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma warning disable 0168
|
|
[UnityEditor.InitializeOnLoad]
|
|
public class AkWwiseWWUBuilder
|
|
{
|
|
private const string s_progTitle = "Populating Wwise Picker";
|
|
private const int s_SecondsBetweenChecks = 3;
|
|
|
|
private static string s_wwiseProjectPath = System.IO.Path.GetDirectoryName(AkWwiseEditorSettings.WwiseProjectAbsolutePath);
|
|
|
|
private static System.DateTime s_lastFileCheck = System.DateTime.Now.AddSeconds(-s_SecondsBetweenChecks);
|
|
private static readonly FileInfo_CompareByPath s_FileInfo_CompareByPath = new FileInfo_CompareByPath();
|
|
|
|
private readonly System.Collections.Generic.HashSet<string> m_WwuToProcess =
|
|
new System.Collections.Generic.HashSet<string>();
|
|
|
|
private int m_currentWwuCnt;
|
|
private int m_totWwuCnt = 1;
|
|
|
|
private static void Tick()
|
|
{
|
|
isTicking = true;
|
|
|
|
if (AkWwiseProjectInfo.GetData() != null)
|
|
{
|
|
if (System.DateTime.Now.Subtract(s_lastFileCheck).Seconds > s_SecondsBetweenChecks &&
|
|
!UnityEditor.EditorApplication.isCompiling && !UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode &&
|
|
AkWwiseProjectInfo.GetData().autoPopulateEnabled)
|
|
{
|
|
if (Populate())
|
|
{
|
|
AkWwiseXMLBuilder.Populate();
|
|
//check if WAAPI or not
|
|
AkWwisePicker.Refresh(ignoreIfWaapi: true);
|
|
//Make sure that the Wwise picker and the inspector are updated
|
|
AkUtilities.RepaintInspector();
|
|
}
|
|
|
|
s_lastFileCheck = System.DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void InitializeWwiseProjectData()
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.WwiseProjectPath))
|
|
{
|
|
UnityEngine.Debug.LogError("WwiseUnity: Wwise project needed to populate from Work Units. Aborting.");
|
|
return;
|
|
}
|
|
|
|
var fullWwiseProjectPath = AkWwiseEditorSettings.WwiseProjectAbsolutePath;
|
|
s_wwiseProjectPath = System.IO.Path.GetDirectoryName(fullWwiseProjectPath);
|
|
|
|
AkUtilities.IsWwiseProjectAvailable = System.IO.File.Exists(fullWwiseProjectPath);
|
|
if (!AkUtilities.IsWwiseProjectAvailable || UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || string.IsNullOrEmpty(s_wwiseProjectPath) ||
|
|
UnityEditor.EditorApplication.isCompiling)
|
|
return;
|
|
|
|
var builder = new AkWwiseWWUBuilder();
|
|
builder.GatherModifiedFiles();
|
|
builder.UpdateFiles();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
public static bool Populate()
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.WwiseProjectPath))
|
|
{
|
|
UnityEngine.Debug.LogError("WwiseUnity: Wwise project needed to populate from Work Units. Aborting.");
|
|
return false;
|
|
}
|
|
|
|
var fullWwiseProjectPath = AkWwiseEditorSettings.WwiseProjectAbsolutePath;
|
|
s_wwiseProjectPath = System.IO.Path.GetDirectoryName(fullWwiseProjectPath);
|
|
|
|
AkUtilities.IsWwiseProjectAvailable = System.IO.File.Exists(fullWwiseProjectPath);
|
|
if (!AkUtilities.IsWwiseProjectAvailable || UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || string.IsNullOrEmpty(s_wwiseProjectPath) ||
|
|
(UnityEditor.EditorApplication.isCompiling && !AkUtilities.IsMigrating))
|
|
return false;
|
|
|
|
AkPluginActivator.Update();
|
|
|
|
var builder = new AkWwiseWWUBuilder();
|
|
if (!builder.GatherModifiedFiles())
|
|
return false;
|
|
|
|
builder.UpdateFiles();
|
|
return true;
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
UnityEngine.Debug.LogError(e.ToString());
|
|
UnityEditor.EditorUtility.ClearProgressBar();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static void UpdateWwiseObjectReferenceData()
|
|
{
|
|
UnityEngine.Debug.Log("WwiseUnity: Updating Wwise Object References");
|
|
|
|
WwiseObjectReference.ClearWwiseObjectDataMap();
|
|
UpdateWwiseObjectReference(WwiseObjectType.AuxBus, AkWwiseProjectInfo.GetData().AuxBusWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.Event, AkWwiseProjectInfo.GetData().EventWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.Soundbank, AkWwiseProjectInfo.GetData().BankWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.GameParameter, AkWwiseProjectInfo.GetData().RtpcWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.Trigger, AkWwiseProjectInfo.GetData().TriggerWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.AcousticTexture, AkWwiseProjectInfo.GetData().AcousticTextureWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.StateGroup, WwiseObjectType.State, AkWwiseProjectInfo.GetData().StateWwu);
|
|
UpdateWwiseObjectReference(WwiseObjectType.SwitchGroup, WwiseObjectType.Switch, AkWwiseProjectInfo.GetData().SwitchWwu);
|
|
}
|
|
|
|
private int RecurseWorkUnit(AssetType in_type, System.IO.FileInfo in_workUnit, string in_currentPathInProj,
|
|
string in_currentPhysicalPath, System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement> in_pathAndIcons,
|
|
string in_parentPath = "")
|
|
{
|
|
m_WwuToProcess.Remove(in_workUnit.FullName);
|
|
var wwuIndex = -1;
|
|
try
|
|
{
|
|
//Progress bar stuff
|
|
var msg = "Parsing Work Unit " + in_workUnit.Name;
|
|
UnityEditor.EditorUtility.DisplayProgressBar(s_progTitle, msg, m_currentWwuCnt / (float)m_totWwuCnt);
|
|
m_currentWwuCnt++;
|
|
|
|
in_currentPathInProj =
|
|
System.IO.Path.Combine(in_currentPathInProj, System.IO.Path.GetFileNameWithoutExtension(in_workUnit.Name));
|
|
|
|
var WwuPhysicalPath = System.IO.Path.Combine(in_currentPhysicalPath, in_workUnit.Name);
|
|
|
|
var wwu = ReplaceWwuEntry(WwuPhysicalPath, in_type, out wwuIndex);
|
|
|
|
wwu.ParentPath = in_currentPathInProj;
|
|
wwu.PhysicalPath = WwuPhysicalPath;
|
|
wwu.Guid = System.Guid.Empty;
|
|
wwu.LastTime = System.IO.File.GetLastWriteTime(in_workUnit.FullName);
|
|
|
|
using (var reader = System.Xml.XmlReader.Create(in_workUnit.FullName))
|
|
{
|
|
reader.MoveToContent();
|
|
reader.Read();
|
|
|
|
while (!reader.EOF && reader.ReadState == System.Xml.ReadState.Interactive)
|
|
{
|
|
if (reader.NodeType == System.Xml.XmlNodeType.Element && reader.Name.Equals("WorkUnit"))
|
|
{
|
|
if (wwu.Guid.Equals(System.Guid.Empty))
|
|
{
|
|
var ID = reader.GetAttribute("ID");
|
|
try
|
|
{
|
|
wwu.Guid = new System.Guid(ID);
|
|
in_pathAndIcons.AddLast(new AkWwiseProjectData.PathElement(
|
|
System.IO.Path.GetFileNameWithoutExtension(in_workUnit.Name), WwiseObjectType.WorkUnit, wwu.Guid));
|
|
wwu.PathAndIcons = new System.Collections.Generic.List<AkWwiseProjectData.PathElement>(in_pathAndIcons);
|
|
|
|
}
|
|
catch
|
|
{
|
|
UnityEngine.Debug.LogWarning("WwiseUnity: Error reading ID <" + ID + "> from work unit <" + in_workUnit.FullName + ">.");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
var persistMode = reader.GetAttribute("PersistMode");
|
|
if (persistMode == "Reference")
|
|
{
|
|
// ReadFrom advances the reader
|
|
var matchedElement = System.Xml.Linq.XNode.ReadFrom(reader) as System.Xml.Linq.XElement;
|
|
var newWorkUnitPath =
|
|
System.IO.Path.Combine(in_workUnit.Directory.FullName, matchedElement.Attribute("Name").Value + ".wwu");
|
|
var newWorkUnit = new System.IO.FileInfo(newWorkUnitPath);
|
|
|
|
// Parse the referenced Work Unit
|
|
RecurseWorkUnit(in_type, newWorkUnit, in_currentPathInProj, in_currentPhysicalPath, in_pathAndIcons,
|
|
WwuPhysicalPath);
|
|
}
|
|
else
|
|
{
|
|
// If the persist mode is "Standalone" or "Nested", it means the current XML tag
|
|
// is the one corresponding to the current file. We can ignore it and advance the reader
|
|
reader.Read();
|
|
}
|
|
}
|
|
else if (reader.NodeType == System.Xml.XmlNodeType.Element && (reader.Name.Equals("AuxBus") || reader.Name.Equals("Folder") || reader.Name.Equals("Bus")))
|
|
{
|
|
WwiseObjectType objType;
|
|
switch (reader.Name)
|
|
{
|
|
case "AuxBus":
|
|
objType = WwiseObjectType.AuxBus;
|
|
break;
|
|
|
|
case "Bus":
|
|
objType = WwiseObjectType.Bus;
|
|
break;
|
|
|
|
case "Folder":
|
|
default:
|
|
objType = WwiseObjectType.Folder;
|
|
break;
|
|
}
|
|
in_currentPathInProj = System.IO.Path.Combine(in_currentPathInProj, reader.GetAttribute("Name"));
|
|
in_pathAndIcons.AddLast(new AkWwiseProjectData.PathElement(reader.GetAttribute("Name"), objType, new System.Guid(reader.GetAttribute("ID"))));
|
|
bool IsEmptyElement = reader.IsEmptyElement; // Need to cache this because AddElementToList advances the reader.
|
|
AddElementToList(in_currentPathInProj, reader, in_type, in_pathAndIcons, wwuIndex, objType);
|
|
if (IsEmptyElement)
|
|
{
|
|
// This element has no children, step out of it immediately
|
|
// Remove the folder/bus from the path
|
|
in_currentPathInProj = in_currentPathInProj.Remove(in_currentPathInProj.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
|
|
in_pathAndIcons.RemoveLast();
|
|
// Reader was already advanced by AddElementToList
|
|
}
|
|
}
|
|
else if (reader.NodeType == System.Xml.XmlNodeType.EndElement &&
|
|
(reader.Name.Equals("Folder") || reader.Name.Equals("Bus") || reader.Name.Equals("AuxBus")))
|
|
{
|
|
// Remove the folder/bus from the path
|
|
in_currentPathInProj = in_currentPathInProj.Remove(in_currentPathInProj.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
|
|
in_pathAndIcons.RemoveLast();
|
|
// Advance the reader
|
|
reader.Read();
|
|
}
|
|
else if (reader.NodeType == System.Xml.XmlNodeType.Element && reader.Name.Equals(in_type.XmlElementName))
|
|
{
|
|
// Add the element to the list
|
|
AddElementToList(in_currentPathInProj, reader, in_type, in_pathAndIcons, wwuIndex);
|
|
}
|
|
else
|
|
reader.Read();
|
|
}
|
|
}
|
|
|
|
// Sort the newly populated Wwu alphabetically
|
|
SortWwu(in_type, wwuIndex);
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
UnityEngine.Debug.LogError(e.ToString());
|
|
wwuIndex = -1;
|
|
}
|
|
|
|
in_pathAndIcons.RemoveLast();
|
|
return wwuIndex;
|
|
}
|
|
|
|
private static bool isTicking = false;
|
|
|
|
public static void StartWWUWatcher()
|
|
{
|
|
if (isTicking)
|
|
return;
|
|
|
|
Tick();
|
|
UnityEditor.EditorApplication.update += Tick;
|
|
}
|
|
|
|
public static void StopWWUWatcher()
|
|
{
|
|
if (isTicking)
|
|
UnityEditor.EditorApplication.update -= Tick;
|
|
}
|
|
|
|
private static void RestartWWUWatcher()
|
|
{
|
|
if (AkWwiseProjectInfo.GetData().autoPopulateEnabled)
|
|
StartWWUWatcher();
|
|
}
|
|
|
|
static AkWwiseWWUBuilder()
|
|
{
|
|
InitializeWwiseProjectData();
|
|
|
|
UnityEditor.EditorApplication.playModeStateChanged += (UnityEditor.PlayModeStateChange playMode) =>
|
|
{
|
|
if (playMode == UnityEditor.PlayModeStateChange.EnteredEditMode)
|
|
RestartWWUWatcher();
|
|
};
|
|
}
|
|
|
|
private static System.Collections.Generic.Dictionary<WwiseObjectType, System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>> _WwiseObjectsToRemove
|
|
= new System.Collections.Generic.Dictionary<WwiseObjectType, System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>>();
|
|
|
|
private static System.Collections.Generic.Dictionary<WwiseObjectType, System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>> _WwiseObjectsToAdd
|
|
= new System.Collections.Generic.Dictionary<WwiseObjectType, System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>>();
|
|
|
|
private static void FlagForRemoval(WwiseObjectType type, int wwuIndex)
|
|
{
|
|
switch (type)
|
|
{
|
|
case WwiseObjectType.AuxBus:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().AuxBusWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.Event:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().EventWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.Soundbank:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().BankWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.GameParameter:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().RtpcWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.Trigger:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().TriggerWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.AcousticTexture:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().AcousticTextureWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.StateGroup:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().StateWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
|
|
case WwiseObjectType.SwitchGroup:
|
|
foreach (var wwobject in AkWwiseProjectInfo.GetData().SwitchWwu[wwuIndex].List)
|
|
FlagForRemoval(wwobject, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void FlagForInsertion(AkWwiseProjectData.AkBaseInformation info, WwiseObjectType type)
|
|
{
|
|
if (!_WwiseObjectsToAdd.ContainsKey(type))
|
|
_WwiseObjectsToAdd[type] = new System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>();
|
|
|
|
_WwiseObjectsToAdd[type].Add(info);
|
|
|
|
if (!AkUtilities.IsMigrating)
|
|
WwiseObjectReference.UpdateWwiseObject(type, info.Name, info.Guid);
|
|
}
|
|
|
|
private static void FlagForRemoval(AkWwiseProjectData.AkBaseInformation info, WwiseObjectType type)
|
|
{
|
|
if (!_WwiseObjectsToRemove.ContainsKey(type))
|
|
_WwiseObjectsToRemove[type] = new System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation>();
|
|
|
|
_WwiseObjectsToRemove[type].Add(info);
|
|
}
|
|
|
|
private bool GatherModifiedFiles()
|
|
{
|
|
_WwiseObjectsToRemove.Clear();
|
|
_WwiseObjectsToAdd.Clear();
|
|
|
|
var bChanged = false;
|
|
var iBasePathLen = s_wwiseProjectPath.Length + 1;
|
|
foreach (var scannedAsset in AssetType.ScannedAssets)
|
|
{
|
|
var dir = scannedAsset.RootDirectoryName;
|
|
var deleted = new System.Collections.Generic.List<int>();
|
|
var knownFiles = AkWwiseProjectInfo.GetData().GetWwuListByString(dir);
|
|
var cKnownBefore = knownFiles.Count;
|
|
|
|
try
|
|
{
|
|
//Get all Wwus in this folder.
|
|
var di = new System.IO.DirectoryInfo(System.IO.Path.Combine(s_wwiseProjectPath, dir));
|
|
var files = di.GetFiles("*.wwu", System.IO.SearchOption.AllDirectories);
|
|
System.Array.Sort(files, s_FileInfo_CompareByPath);
|
|
|
|
//Walk both arrays
|
|
var iKnown = 0;
|
|
var iFound = 0;
|
|
|
|
while (iFound < files.Length && iKnown < knownFiles.Count)
|
|
{
|
|
var workunit = knownFiles[iKnown] as AkWwiseProjectData.WorkUnit;
|
|
var foundRelPath = files[iFound].FullName.Substring(iBasePathLen);
|
|
switch (workunit.PhysicalPath.CompareTo(foundRelPath))
|
|
{
|
|
case 0:
|
|
//File was there and is still there. Check the FileTimes.
|
|
try
|
|
{
|
|
if (files[iFound].LastWriteTime > workunit.LastTime)
|
|
{
|
|
//File has been changed!
|
|
//If this file had a parent, parse recursively the parent itself
|
|
m_WwuToProcess.Add(files[iFound].FullName);
|
|
FlagForRemoval(scannedAsset.Type, iKnown);
|
|
bChanged = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
//Access denied probably (file does exists since it was picked up by GetFiles).
|
|
//Just ignore this file.
|
|
}
|
|
|
|
iFound++;
|
|
iKnown++;
|
|
break;
|
|
|
|
case 1:
|
|
m_WwuToProcess.Add(files[iFound].FullName);
|
|
iFound++;
|
|
break;
|
|
|
|
case -1:
|
|
//A file was deleted. Can't process it now, it would change the array indices.
|
|
deleted.Add(iKnown);
|
|
iKnown++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//The remainder from the files found on disk are all new files.
|
|
for (; iFound < files.Length; iFound++)
|
|
m_WwuToProcess.Add(files[iFound].FullName);
|
|
|
|
//All the remainder is deleted. From the end, of course.
|
|
if (iKnown < knownFiles.Count)
|
|
{
|
|
for (var i = iKnown; i < knownFiles.Count; ++i)
|
|
FlagForRemoval(scannedAsset.Type, i);
|
|
|
|
knownFiles.RemoveRange(iKnown, knownFiles.Count - iKnown);
|
|
}
|
|
|
|
//Delete those tagged.
|
|
for (var i = deleted.Count - 1; i >= 0; i--)
|
|
{
|
|
FlagForRemoval(scannedAsset.Type, deleted[i]);
|
|
knownFiles.RemoveAt(deleted[i]);
|
|
}
|
|
|
|
bChanged |= cKnownBefore != knownFiles.Count;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return bChanged || m_WwuToProcess.Count > 0;
|
|
}
|
|
|
|
private void UpdateFiles()
|
|
{
|
|
m_totWwuCnt = m_WwuToProcess.Count;
|
|
|
|
var iBasePathLen = s_wwiseProjectPath.Length + 1;
|
|
var iUnprocessed = 0;
|
|
while (m_WwuToProcess.Count - iUnprocessed > 0)
|
|
{
|
|
System.Collections.IEnumerator e = m_WwuToProcess.GetEnumerator();
|
|
for (var i = 0; i < iUnprocessed + 1; i++)
|
|
e.MoveNext();
|
|
|
|
var fullPath = e.Current as string;
|
|
var relPath = fullPath.Substring(iBasePathLen);
|
|
var typeStr = relPath.Remove(relPath.IndexOf(System.IO.Path.DirectorySeparatorChar));
|
|
if (!CreateWorkUnit(relPath, typeStr, fullPath))
|
|
iUnprocessed++;
|
|
}
|
|
|
|
//Add the unprocessed directly. This can happen if we don't find the parent WorkUnit.
|
|
//Normally, it should never happen, this is just a safe guard.
|
|
while (m_WwuToProcess.Count > 0)
|
|
{
|
|
System.Collections.IEnumerator e = m_WwuToProcess.GetEnumerator();
|
|
e.MoveNext();
|
|
var fullPath = e.Current as string;
|
|
var relPath = fullPath.Substring(iBasePathLen);
|
|
var typeStr = relPath.Remove(relPath.IndexOf(System.IO.Path.DirectorySeparatorChar));
|
|
UpdateWorkUnit(fullPath, typeStr, relPath);
|
|
}
|
|
|
|
foreach (var pair in _WwiseObjectsToAdd)
|
|
{
|
|
System.Collections.Generic.List<AkWwiseProjectData.AkBaseInformation> removeList = null;
|
|
if (!_WwiseObjectsToRemove.TryGetValue(pair.Key, out removeList))
|
|
continue;
|
|
|
|
removeList.Sort(AkWwiseProjectData.AkBaseInformation.CompareByGuid);
|
|
foreach (var info in pair.Value)
|
|
{
|
|
var index = removeList.BinarySearch(info, AkWwiseProjectData.AkBaseInformation.CompareByGuid);
|
|
if (index >= 0)
|
|
removeList.RemoveAt(index);
|
|
}
|
|
}
|
|
|
|
foreach (var pair in _WwiseObjectsToRemove)
|
|
{
|
|
var type = pair.Key;
|
|
var childType = type == WwiseObjectType.StateGroup ? WwiseObjectType.State : WwiseObjectType.Switch;
|
|
|
|
foreach (var info in pair.Value)
|
|
{
|
|
var groupValue = info as AkWwiseProjectData.GroupValue;
|
|
if (groupValue != null)
|
|
foreach (var value in groupValue.values)
|
|
WwiseObjectReference.DeleteWwiseObject(childType, value.Guid);
|
|
|
|
WwiseObjectReference.DeleteWwiseObject(type, info.Guid);
|
|
}
|
|
}
|
|
|
|
UnityEditor.EditorUtility.SetDirty(AkWwiseProjectInfo.GetData());
|
|
UnityEditor.EditorUtility.ClearProgressBar();
|
|
}
|
|
|
|
private static void UpdateWwiseObjectReference(WwiseObjectType type, System.Collections.Generic.List<AkWwiseProjectData.AkInfoWorkUnit> infoWwus)
|
|
{
|
|
foreach (var infoWwu in infoWwus)
|
|
foreach (var info in infoWwu.List)
|
|
WwiseObjectReference.UpdateWwiseObjectDataMap(type, info.Name, info.Guid);
|
|
}
|
|
|
|
private static void UpdateWwiseObjectReference(WwiseObjectType type, System.Collections.Generic.List<AkWwiseProjectData.EventWorkUnit> infoWwus)
|
|
{
|
|
foreach (var infoWwu in infoWwus)
|
|
foreach (var info in infoWwu.List)
|
|
WwiseObjectReference.UpdateWwiseObjectDataMap(type, info.Name, info.Guid);
|
|
}
|
|
|
|
private static void UpdateWwiseObjectReference(WwiseObjectType groupType, WwiseObjectType type, System.Collections.Generic.List<AkWwiseProjectData.GroupValWorkUnit> infoWwus)
|
|
{
|
|
foreach (var infoWwu in infoWwus)
|
|
{
|
|
foreach (var info in infoWwu.List)
|
|
{
|
|
WwiseObjectReference.UpdateWwiseObjectDataMap(groupType, info.Name, info.Guid);
|
|
foreach (var subTypeInfo in info.values)
|
|
WwiseObjectReference.UpdateWwiseObjectDataMap(type, subTypeInfo.Name, subTypeInfo.Guid);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void SortWwu(AssetType in_type, int in_wwuIndex)
|
|
{
|
|
switch (in_type.Type)
|
|
{
|
|
case WwiseObjectType.AuxBus:
|
|
AkWwiseProjectInfo.GetData().AuxBusWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.Event:
|
|
AkWwiseProjectInfo.GetData().EventWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.Soundbank:
|
|
AkWwiseProjectInfo.GetData().BankWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.GameParameter:
|
|
AkWwiseProjectInfo.GetData().RtpcWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.Trigger:
|
|
AkWwiseProjectInfo.GetData().TriggerWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.AcousticTexture:
|
|
AkWwiseProjectInfo.GetData().AcousticTextureWwu[in_wwuIndex].List.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.StateGroup:
|
|
var stateList = AkWwiseProjectInfo.GetData().StateWwu[in_wwuIndex].List;
|
|
stateList.Sort();
|
|
foreach (var group in stateList)
|
|
if (group.values.Count > 0)
|
|
group.values.Sort();
|
|
break;
|
|
|
|
case WwiseObjectType.SwitchGroup:
|
|
var switchList = AkWwiseProjectInfo.GetData().SwitchWwu[in_wwuIndex].List;
|
|
switchList.Sort();
|
|
foreach (var group in switchList)
|
|
if (group.values.Count > 0)
|
|
group.values.Sort();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static AkWwiseProjectData.WorkUnit ReplaceWwuEntry(string in_currentPhysicalPath, AssetType in_type, out int out_wwuIndex)
|
|
{
|
|
var list = AkWwiseProjectInfo.GetData().GetWwuListByString(in_type.RootDirectoryName);
|
|
out_wwuIndex = list.BinarySearch(new AkWwiseProjectData.WorkUnit { PhysicalPath = in_currentPhysicalPath });
|
|
AkWwiseProjectData.WorkUnit out_wwu = null;
|
|
|
|
switch (in_type.Type)
|
|
{
|
|
case WwiseObjectType.Event:
|
|
out_wwu = new AkWwiseProjectData.EventWorkUnit();
|
|
break;
|
|
|
|
case WwiseObjectType.StateGroup:
|
|
case WwiseObjectType.SwitchGroup:
|
|
out_wwu = new AkWwiseProjectData.GroupValWorkUnit();
|
|
break;
|
|
|
|
case WwiseObjectType.AuxBus:
|
|
case WwiseObjectType.Soundbank:
|
|
case WwiseObjectType.GameParameter:
|
|
case WwiseObjectType.Trigger:
|
|
case WwiseObjectType.AcousticTexture:
|
|
out_wwu = new AkWwiseProjectData.AkInfoWorkUnit();
|
|
break;
|
|
}
|
|
|
|
if (out_wwuIndex < 0)
|
|
{
|
|
out_wwuIndex = ~out_wwuIndex;
|
|
list.Insert(out_wwuIndex, out_wwu);
|
|
}
|
|
else
|
|
list[out_wwuIndex] = out_wwu;
|
|
|
|
return out_wwu;
|
|
}
|
|
|
|
private static void AddElementToList(string in_currentPathInProj, System.Xml.XmlReader in_reader, AssetType in_type,
|
|
System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement> in_pathAndIcons, int in_wwuIndex, WwiseObjectType in_LeafType = WwiseObjectType.None)
|
|
{
|
|
switch (in_type.Type)
|
|
{
|
|
case WwiseObjectType.Folder:
|
|
case WwiseObjectType.Bus:
|
|
case WwiseObjectType.AuxBus:
|
|
case WwiseObjectType.Event:
|
|
case WwiseObjectType.Soundbank:
|
|
case WwiseObjectType.GameParameter:
|
|
case WwiseObjectType.Trigger:
|
|
case WwiseObjectType.AcousticTexture:
|
|
{
|
|
var LeafType = in_LeafType == WwiseObjectType.None ? in_type.Type : in_LeafType;
|
|
var name = in_reader.GetAttribute("Name");
|
|
var valueToAdd = in_type.Type == WwiseObjectType.Event ? new AkWwiseProjectData.Event() : new AkWwiseProjectData.AkInformation();
|
|
valueToAdd.Name = name;
|
|
valueToAdd.Guid = new System.Guid(in_reader.GetAttribute("ID"));
|
|
valueToAdd.PathAndIcons = new System.Collections.Generic.List<AkWwiseProjectData.PathElement>(in_pathAndIcons);
|
|
|
|
FlagForInsertion(valueToAdd, in_type.Type);
|
|
|
|
switch (LeafType)
|
|
{
|
|
case WwiseObjectType.AuxBus:
|
|
case WwiseObjectType.Bus:
|
|
case WwiseObjectType.Folder:
|
|
valueToAdd.Path = in_currentPathInProj;
|
|
break;
|
|
|
|
default:
|
|
valueToAdd.Path = System.IO.Path.Combine(in_currentPathInProj, name);
|
|
valueToAdd.PathAndIcons.Add(new AkWwiseProjectData.PathElement(name, in_type.Type, valueToAdd.Guid));
|
|
break;
|
|
}
|
|
|
|
switch (in_type.Type)
|
|
{
|
|
case WwiseObjectType.AuxBus:
|
|
AkWwiseProjectInfo.GetData().AuxBusWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
|
|
case WwiseObjectType.Event:
|
|
AkWwiseProjectInfo.GetData().EventWwu[in_wwuIndex].List.Add(valueToAdd as AkWwiseProjectData.Event);
|
|
break;
|
|
|
|
case WwiseObjectType.Soundbank:
|
|
AkWwiseProjectInfo.GetData().BankWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
|
|
case WwiseObjectType.GameParameter:
|
|
AkWwiseProjectInfo.GetData().RtpcWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
|
|
case WwiseObjectType.Trigger:
|
|
AkWwiseProjectInfo.GetData().TriggerWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
|
|
case WwiseObjectType.AcousticTexture:
|
|
AkWwiseProjectInfo.GetData().AcousticTextureWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
in_reader.Read();
|
|
break;
|
|
|
|
case WwiseObjectType.StateGroup:
|
|
case WwiseObjectType.SwitchGroup:
|
|
{
|
|
var valueToAdd = new AkWwiseProjectData.GroupValue();
|
|
if (in_LeafType == WwiseObjectType.Folder)
|
|
{
|
|
valueToAdd.Name = in_reader.GetAttribute("Name");
|
|
valueToAdd.Guid = new System.Guid(in_reader.GetAttribute("ID"));
|
|
valueToAdd.PathAndIcons = new System.Collections.Generic.List<AkWwiseProjectData.PathElement>(in_pathAndIcons);
|
|
valueToAdd.Path = in_currentPathInProj;
|
|
|
|
FlagForInsertion(valueToAdd, in_type.Type);
|
|
in_reader.Read();
|
|
}
|
|
else
|
|
{
|
|
var XmlElement = System.Xml.Linq.XNode.ReadFrom(in_reader) as System.Xml.Linq.XElement;
|
|
var ChildrenList = System.Xml.Linq.XName.Get("ChildrenList");
|
|
var ChildrenElement = XmlElement.Element(ChildrenList);
|
|
if (ChildrenElement != null)
|
|
{
|
|
var name = XmlElement.Attribute("Name").Value;
|
|
valueToAdd.Name = name;
|
|
valueToAdd.Guid = new System.Guid(XmlElement.Attribute("ID").Value);
|
|
valueToAdd.Path = System.IO.Path.Combine(in_currentPathInProj, name);
|
|
valueToAdd.PathAndIcons = new System.Collections.Generic.List<AkWwiseProjectData.PathElement>(in_pathAndIcons);
|
|
valueToAdd.PathAndIcons.Add(new AkWwiseProjectData.PathElement(name, in_type.Type, valueToAdd.Guid));
|
|
|
|
FlagForInsertion(valueToAdd, in_type.Type);
|
|
|
|
var ChildElem = System.Xml.Linq.XName.Get(in_type.ChildElementName);
|
|
foreach (var element in ChildrenElement.Elements(ChildElem))
|
|
{
|
|
if (element.Name != in_type.ChildElementName)
|
|
continue;
|
|
|
|
var elementName = element.Attribute("Name").Value;
|
|
var childValue = new AkWwiseProjectData.AkBaseInformation
|
|
{
|
|
Name = elementName,
|
|
Guid = new System.Guid(element.Attribute("ID").Value),
|
|
};
|
|
childValue.PathAndIcons = new System.Collections.Generic.List<AkWwiseProjectData.PathElement>(valueToAdd.PathAndIcons);
|
|
childValue.PathAndIcons.Add(new AkWwiseProjectData.PathElement(elementName, in_type.ChildType, childValue.Guid));
|
|
valueToAdd.values.Add(childValue);
|
|
|
|
FlagForInsertion(childValue, in_type.ChildType);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
valueToAdd = null;
|
|
}
|
|
}
|
|
|
|
if (valueToAdd != null)
|
|
{
|
|
switch (in_type.Type)
|
|
{
|
|
case WwiseObjectType.StateGroup:
|
|
AkWwiseProjectInfo.GetData().StateWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
|
|
case WwiseObjectType.SwitchGroup:
|
|
AkWwiseProjectInfo.GetData().SwitchWwu[in_wwuIndex].List.Add(valueToAdd);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
UnityEngine.Debug.LogError("WwiseUnity: Unknown asset type in WWU parser");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private bool CreateWorkUnit(string in_relativePath, string in_wwuType, string in_fullPath)
|
|
{
|
|
var ParentID = string.Empty;
|
|
try
|
|
{
|
|
using (var reader = System.Xml.XmlReader.Create(in_fullPath))
|
|
{
|
|
reader.MoveToContent();
|
|
|
|
//We check if the current work unit has a parent and save its guid if its the case
|
|
while (!reader.EOF && reader.ReadState == System.Xml.ReadState.Interactive)
|
|
{
|
|
if (reader.NodeType == System.Xml.XmlNodeType.Element && reader.Name.Equals("WorkUnit"))
|
|
{
|
|
if (reader.GetAttribute("PersistMode").Equals("Nested"))
|
|
ParentID = reader.GetAttribute("OwnerID");
|
|
break;
|
|
}
|
|
|
|
reader.Read();
|
|
}
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
UnityEngine.Debug.Log("WwiseUnity: A changed Work unit wasn't found. It must have been deleted " + in_fullPath);
|
|
return false;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(ParentID))
|
|
{
|
|
var parentGuid = System.Guid.Empty;
|
|
|
|
try
|
|
{
|
|
parentGuid = new System.Guid(ParentID);
|
|
}
|
|
catch
|
|
{
|
|
UnityEngine.Debug.LogWarning("WwiseUnity: \"OwnerID\" in <" + in_fullPath + "> cannot be converted to a GUID (" + ParentID + ")");
|
|
return false;
|
|
}
|
|
|
|
var list = AkWwiseProjectInfo.GetData().GetWwuListByString(in_wwuType);
|
|
var PathAndIcons = new System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement>();
|
|
string PathInProj = string.Empty;
|
|
AkWwiseProjectData.WorkUnit wwu = null;
|
|
|
|
if (parentGuid != System.Guid.Empty)
|
|
{
|
|
for (var i = 0; i < list.Count; i++)
|
|
{
|
|
wwu = list[i] as AkWwiseProjectData.WorkUnit;
|
|
if (wwu.Guid.Equals(parentGuid))
|
|
{
|
|
PathInProj = wwu.ParentPath;
|
|
PathAndIcons = new System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement>(wwu.PathAndIcons);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
var WwuChildren = wwu.GetChildrenArrayList();
|
|
foreach (AkWwiseProjectData.AkInformation child in WwuChildren)
|
|
{
|
|
if (child.Guid.Equals(parentGuid))
|
|
{
|
|
PathInProj = child.Path;
|
|
PathAndIcons = new System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement>(child.PathAndIcons);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!string.IsNullOrEmpty(PathInProj))
|
|
{
|
|
RecurseWorkUnit(AssetType.Create(in_wwuType), new System.IO.FileInfo(in_fullPath), PathInProj,
|
|
in_relativePath.Remove(in_relativePath.LastIndexOf(System.IO.Path.DirectorySeparatorChar)), PathAndIcons,
|
|
wwu.PhysicalPath);
|
|
return true;
|
|
}
|
|
|
|
//Not found. Wait for it to load
|
|
return false;
|
|
}
|
|
|
|
//Root Wwu
|
|
UpdateWorkUnit(in_fullPath, in_wwuType, in_relativePath);
|
|
return true;
|
|
}
|
|
|
|
private void UpdateWorkUnit(string in_wwuFullPath, string in_wwuType, string in_relativePath)
|
|
{
|
|
var PathAndIcons = new System.Collections.Generic.LinkedList<AkWwiseProjectData.PathElement>();
|
|
var currentPathInProj = string.Empty;
|
|
|
|
|
|
//Add physical folders to the hierarchy if the work unit isn't in the root folder
|
|
var physicalPath = in_relativePath.Split(System.IO.Path.DirectorySeparatorChar);
|
|
for (var i = 0; i < physicalPath.Length -1; i++)
|
|
{
|
|
PathAndIcons.AddLast(
|
|
new AkWwiseProjectData.PathElement(physicalPath[i], WwiseObjectType.PhysicalFolder, System.Guid.Empty));
|
|
currentPathInProj = System.IO.Path.Combine(currentPathInProj,physicalPath[i]);
|
|
}
|
|
|
|
//Parse the work unit file
|
|
RecurseWorkUnit(AssetType.Create(in_wwuType), new System.IO.FileInfo(in_wwuFullPath), currentPathInProj,
|
|
in_relativePath.Remove(in_relativePath.LastIndexOf(System.IO.Path.DirectorySeparatorChar)), PathAndIcons);
|
|
}
|
|
|
|
public class AssetType
|
|
{
|
|
public string RootDirectoryName { get; set; }
|
|
public string XmlElementName;
|
|
public string ChildElementName;
|
|
public WwiseObjectType Type = WwiseObjectType.None;
|
|
public WwiseObjectType ChildType = WwiseObjectType.None;
|
|
|
|
public static AssetType[] ScannedAssets
|
|
{
|
|
get { return _ScannedAssets; }
|
|
}
|
|
|
|
public static AssetType Create(string rootDirectoryName)
|
|
{
|
|
foreach (var asset in ScannedAssets)
|
|
if (string.Equals(rootDirectoryName, asset.RootDirectoryName, System.StringComparison.OrdinalIgnoreCase))
|
|
return asset;
|
|
|
|
return null;
|
|
}
|
|
|
|
private AssetType(string RootFolder, string XmlElemName, WwiseObjectType type)
|
|
{
|
|
RootDirectoryName = RootFolder;
|
|
XmlElementName = XmlElemName;
|
|
Type = type;
|
|
}
|
|
|
|
private static readonly AssetType[] _ScannedAssets = new AssetType[]
|
|
{
|
|
new AssetType("Master-Mixer Hierarchy", "AuxBus", WwiseObjectType.AuxBus),
|
|
new AssetType("Events", "Event", WwiseObjectType.Event),
|
|
new AssetType("SoundBanks", "SoundBank", WwiseObjectType.Soundbank),
|
|
new AssetType("States", "StateGroup", WwiseObjectType.StateGroup) { ChildElementName = "State", ChildType = WwiseObjectType.State },
|
|
new AssetType("Switches", "SwitchGroup", WwiseObjectType.SwitchGroup) { ChildElementName = "Switch", ChildType = WwiseObjectType.Switch },
|
|
new AssetType("Game Parameters", "GameParameter", WwiseObjectType.GameParameter),
|
|
new AssetType("Triggers", "Trigger", WwiseObjectType.Trigger),
|
|
new AssetType("Virtual Acoustics", "AcousticTexture", WwiseObjectType.AcousticTexture),
|
|
};
|
|
}
|
|
|
|
private class FileInfo_CompareByPath : System.Collections.Generic.IComparer<System.IO.FileInfo>
|
|
{
|
|
int System.Collections.Generic.IComparer<System.IO.FileInfo>.Compare(System.IO.FileInfo wwuA, System.IO.FileInfo wwuB)
|
|
{
|
|
return wwuA.FullName.CompareTo(wwuB.FullName);
|
|
}
|
|
}
|
|
}
|
|
#endif
|