static private string UpdateCache() { if (eventCache == null) { eventCache = AssetDatabase.LoadAssetAtPath(CacheAssetFullName, typeof(EventCache)) as EventCache; if (eventCache == null || eventCache.cacheVersion != EventCache.CurrentCacheVersion) { Debug.Log("FMOD: Event cache is missing or in an old format; creating a new instance."); eventCache = ScriptableObject.CreateInstance <EventCache>(); eventCache.cacheVersion = EventCache.CurrentCacheVersion; Directory.CreateDirectory(Path.GetDirectoryName(CacheAssetFullName)); AssetDatabase.CreateAsset(eventCache, CacheAssetFullName); } } var settings = Settings.Instance; if (string.IsNullOrEmpty(settings.SourceBankPath)) { ClearCache(); return(null); } string defaultBankFolder = null; if (!settings.HasPlatforms) { defaultBankFolder = settings.SourceBankPath; } else { Platform platform = settings.CurrentEditorPlatform; if (platform == settings.DefaultPlatform) { platform = settings.PlayInEditorPlatform; } defaultBankFolder = RuntimeUtils.GetCommonPlatformPath(Path.Combine(settings.SourceBankPath, platform.BuildDirectory)); } string[] bankPlatforms = EditorUtils.GetBankPlatforms(); string[] bankFolders = new string[bankPlatforms.Length]; for (int i = 0; i < bankPlatforms.Length; i++) { bankFolders[i] = RuntimeUtils.GetCommonPlatformPath(Path.Combine(settings.SourceBankPath, bankPlatforms[i])); } List <string> stringBanks = new List <string>(0); try { var files = Directory.GetFiles(defaultBankFolder, "*." + StringBankExtension, SearchOption.AllDirectories); stringBanks = new List <string>(files); } catch { } // Strip out OSX resource-fork files that appear on FAT32 stringBanks.RemoveAll((x) => Path.GetFileName(x).StartsWith("._")); if (stringBanks.Count == 0) { ClearCache(); return(string.Format("Directory {0} doesn't contain any banks.\nBuild the banks in Studio or check the path in the settings.", defaultBankFolder)); } // If we have multiple .strings.bank files find the most recent stringBanks.Sort((a, b) => File.GetLastWriteTime(b).CompareTo(File.GetLastWriteTime(a))); // Use the most recent string bank timestamp as a marker for the most recent build of any bank because it gets exported every time DateTime lastWriteTime = File.GetLastWriteTime(stringBanks[0]); // Get a list of all banks List <string> bankFileNames = new List <string>(); List <string> reducedStringBanksList = new List <string>(); HashSet <Guid> stringBankGuids = new HashSet <Guid>(); foreach (string stringBankPath in stringBanks) { FMOD.Studio.Bank stringBank; EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank)); if (!stringBank.isValid()) { return(string.Format("{0} is not a valid bank.", stringBankPath)); } else { // Unload the strings bank stringBank.unload(); } Guid stringBankGuid; EditorUtils.CheckResult(stringBank.getID(out stringBankGuid)); if (!stringBankGuids.Add(stringBankGuid)) { // If we encounter multiple string banks with the same GUID then only use the first. This handles the scenario where // a Studio project is cloned and extended for DLC with a new master bank name. continue; } reducedStringBanksList.Add(stringBankPath); } bankFileNames = new List <string>(Directory.GetFiles(defaultBankFolder, "*.bank", SearchOption.AllDirectories)); bankFileNames.RemoveAll(x => x.Contains(".strings")); stringBanks = reducedStringBanksList; eventCache.StringsBankWriteTime = lastWriteTime; // Stop editor preview so no stale data being held EditorUtils.PreviewStop(); // Reload the strings banks List <FMOD.Studio.Bank> loadedStringsBanks = new List <FMOD.Studio.Bank>(); try { AssetDatabase.StartAssetEditing(); eventCache.EditorBanks.ForEach((x) => x.Exists = false); HashSet <string> masterBankFileNames = new HashSet <string>(); foreach (string stringBankPath in stringBanks) { FMOD.Studio.Bank stringBank; EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank)); if (!stringBank.isValid()) { ClearCache(); return(string.Format("{0} is not a valid bank.", stringBankPath)); } loadedStringsBanks.Add(stringBank); FileInfo stringBankFileInfo = new FileInfo(stringBankPath); string masterBankFileName = Path.GetFileName(stringBankPath).Replace(StringBankExtension, BankExtension); masterBankFileNames.Add(masterBankFileName); EditorBankRef stringsBankRef = eventCache.StringsBanks.Find(x => RuntimeUtils.GetCommonPlatformPath(stringBankPath) == x.Path); if (stringsBankRef == null) { stringsBankRef = ScriptableObject.CreateInstance <EditorBankRef>(); stringsBankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); AssetDatabase.AddObjectToAsset(stringsBankRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(stringsBankRef)); eventCache.EditorBanks.Add(stringsBankRef); eventCache.StringsBanks.Add(stringsBankRef); } stringsBankRef.SetPath(stringBankPath, defaultBankFolder); string studioPath; stringBank.getPath(out studioPath); stringsBankRef.SetStudioPath(studioPath); stringsBankRef.LastModified = stringBankFileInfo.LastWriteTime; stringsBankRef.Exists = true; stringsBankRef.FileSizes.Clear(); if (Settings.Instance.HasPlatforms) { for (int i = 0; i < bankPlatforms.Length; i++) { stringsBankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], stringBankFileInfo.Length)); } } else { stringsBankRef.FileSizes.Add(new EditorBankRef.NameValuePair("", stringBankFileInfo.Length)); } } eventCache.EditorParameters.ForEach((x) => x.Exists = false); foreach (string bankFileName in bankFileNames) { EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => RuntimeUtils.GetCommonPlatformPath(bankFileName) == x.Path); // New bank we've never seen before if (bankRef == null) { bankRef = ScriptableObject.CreateInstance <EditorBankRef>(); AssetDatabase.AddObjectToAsset(bankRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(bankRef)); bankRef.SetPath(bankFileName, defaultBankFolder); bankRef.LastModified = DateTime.MinValue; bankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); eventCache.EditorBanks.Add(bankRef); } bankRef.Exists = true; FileInfo bankFileInfo = new FileInfo(bankFileName); // Update events from this bank if it has been modified, // or it is a master bank (so that we get any global parameters) if (bankRef.LastModified != bankFileInfo.LastWriteTime || masterBankFileNames.Contains(Path.GetFileName(bankFileName))) { bankRef.LastModified = bankFileInfo.LastWriteTime; UpdateCacheBank(bankRef); } // Update file sizes bankRef.FileSizes.Clear(); if (Settings.Instance.HasPlatforms) { for (int i = 0; i < bankPlatforms.Length; i++) { string platformBankPath = RuntimeUtils.GetCommonPlatformPath(bankFolders[i] + bankFileName.Replace(defaultBankFolder, "")); var fileInfo = new FileInfo(platformBankPath); if (fileInfo.Exists) { bankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], fileInfo.Length)); } } } else { string platformBankPath = RuntimeUtils.GetCommonPlatformPath(Path.Combine(Settings.Instance.SourceBankPath, bankFileName)); var fileInfo = new FileInfo(platformBankPath); if (fileInfo.Exists) { bankRef.FileSizes.Add(new EditorBankRef.NameValuePair("", fileInfo.Length)); } } if (masterBankFileNames.Contains(bankFileInfo.Name)) { if (!eventCache.MasterBanks.Exists(x => RuntimeUtils.GetCommonPlatformPath(bankFileName) == x.Path)) { eventCache.MasterBanks.Add(bankRef); } } } // Remove any stale entries from bank, event and parameter lists eventCache.EditorBanks.FindAll((x) => !x.Exists).ForEach(RemoveCacheBank); eventCache.EditorBanks.RemoveAll((x) => !x.Exists); eventCache.EditorEvents.RemoveAll((x) => x.Banks.Count == 0); eventCache.EditorParameters.RemoveAll((x) => !x.Exists); eventCache.MasterBanks.RemoveAll((x) => !x.Exists); eventCache.StringsBanks.RemoveAll((x) => !x.Exists); } finally { // Unload the strings banks loadedStringsBanks.ForEach(x => x.unload()); AssetDatabase.StopAssetEditing(); Debug.Log("FMOD: Cache updated."); } return(null); }
static void UpdateCacheBank(EditorBankRef bankRef) { // Clear out any cached events from this bank eventCache.EditorEvents.ForEach((x) => x.Banks.Remove(bankRef)); FMOD.Studio.Bank bank; FMOD.RESULT loadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); if (loadResult == FMOD.RESULT.ERR_EVENT_ALREADY_LOADED) { EditorUtils.System.getBank(bankRef.Name, out bank); bank.unload(); loadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); } if (loadResult == FMOD.RESULT.OK) { // Get studio path string studioPath; bank.getPath(out studioPath); bankRef.SetStudioPath(studioPath); // Iterate all events in the bank and cache them FMOD.Studio.EventDescription[] eventList; var result = bank.getEventList(out eventList); if (result == FMOD.RESULT.OK) { foreach (var eventDesc in eventList) { string path; result = eventDesc.getPath(out path); EditorEventRef eventRef = eventCache.EditorEvents.Find((x) => x.Path == path); if (eventRef == null) { eventRef = ScriptableObject.CreateInstance <EditorEventRef>(); AssetDatabase.AddObjectToAsset(eventRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(eventRef)); eventRef.Banks = new List <EditorBankRef>(); eventCache.EditorEvents.Add(eventRef); eventRef.Parameters = new List <EditorParamRef>(); } eventRef.Banks.Add(bankRef); Guid guid; eventDesc.getID(out guid); eventRef.Guid = guid; eventRef.Path = eventRef.name = path; eventDesc.is3D(out eventRef.Is3D); eventDesc.isOneshot(out eventRef.IsOneShot); eventDesc.isStream(out eventRef.IsStream); eventDesc.getMaximumDistance(out eventRef.MaxDistance); eventDesc.getMinimumDistance(out eventRef.MinDistance); eventDesc.getLength(out eventRef.Length); int paramCount = 0; eventDesc.getParameterDescriptionCount(out paramCount); eventRef.Parameters.ForEach((x) => x.Exists = false); for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { FMOD.Studio.PARAMETER_DESCRIPTION param; eventDesc.getParameterDescriptionByIndex(paramIndex, out param); // Skip if readonly and not global if ((param.flags & FMOD.Studio.PARAMETER_FLAGS.READONLY) != 0 && (param.flags & FMOD.Studio.PARAMETER_FLAGS.GLOBAL) == 0) { continue; } EditorParamRef paramRef = eventRef.Parameters.Find((x) => x.name == param.name); if (paramRef == null) { paramRef = ScriptableObject.CreateInstance <EditorParamRef>(); AssetDatabase.AddObjectToAsset(paramRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(paramRef)); eventRef.Parameters.Add(paramRef); } InitializeParamRef(paramRef, param); paramRef.name = "parameter:/" + Path.GetFileName(path) + "/" + paramRef.Name; paramRef.Exists = true; } eventRef.Parameters.RemoveAll((x) => !x.Exists); } } // Update global parameter list for each bank FMOD.Studio.PARAMETER_DESCRIPTION[] parameterDescriptions; result = EditorUtils.System.getParameterDescriptionList(out parameterDescriptions); if (result == FMOD.RESULT.OK) { for (int i = 0; i < parameterDescriptions.Length; i++) { FMOD.Studio.PARAMETER_DESCRIPTION param = parameterDescriptions[i]; if ((param.flags & FMOD.Studio.PARAMETER_FLAGS.GLOBAL) == FMOD.Studio.PARAMETER_FLAGS.GLOBAL) { EditorParamRef paramRef = eventCache.EditorParameters.Find((x) => (param.id.data1 == x.ID.data1 && param.id.data2 == x.ID.data2)); if (paramRef == null) { paramRef = ScriptableObject.CreateInstance <EditorParamRef>(); AssetDatabase.AddObjectToAsset(paramRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(paramRef)); eventCache.EditorParameters.Add(paramRef); paramRef.ID = param.id; } InitializeParamRef(paramRef, param); paramRef.name = "parameter:/" + param.name; paramRef.Exists = true; } } } bank.unload(); } else { Debug.LogError(string.Format("FMOD Studio: Unable to load {0}: {1}", bankRef.Name, FMOD.Error.String(loadResult))); eventCache.StringsBankWriteTime = DateTime.MinValue; } }