public EventCache() { EditorBanks = new List <EditorBankRef>(); EditorEvents = new List <EditorEventRef>(); MasterBankRef = null; stringsBankWriteTime = 0; }
public EventCache() { EditorBanks = new List<EditorBankRef>(); EditorEvents = new List<EditorEventRef>(); MasterBankRef = null; stringsBankWriteTime = 0; }
public void DrawBank(EditorBankRef bank) { AffirmResources(); DrawCopyableTextField("Full Path", "bank:/" + bank.Name); string[] SizeSuffix = { "B", "KB", "MB", "GB" }; GUILayout.Label("Platform Bank Sizes", textFieldNameStyle); EditorGUI.indentLevel++; foreach (var sizeInfo in bank.FileSizes) { int order = 0; long size = sizeInfo.Value; while (size >= 1024 && order + 1 < SizeSuffix.Length) { order++; size /= 1024; } EditorGUILayout.LabelField(sizeInfo.Name, string.Format("{0} {1}", size, SizeSuffix[order])); } EditorGUI.indentLevel--; }
private void PreviewBank(Rect previewRect, EditorBankRef selectedBank) { GUILayout.BeginArea(previewRect); EditorGUIUtility.labelWidth = 75; string[] SizeSuffix = { "B", "KB", "MB", "GB" }; EditorStyles.label.fontStyle = FontStyle.Bold; EditorGUILayout.LabelField("Platform Bank Sizes"); EditorStyles.label.fontStyle = FontStyle.Normal; EditorGUI.indentLevel++; foreach (var sizeInfo in selectedBank.FileSizes) { int order = 0; long len = sizeInfo.Value; while (len >= 1024 && order + 1 < SizeSuffix.Length) { order++; len /= 1024; } EditorGUILayout.LabelField(sizeInfo.Name, String.Format("{0} {1}", len, SizeSuffix[order])); } EditorGUI.indentLevel--; EditorGUIUtility.labelWidth = 0; GUILayout.EndArea(); }
static public void UpdateCache() { // Deserialize the cache from the unity resources if (eventCache == null) { eventCache = AssetDatabase.LoadAssetAtPath(CacheAssetFullName, typeof(EventCache)) as EventCache; if (eventCache == null || eventCache.cacheVersion != EventCache.CurrentCacheVersion) { UnityEngine.Debug.Log("FMOD Studio: Cannot find serialized event cache or cache in old format, creating 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; } 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) { bool wasValid = eventCache.StringsBankWriteTime != DateTime.MinValue; ClearCache(); if (wasValid) { UnityEngine.Debug.LogError(string.Format("FMOD Studio: Directory {0} doesn't contain any banks. Build the banks in Studio or check the path in the settings.", defaultBankFolder)); } return; } // 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]); if (lastWriteTime == eventCache.StringsBankWriteTime) { countdownTimer = CountdownTimerReset; return; } if (EditorUtils.IsFileOpenByStudio(stringBanks[0])) { countdownTimer = CountdownTimerReset; return; } // Most recent strings bank is newer than last cache update time, recache. // 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()) { countdownTimer = CountdownTimerReset; return; } 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; if (!UnityEditorInternal.InternalEditorUtility.inBatchMode) { // Check if any of the files are still being written by studio foreach (string bankFileName in bankFileNames) { EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => RuntimeUtils.GetCommonPlatformPath(bankFileName) == x.Path); if (bankRef == null) { if (EditorUtils.IsFileOpenByStudio(bankFileName)) { countdownTimer = CountdownTimerReset; return; } continue; } if (bankRef.LastModified != File.GetLastWriteTime(bankFileName)) { if (EditorUtils.IsFileOpenByStudio(bankFileName)) { countdownTimer = CountdownTimerReset; return; } } } // Count down the timer in case we catch studio in-between updating two files. if (countdownTimer-- > 0) { return; } } eventCache.StringsBankWriteTime = lastWriteTime; // All files are finished being modified by studio so update the cache // 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; } 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); 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); // Timestamp check - if it doesn't match update events from that bank if (bankRef.LastModified != bankFileInfo.LastWriteTime) { 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(Path.Combine(bankFolders[i], bankFileName)); 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."); } }
static void UpdateCache() { if (EditorUtils.GetBankDirectory() == null) { if (eventCache.StringsBankWriteTime != DateTime.MinValue) { eventCache.StringsBankWriteTime = DateTime.MinValue; eventCache.EditorBanks.Clear(); eventCache.EditorEvents.Clear(); OnCacheChange(); } return; } string defaultBankFolder = null; if (!Settings.Instance.HasPlatforms) { defaultBankFolder = EditorUtils.GetBankDirectory(); } else { defaultBankFolder = Path.Combine(EditorUtils.GetBankDirectory(), Settings.Instance.GetBankPlatform(FMODPlatform.PlayInEditor)); } string[] bankPlatforms = EditorUtils.GetBankPlatforms(); string[] bankFolders = new string[bankPlatforms.Length]; for (int i = 0; i < bankPlatforms.Length; i++) { bankFolders[i] = Path.Combine(EditorUtils.GetBankDirectory(), bankPlatforms[i]); } string[] stringBanks = new string[0]; try { stringBanks = Directory.GetFiles(defaultBankFolder, "*." + StringBankExtension); } catch { } if (stringBanks.Length == 0) { if (eventCache.StringsBankWriteTime != DateTime.MinValue) { eventCache.StringsBankWriteTime = DateTime.MinValue; eventCache.EditorBanks.Clear(); eventCache.EditorEvents.Clear(); OnCacheChange(); UnityEngine.Debug.LogWarningFormat("FMOD Studio: Directory {0} doesn't contain any banks. Build from the tool or check the path in the settings", defaultBankFolder); } return; } // If we have multiple .strings.bank files find the most recent Array.Sort(stringBanks, (a, b) => File.GetLastWriteTime(b).CompareTo(File.GetLastWriteTime(a))); string stringBankPath = stringBanks[0]; // Use the string bank timestamp as a marker for the most recent build of any bank because it gets exported every time if (File.GetLastWriteTime(stringBankPath) <= eventCache.StringsBankWriteTime) { return; } eventCache.StringsBankWriteTime = File.GetLastWriteTime(stringBankPath); string masterBankFileName = Path.GetFileName(stringBankPath).Replace(StringBankExtension, BankExtension); FMOD.Studio.Bank stringBank = null; EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank)); if (stringBank == null) { if (eventCache.StringsBankWriteTime != DateTime.MinValue) { eventCache.StringsBankWriteTime = DateTime.MinValue; eventCache.EditorBanks.Clear(); eventCache.EditorEvents.Clear(); OnCacheChange(); } return; } // Iterate every string in the strings bank and look for any that identify banks int stringCount; stringBank.getStringCount(out stringCount); List <string> bankFileNames = new List <string>(); for (int stringIndex = 0; stringIndex < stringCount; stringIndex++) { string currentString; Guid currentGuid; stringBank.getStringInfo(stringIndex, out currentGuid, out currentString); const string BankPrefix = "bank:/"; int BankPrefixLength = BankPrefix.Length; if (currentString.StartsWith(BankPrefix)) { string bankFileName = currentString.Substring(BankPrefixLength) + "." + BankExtension; if (!bankFileName.Contains(StringBankExtension)) // filter out the strings bank { bankFileNames.Add(bankFileName); } } } eventCache.EditorBanks.ForEach((x) => x.Exists = false); foreach (string bankFileName in bankFileNames) { string bankPath = Path.Combine(defaultBankFolder, bankFileName); EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => bankPath == x.Path); // New bank we've never seen before if (bankRef == null) { bankRef = ScriptableObject.CreateInstance <EditorBankRef>(); AssetDatabase.AddObjectToAsset(bankRef, CacheAssetFullName); bankRef.Path = bankPath; bankRef.LastModified = DateTime.MinValue; bankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); eventCache.EditorBanks.Add(bankRef); } bankRef.Exists = true; // Timestamp check - if it doesn't match update events from that bank if (bankRef.LastModified != File.GetLastWriteTime(bankPath)) { bankRef.LastModified = File.GetLastWriteTime(bankPath); UpdateCacheBank(bankRef); } // Update file sizes bankRef.FileSizes.Clear(); for (int i = 0; i < bankPlatforms.Length; i++) { string platformBankPath = Path.Combine(bankFolders[i], bankFileName); var fileInfo = new FileInfo(platformBankPath); if (fileInfo.Exists) { bankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], fileInfo.Length)); } } if (bankFileName == masterBankFileName) { eventCache.MasterBankRef = bankRef; } } // Unload the strings bank stringBank.unload(); // Remove any stale entries from bank and event lists eventCache.EditorBanks.FindAll((x) => !x.Exists).ForEach(RemoveCacheBank); eventCache.EditorBanks.RemoveAll((x) => !x.Exists); eventCache.EditorEvents.RemoveAll((x) => x.Banks.Count == 0); OnCacheChange(); }
static void RemoveCacheBank(EditorBankRef bankRef) { eventCache.EditorEvents.ForEach((x) => x.Banks.Remove(bankRef)); }
public static void CopyToStreamingAssets() { if (string.IsNullOrEmpty(Settings.Instance.SourceBankPath)) { return; } Platform platform = Settings.Instance.CurrentEditorPlatform; if (platform == Settings.Instance.DefaultPlatform) { Debug.LogWarningFormat("FMOD Studio: copy banks for platform {0} : Unsupported platform", EditorUserBuildSettings.activeBuildTarget); return; } string bankTargetFolder = Settings.Instance.ImportType == ImportType.StreamingAssets ? Settings.Instance.TargetPath : Application.dataPath + (string.IsNullOrEmpty(Settings.Instance.TargetAssetPath) ? "" : '/' + Settings.Instance.TargetAssetPath); bankTargetFolder = RuntimeUtils.GetCommonPlatformPath(bankTargetFolder); Directory.CreateDirectory(bankTargetFolder); string bankTargetExtension = Settings.Instance.ImportType == ImportType.StreamingAssets ? ".bank" : ".bytes"; string bankSourceFolder = Settings.Instance.HasPlatforms ? Settings.Instance.SourceBankPath + '/' + platform.BuildDirectory : Settings.Instance.SourceBankPath; bankSourceFolder = RuntimeUtils.GetCommonPlatformPath(bankSourceFolder); if (Path.GetFullPath(bankTargetFolder).TrimEnd('/').ToUpperInvariant() == Path.GetFullPath(bankSourceFolder).TrimEnd('/').ToUpperInvariant()) { return; } bool madeChanges = false; if (removeBanks) { string oldBankTargetFolder = Settings.Instance.ImportType == ImportType.AssetBundle ? Settings.Instance.TargetPath : Application.dataPath + "/" + Settings.Instance.TargetAssetPath; RemoveBanks(oldBankTargetFolder); madeChanges = true; } try { // Clean out any stale .bank files string[] existingBankFiles = Directory.GetFiles(bankTargetFolder, "*" + bankTargetExtension, SearchOption.AllDirectories); foreach (string bankFilePath in existingBankFiles) { string bankName = EditorBankRef.CalculateName(bankFilePath, bankTargetFolder); if (!eventCache.EditorBanks.Exists(x => x.Name == bankName)) { string assetPath = bankFilePath.Replace(Application.dataPath, AssetsFolderName); if (AssetHasLabel(assetPath, FMODLabel)) { AssetDatabase.MoveAssetToTrash(assetPath); madeChanges = true; } } } // Copy over any files that don't match timestamp or size or don't exist foreach (var bankRef in eventCache.EditorBanks) { string sourcePath = bankSourceFolder + "/" + bankRef.Name + ".bank"; string targetPathRelative = bankRef.Name + bankTargetExtension; string targetPathFull = bankTargetFolder + "/" + targetPathRelative; FileInfo sourceInfo = new FileInfo(sourcePath); FileInfo targetInfo = new FileInfo(targetPathFull); if (!targetInfo.Exists || sourceInfo.Length != targetInfo.Length || sourceInfo.LastWriteTime != targetInfo.LastWriteTime) { if (targetInfo.Exists) { targetInfo.IsReadOnly = false; } else { EnsureFoldersExist(targetPathRelative, bankTargetFolder); } File.Copy(sourcePath, targetPathFull, true); targetInfo = new FileInfo(targetPathFull); targetInfo.IsReadOnly = false; targetInfo.LastWriteTime = sourceInfo.LastWriteTime; madeChanges = true; string assetString = targetPathFull.Replace(Application.dataPath, "Assets"); AssetDatabase.ImportAsset(assetString); UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(assetString); AssetDatabase.SetLabels(obj, new string[] { FMODLabel }); } } RemoveEmptyFMODFolders(bankTargetFolder); } catch (Exception exception) { Debug.LogErrorFormat("FMOD Studio: copy banks for platform {0} : copying banks from {1} to {2}", platform.DisplayName, bankSourceFolder, bankTargetFolder); Debug.LogException(exception); return; } if (madeChanges) { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.LogFormat("FMOD Studio: copy banks for platform {0} : copying banks from {1} to {2} succeeded", platform.DisplayName, bankSourceFolder, bankTargetFolder); } }
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; bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); if (bankRef.LoadResult == FMOD.RESULT.ERR_EVENT_ALREADY_LOADED) { EditorUtils.System.getBank(bankRef.Name, out bank); bank.unload(); bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); } if (bankRef.LoadResult == FMOD.RESULT.OK) { // 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; 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.Banks.Add(bankRef); Guid guid; eventDesc.getID(out guid); eventRef.Guid = guid; eventRef.Path = 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); int paramCount = 0; eventDesc.getParameterCount(out paramCount); eventRef.Parameters = new List<EditorParamRef>(paramCount); for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { EditorParamRef paramRef = ScriptableObject.CreateInstance<EditorParamRef>(); AssetDatabase.AddObjectToAsset(paramRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(paramRef)); FMOD.Studio.PARAMETER_DESCRIPTION param; eventDesc.getParameterByIndex(paramIndex, out param); paramRef.Name = param.name; paramRef.Min = param.minimum; paramRef.Max = param.maximum; paramRef.Default = param.defaultValue; eventRef.Parameters.Add(paramRef); } } } bank.unload(); } else { eventCache.StringsBankWriteTime = DateTime.MinValue; } }
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; bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); if (bankRef.LoadResult == FMOD.RESULT.ERR_EVENT_ALREADY_LOADED) { EditorUtils.System.getBank(bankRef.Name, out bank); bank.unload(); bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); } if (bankRef.LoadResult == FMOD.RESULT.OK) { // 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); if ((param.flags & FMOD.Studio.PARAMETER_FLAGS.READONLY) != 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); } paramRef.Name = param.name; paramRef.name = "parameter:/" + Path.GetFileName(path) + "/" + paramRef.Name; paramRef.Min = param.minimum; paramRef.Max = param.maximum; paramRef.Default = param.defaultvalue; 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) { EditorParamRef paramRef = eventCache.EditorParameters.Find((x) => (parameterDescriptions[i].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; } paramRef.Name = paramRef.name = param.name; paramRef.Min = param.minimum; paramRef.Max = param.maximum; paramRef.Default = param.defaultvalue; paramRef.Exists = true; } } } bank.unload(); } else { Debug.LogError(string.Format("FMOD Studio: Unable to load {0}: {1}", bankRef.Name, FMOD.Error.String(bankRef.LoadResult))); eventCache.StringsBankWriteTime = DateTime.MinValue; } }
public static void UpdateBankStubAssets(BuildTarget buildTarget) { if (Settings.Instance.ImportType != ImportType.AssetBundle || string.IsNullOrEmpty(Settings.Instance.SourceBankPath)) { return; } Platform platform = Settings.Instance.GetPlatform(buildTarget); if (platform == Settings.Instance.DefaultPlatform) { Debug.LogWarningFormat("FMOD: Updating bank stubs: Unsupported platform {0}", buildTarget); return; } string bankTargetFolder = Application.dataPath; if (!string.IsNullOrEmpty(Settings.Instance.TargetAssetPath)) { bankTargetFolder += "/" + Settings.Instance.TargetAssetPath; } bankTargetFolder = RuntimeUtils.GetCommonPlatformPath(bankTargetFolder); string bankSourceFolder = Settings.Instance.SourceBankPath; if (Settings.Instance.HasPlatforms) { bankSourceFolder += "/" + platform.BuildDirectory; } bankSourceFolder = RuntimeUtils.GetCommonPlatformPath(bankSourceFolder); if (Path.GetFullPath(bankTargetFolder).TrimEnd('/').ToUpperInvariant() == Path.GetFullPath(bankSourceFolder).TrimEnd('/').ToUpperInvariant()) { return; } bool madeChanges = false; Directory.CreateDirectory(bankTargetFolder); try { const string BankAssetExtension = ".bytes"; // Clean out any stale stubs string[] existingBankFiles = Directory.GetFiles(bankTargetFolder, "*" + BankAssetExtension, SearchOption.AllDirectories); foreach (string bankFilePath in existingBankFiles) { string bankName = EditorBankRef.CalculateName(bankFilePath, bankTargetFolder); if (!eventCache.EditorBanks.Exists(x => x.Name == bankName)) { string assetPath = bankFilePath.Replace(Application.dataPath, AssetsFolderName); if (AssetHasLabel(assetPath, FMODLabel)) { AssetDatabase.MoveAssetToTrash(assetPath); madeChanges = true; } } } // Create any stubs that don't exist, and ensure any that do exist have the correct data foreach (var bankRef in eventCache.EditorBanks) { string sourcePath = bankSourceFolder + "/" + bankRef.Name + ".bank"; string targetPathRelative = bankRef.Name + BankAssetExtension; string targetPathFull = bankTargetFolder + "/" + targetPathRelative; EnsureFoldersExist(targetPathRelative, bankTargetFolder); FileInfo targetInfo = new FileInfo(targetPathFull); string stubData = RuntimeManager.BankStubPrefix + bankRef.Name; // Minimise asset database refreshing by only writing the stub if necessary bool writeStub; if (targetInfo.Exists && targetInfo.Length == stubData.Length) { using (StreamReader reader = targetInfo.OpenText()) { string contents = reader.ReadToEnd(); writeStub = (contents != stubData); } } else { writeStub = true; } if (writeStub) { // Create or update the stub using (StreamWriter writer = targetInfo.CreateText()) { writer.Write(stubData); } madeChanges = true; if (!targetInfo.Exists) { string assetPath = targetPathFull.Replace(Application.dataPath, "Assets"); AssetDatabase.ImportAsset(assetPath); UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(assetPath); AssetDatabase.SetLabels(obj, new string[] { FMODLabel }); } } } RemoveEmptyFMODFolders(bankTargetFolder); } catch (Exception exception) { Debug.LogErrorFormat("FMOD: Updating bank stubs in {0} to match {1}", bankTargetFolder, bankSourceFolder); Debug.LogException(exception); return; } if (madeChanges) { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.LogFormat("FMOD: Updated bank stubs in {0} to match {1}", bankTargetFolder, bankSourceFolder); } }
static public void UpdateCache() { // Deserialize the cache from the unity resources if (eventCache == null) { eventCache = AssetDatabase.LoadAssetAtPath(CacheAssetFullName, typeof(EventCache)) as EventCache; if (eventCache == null || eventCache.cacheVersion != EventCache.CurrentCacheVersion) { UnityEngine.Debug.Log("FMOD Studio: Cannot find serialized event cache or cache in old format, creating new instance"); eventCache = ScriptableObject.CreateInstance <EventCache>(); eventCache.cacheVersion = EventCache.CurrentCacheVersion; AssetDatabase.CreateAsset(eventCache, CacheAssetFullName); } } if (EditorUtils.GetBankDirectory() == null) { ClearCache(); return; } string defaultBankFolder = null; if (!Settings.Instance.HasPlatforms) { defaultBankFolder = EditorUtils.GetBankDirectory(); } else { defaultBankFolder = Path.Combine(EditorUtils.GetBankDirectory(), Settings.Instance.GetBankPlatform(FMODPlatform.PlayInEditor)); } string[] bankPlatforms = EditorUtils.GetBankPlatforms(); string[] bankFolders = new string[bankPlatforms.Length]; for (int i = 0; i < bankPlatforms.Length; i++) { bankFolders[i] = Path.Combine(EditorUtils.GetBankDirectory(), bankPlatforms[i]); } List <String> stringBanks = new List <string>(0); try { var files = Directory.GetFiles(defaultBankFolder, "*." + StringBankExtension); stringBanks = new List <string>(files); } catch { UnityEngine.Debug.LogWarning(String.Format("FMOD Studio: Directory {0} doesn't exist. Build from the tool or check the path in the settings", defaultBankFolder)); } // Strip out OSX resource-fork files that appear on FAT32 stringBanks.RemoveAll((x) => Path.GetFileName(x).StartsWith("._")); if (stringBanks.Count == 0) { ClearCache(); if (eventCache.StringsBankWriteTime != DateTime.MinValue) { UnityEngine.Debug.LogWarning(String.Format("FMOD Studio: Directory {0} doesn't contain any banks. Build from the tool or check the path in the settings", defaultBankFolder)); } return; } // If we have multiple .strings.bank files find the most recent stringBanks.Sort((a, b) => File.GetLastWriteTime(b).CompareTo(File.GetLastWriteTime(a))); string stringBankPath = stringBanks[0]; // Use the string bank timestamp as a marker for the most recent build of any bank because it gets exported every time if (File.GetLastWriteTime(stringBankPath) == eventCache.StringsBankWriteTime) { countdownTimer = 1; return; } if (EditorUtils.IsFileOpenByStudio(stringBankPath)) { countdownTimer = 1; return; } FMOD.Studio.Bank stringBank = null; EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank)); if (stringBank == null) { countdownTimer = 1; return; } // Iterate every string in the strings bank and look for any that identify banks int stringCount; stringBank.getStringCount(out stringCount); List <string> bankFileNames = new List <string>(); for (int stringIndex = 0; stringIndex < stringCount; stringIndex++) { string currentString; Guid currentGuid; stringBank.getStringInfo(stringIndex, out currentGuid, out currentString); const string BankPrefix = "bank:/"; int BankPrefixLength = BankPrefix.Length; if (currentString.StartsWith(BankPrefix)) { string bankFileName = currentString.Substring(BankPrefixLength) + "." + BankExtension; if (!bankFileName.Contains(StringBankExtension)) // filter out the strings bank { bankFileNames.Add(bankFileName); } } } // Unload the strings bank stringBank.unload(); // Check if any of the files are still being written by studio foreach (string bankFileName in bankFileNames) { string bankPath = Path.Combine(defaultBankFolder, bankFileName); if (!File.Exists(bankPath)) { countdownTimer = 1; return; } EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => bankPath == x.Path); if (bankRef == null) { if (EditorUtils.IsFileOpenByStudio(bankPath)) { countdownTimer = 1; return; } continue; } if (bankRef.LastModified != File.GetLastWriteTime(bankPath)) { if (EditorUtils.IsFileOpenByStudio(bankPath)) { countdownTimer = 1; return; } } } // Do one extra loop through the in-use check in case we catch studio exactly in-between updating two files. if (countdownTimer-- > 0) { return; } // All files are finished being modified by studio so update the cache // Reload the strings bank EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank)); if (stringBank == null) { ClearCache(); return; } eventCache.StringsBankWriteTime = File.GetLastWriteTime(stringBankPath); string masterBankFileName = Path.GetFileName(stringBankPath).Replace(StringBankExtension, BankExtension); eventCache.EditorBanks.ForEach((x) => x.Exists = false); foreach (string bankFileName in bankFileNames) { string bankPath = Path.Combine(defaultBankFolder, bankFileName); EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => bankPath == 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.Path = bankPath; bankRef.LastModified = DateTime.MinValue; bankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); eventCache.EditorBanks.Add(bankRef); } bankRef.Exists = true; // Timestamp check - if it doesn't match update events from that bank if (bankRef.LastModified != File.GetLastWriteTime(bankPath)) { bankRef.LastModified = File.GetLastWriteTime(bankPath); UpdateCacheBank(bankRef); } // Update file sizes bankRef.FileSizes.Clear(); for (int i = 0; i < bankPlatforms.Length; i++) { string platformBankPath = Path.Combine(bankFolders[i], bankFileName); var fileInfo = new FileInfo(platformBankPath); if (fileInfo.Exists) { bankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], fileInfo.Length)); } } if (bankFileName == masterBankFileName) { eventCache.MasterBankRef = bankRef; } } // Unload the strings bank stringBank.unload(); // Remove any stale entries from bank and event lists eventCache.EditorBanks.FindAll((x) => !x.Exists).ForEach(RemoveCacheBank); eventCache.EditorBanks.RemoveAll((x) => !x.Exists); eventCache.EditorEvents.RemoveAll((x) => x.Banks.Count == 0); OnCacheChange(); }
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; bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); if (bankRef.LoadResult == FMOD.RESULT.ERR_EVENT_ALREADY_LOADED) { EditorUtils.System.getBank(bankRef.Name, out bank); bank.unload(); bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); } if (bankRef.LoadResult == FMOD.RESULT.OK) { // 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; eventDesc.getPath(out path); EditorEventRef eventRef = eventCache.EditorEvents.Find((x) => x.Path == path); if (eventRef == null) { eventRef = ScriptableObject.CreateInstance <EditorEventRef>(); AssetDatabase.AddObjectToAsset(eventRef, CacheAssetFullName); eventRef.Banks = new List <EditorBankRef>(); eventCache.EditorEvents.Add(eventRef); } eventRef.Banks.Add(bankRef); Guid guid; eventDesc.getID(out guid); eventRef.Guid = guid; eventRef.Path = 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); int paramCount = 0; eventDesc.getParameterCount(out paramCount); eventRef.Parameters = new List <EditorParamRef>(paramCount); for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { EditorParamRef paramRef = ScriptableObject.CreateInstance <EditorParamRef>(); AssetDatabase.AddObjectToAsset(paramRef, CacheAssetFullName); FMOD.Studio.PARAMETER_DESCRIPTION param; eventDesc.getParameterByIndex(paramIndex, out param); paramRef.Name = param.name; paramRef.Min = param.minimum; paramRef.Max = param.maximum; eventRef.Parameters.Add(paramRef); } } } bank.unload(); } else { // TODO: log the error //UnityEngine.Debug.LogWarning("Cannot load ); } }
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; bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); if (bankRef.LoadResult == FMOD.RESULT.ERR_EVENT_ALREADY_LOADED) { EditorUtils.System.getBank(bankRef.Name, out bank); bank.unload(); bankRef.LoadResult = EditorUtils.System.loadBankFile(bankRef.Path, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out bank); } if (bankRef.LoadResult == FMOD.RESULT.OK) { // 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.Banks.Add(bankRef); Guid guid; eventDesc.getID(out guid); eventRef.Guid = guid; eventRef.Path = 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.getParameterCount(out paramCount); eventRef.Parameters = new List <EditorParamRef>(paramCount); for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { FMOD.Studio.PARAMETER_DESCRIPTION param; eventDesc.getParameterByIndex(paramIndex, out param); if (param.type != FMOD.Studio.PARAMETER_TYPE.GAME_CONTROLLED) { continue; } EditorParamRef paramRef = ScriptableObject.CreateInstance <EditorParamRef>(); AssetDatabase.AddObjectToAsset(paramRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(paramRef)); paramRef.Name = param.name; paramRef.Min = param.minimum; paramRef.Max = param.maximum; paramRef.Default = param.defaultvalue; eventRef.Parameters.Add(paramRef); } } } bank.unload(); } else { Debug.LogError(String.Format("FMOD Studio: Unable to load {0}: {1}", bankRef.Name, FMOD.Error.String(bankRef.LoadResult))); eventCache.StringsBankWriteTime = DateTime.MinValue; } }
static public void UpdateCache() { // Deserialize the cache from the unity resources if (eventCache == null) { eventCache = AssetDatabase.LoadAssetAtPath(CacheAssetFullName, typeof(EventCache)) as EventCache; if (eventCache == null || eventCache.cacheVersion != EventCache.CurrentCacheVersion) { UnityEngine.Debug.Log("FMOD Studio: Cannot find serialized event cache or cache in old format, creating new instance"); eventCache = ScriptableObject.CreateInstance <EventCache>(); eventCache.cacheVersion = EventCache.CurrentCacheVersion; AssetDatabase.CreateAsset(eventCache, CacheAssetFullName); } } if (EditorUtils.GetBankDirectory() == null) { ClearCache(); return; } string defaultBankFolder = null; if (!Settings.Instance.HasPlatforms) { defaultBankFolder = EditorUtils.GetBankDirectory(); } else { FMODPlatform platform = RuntimeUtils.GetEditorFMODPlatform(); if (platform == FMODPlatform.None) { platform = FMODPlatform.PlayInEditor; } defaultBankFolder = Path.Combine(EditorUtils.GetBankDirectory(), Settings.Instance.GetBankPlatform(platform)); } string[] bankPlatforms = EditorUtils.GetBankPlatforms(); string[] bankFolders = new string[bankPlatforms.Length]; for (int i = 0; i < bankPlatforms.Length; i++) { bankFolders[i] = Path.Combine(EditorUtils.GetBankDirectory(), bankPlatforms[i]); } List <String> stringBanks = new List <string>(0); try { var files = Directory.GetFiles(defaultBankFolder, "*." + StringBankExtension); 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) { bool wasValid = eventCache.StringsBankWriteTime != DateTime.MinValue; ClearCache(); if (wasValid) { UnityEngine.Debug.LogError(String.Format("FMOD Studio: Directory {0} doesn't contain any banks. Build from the tool or check the path in the settings", defaultBankFolder)); } return; } // 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]); if (lastWriteTime == eventCache.StringsBankWriteTime) { countdownTimer = CountdownTimerReset; return; } if (EditorUtils.IsFileOpenByStudio(stringBanks[0])) { countdownTimer = CountdownTimerReset; return; } // Most recent strings bank is newer than last cache update time, recache. // Get a list of all banks HashSet <string> bankFileNames = new HashSet <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()) { countdownTimer = CountdownTimerReset; return; } try { 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); // Iterate every string in the strings bank and look for any that identify banks int stringCount; stringBank.getStringCount(out stringCount); for (int stringIndex = 0; stringIndex < stringCount; stringIndex++) { string currentString; Guid currentGuid; stringBank.getStringInfo(stringIndex, out currentGuid, out currentString); const string BankPrefix = "bank:/"; int BankPrefixLength = BankPrefix.Length; if (currentString.StartsWith(BankPrefix)) { string bankFileName = currentString.Substring(BankPrefixLength) + "." + BankExtension; if (!bankFileName.Contains(StringBankExtension)) // filter out the strings bank { bankFileNames.Add(bankFileName); } } } } finally { // Unload the strings bank stringBank.unload(); } } stringBanks = reducedStringBanksList; // Check if any of the files are still being written by studio foreach (string bankFileName in bankFileNames) { string bankPath = Path.Combine(defaultBankFolder, bankFileName); if (!File.Exists(bankPath)) { // TODO: this is meant to catch the case where we're in the middle of a build and a bank is being built // for the first time. But it also stops someone trying to import an incomplete set of banks without any error message. countdownTimer = CountdownTimerReset; return; } EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => bankPath == x.Path); if (bankRef == null) { if (EditorUtils.IsFileOpenByStudio(bankPath)) { countdownTimer = CountdownTimerReset; return; } continue; } if (bankRef.LastModified != File.GetLastWriteTime(bankPath)) { if (EditorUtils.IsFileOpenByStudio(bankPath)) { countdownTimer = CountdownTimerReset; return; } } } // Count down the timer in case we catch studio in-between updating two files. if (countdownTimer-- > 0) { return; } eventCache.StringsBankWriteTime = lastWriteTime; // All files are finished being modified by studio so update the cache // Stop editor preview so no stale data being held EditorUtils.PreviewStop(); // Reload the strings banks List <FMOD.Studio.Bank> loadedBanks = 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; } loadedBanks.Add(stringBank); FileInfo stringBankFileInfo = new FileInfo(stringBankPath); string masterBankFileName = Path.GetFileName(stringBankPath).Replace(StringBankExtension, BankExtension); masterBankFileNames.Add(masterBankFileName); EditorBankRef stringsBankRef = eventCache.StringsBanks.Find(x => stringBankPath == x.Path); if (stringsBankRef == null) { stringsBankRef = ScriptableObject.CreateInstance <EditorBankRef>(); stringsBankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); eventCache.EditorBanks.Add(stringsBankRef); AssetDatabase.AddObjectToAsset(stringsBankRef, eventCache); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(stringsBankRef)); eventCache.StringsBanks.Add(stringsBankRef); } stringsBankRef.Path = stringBankPath; 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)); } } string[] folderContents = Directory.GetFiles(defaultBankFolder); foreach (string bankFileName in bankFileNames) { // Get the true file path, can't trust the character case we got from the string bank string bankPath = ArrayUtility.Find(folderContents, x => (string.Equals(bankFileName, Path.GetFileName(x), StringComparison.CurrentCultureIgnoreCase))); FileInfo bankFileInfo = new FileInfo(bankPath); EditorBankRef bankRef = eventCache.EditorBanks.Find((x) => bankFileInfo.FullName == 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.Path = bankFileInfo.FullName; bankRef.LastModified = DateTime.MinValue; bankRef.FileSizes = new List <EditorBankRef.NameValuePair>(); eventCache.EditorBanks.Add(bankRef); } bankRef.Exists = true; // Timestamp check - if it doesn't match update events from that bank if (bankRef.LastModified != bankFileInfo.LastWriteTime) { 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 = Path.Combine(bankFolders[i], bankFileName); var fileInfo = new FileInfo(platformBankPath); if (fileInfo.Exists) { bankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], fileInfo.Length)); } } } else { string platformBankPath = Path.Combine(EditorUtils.GetBankDirectory(), 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 => bankFileInfo.FullName == x.Path)) { eventCache.MasterBanks.Add(bankRef); } } } // Remove any stale entries from bank and event lists eventCache.EditorBanks.FindAll((x) => !x.Exists).ForEach(RemoveCacheBank); eventCache.EditorBanks.RemoveAll((x) => !x.Exists); eventCache.EditorEvents.RemoveAll((x) => x.Banks.Count == 0); OnCacheChange(); } finally { // Unload the strings banks loadedBanks.ForEach(x => x.unload()); AssetDatabase.StopAssetEditing(); } }