PreviewStop() публичный статический Метод

public static PreviewStop ( ) : void
Результат void
Пример #1
0
            void SetEvent(EditorEventRef eventRef)
            {
                if (eventRef != currentEvent)
                {
                    currentEvent = eventRef;

                    EditorUtils.PreviewStop();
                    transportControls.Reset();
                    event3DPreview.Reset();
                    parameterControls.Reset();
                }
            }
Пример #2
0
            public void OnGUI(EditorEventRef selectedEvent, Dictionary <string, float> parameterValues)
            {
                AffirmResources();

                var  previewState = EditorUtils.PreviewState;
                bool playing      = previewState == PreviewState.Playing;
                bool paused       = previewState == PreviewState.Paused;
                bool stopped      = previewState == PreviewState.Stopped;

                EditorGUILayout.BeginHorizontal();

                if (GUILayout.Button(stopped || paused ? stopOn : stopOff, buttonStyle, GUILayout.ExpandWidth(false)))
                {
                    forceRepaint = false;

                    if (paused)
                    {
                        EditorUtils.PreviewStop();
                    }
                    if (playing)
                    {
                        EditorUtils.PreviewPause();
                    }
                }
                if (GUILayout.Button(playing ? playOn : playOff, buttonStyle, GUILayout.ExpandWidth(false)))
                {
                    if (playing || stopped)
                    {
                        EditorUtils.PreviewEvent(selectedEvent, parameterValues);
                    }
                    else
                    {
                        EditorUtils.PreviewPause();
                    }

                    forceRepaint = true;
                }
                if (GUILayout.Button(new GUIContent(openIcon, "Show Event in FMOD Studio"), buttonStyle, GUILayout.ExpandWidth(false)))
                {
                    string cmd = string.Format("studio.window.navigateTo(studio.project.lookup(\"{0}\"))", selectedEvent.Guid.ToString("b"));
                    EditorUtils.SendScriptCommand(cmd);
                }

                EditorGUILayout.EndHorizontal();
            }
Пример #3
0
        void SetPreviewEvent(EditorEventRef eventRef)
        {
            forceRepaint = false;
            EditorUtils.PreviewStop();
            previewParamValues.Clear();

            previewDistance    = 0;
            previewOrientation = 0;

            if (eventRef != null)
            {
                foreach (var paramRef in eventRef.Parameters)
                {
                    previewParamValues.Add(paramRef.Name, paramRef.Default);
                }
            }
            eventPosition = new Vector2(0, 0);
        }
Пример #4
0
        //Rect previewPathRect;

        private void PreviewEvent(Rect previewRect, EditorEventRef selectedEvent)
        {
            GUILayout.BeginArea(previewRect);

            bool isNarrow = previewRect.width < 400;

            var style = new GUIStyle(EditorStyles.label);

            EditorStyles.label.fontStyle = FontStyle.Bold;
            EditorGUIUtility.labelWidth  = 75;

            var copyIcon = EditorGUIUtility.Load("FMOD/CopyIcon.png") as Texture;

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Full Path", selectedEvent.Path, style, GUILayout.ExpandWidth(true));
            if (GUILayout.Button(copyIcon, GUILayout.ExpandWidth(false)))
            {
                EditorGUIUtility.systemCopyBuffer = selectedEvent.Path;
            }
            EditorGUILayout.EndHorizontal();

            StringBuilder builder = new StringBuilder();

            selectedEvent.Banks.ForEach((x) => { builder.Append(Path.GetFileNameWithoutExtension(x.Path)); builder.Append(", "); });
            EditorGUILayout.LabelField("Banks", builder.ToString(0, Math.Max(0, builder.Length - 2)), style);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Panning", selectedEvent.Is3D ? "3D" : "2D", style);
            EditorGUILayout.LabelField("Oneshot", selectedEvent.IsOneShot.ToString(), style);

            TimeSpan t = System.TimeSpan.FromMilliseconds(selectedEvent.Length);

            EditorGUILayout.LabelField("Length", selectedEvent.Length > 0 ? string.Format("{0:D2}:{1:D2}:{2:D3}", t.Minutes, t.Seconds, t.Milliseconds) : "N/A", style);

            if (!isNarrow)
            {
                EditorGUILayout.LabelField("Streaming", selectedEvent.IsStream.ToString(), style);
            }
            EditorGUILayout.EndHorizontal();
            if (isNarrow)
            {
                EditorGUILayout.LabelField("Streaming", selectedEvent.IsStream.ToString(), style);
            }

            EditorGUIUtility.labelWidth  = 0;
            EditorStyles.label.fontStyle = FontStyle.Normal;

            if (Event.current.type == EventType.Repaint)
            {
                var lastRect = GUILayoutUtility.GetLastRect();
                if (!isNarrow)
                {
                    previewCustomRect = new Rect(lastRect.width / 2 - 200, lastRect.yMax + 10, 400, 150);
                }
                else
                {
                    previewCustomRect = new Rect(lastRect.width / 2 - 130, lastRect.yMax + 10, 260, 150);
                }
            }

            GUI.Box(new Rect(0, previewCustomRect.yMin, previewRect.width, 1), GUIContent.none);
            GUI.Box(new Rect(0, previewCustomRect.yMax, previewRect.width, 1), GUIContent.none);

            GUILayout.BeginArea(previewCustomRect);

            Texture playOff  = EditorGUIUtility.Load("FMOD/TransportPlayButtonOff.png") as Texture;
            Texture playOn   = EditorGUIUtility.Load("FMOD/TransportPlayButtonOn.png") as Texture;
            Texture stopOff  = EditorGUIUtility.Load("FMOD/TransportStopButtonOff.png") as Texture;
            Texture stopOn   = EditorGUIUtility.Load("FMOD/TransportStopButtonOn.png") as Texture;
            Texture openIcon = EditorGUIUtility.Load("FMOD/transportOpen.png") as Texture;

            var transportButtonStyle = new GUIStyle();

            transportButtonStyle.padding.left = 4;
            transportButtonStyle.padding.top  = 10;

            var  previewState = EditorUtils.PreviewState;
            bool playing      = previewState == PreviewState.Playing;
            bool paused       = previewState == PreviewState.Paused;
            bool stopped      = previewState == PreviewState.Stopped;

            EditorGUILayout.BeginVertical();
            if (!isNarrow)
            {
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.BeginHorizontal();

            if (GUILayout.Button(stopped || paused ? stopOn : stopOff, transportButtonStyle, GUILayout.ExpandWidth(false)))
            {
                forceRepaint = false;
                if (paused)
                {
                    EditorUtils.PreviewStop();
                }
                if (playing)
                {
                    EditorUtils.PreviewPause();
                }
            }
            if (GUILayout.Button(playing ? playOn : playOff, transportButtonStyle, GUILayout.ExpandWidth(false)))
            {
                if (playing || stopped)
                {
                    EditorUtils.PreviewEvent(selectedEvent);
                }
                else
                {
                    EditorUtils.PreviewPause();
                }
                forceRepaint = true;
            }
            if (GUILayout.Button(new GUIContent(openIcon, "Show Event in FMOD Studio"), transportButtonStyle, GUILayout.ExpandWidth(false)))
            {
                string cmd = string.Format("studio.window.navigateTo(studio.project.lookup(\"{0}\"))", selectedEvent.Guid.ToString("b"));
                EditorUtils.SendScriptCommand(cmd);
            }


            EditorGUILayout.EndHorizontal();
            if (!isNarrow)
            {
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.EndVertical();

            {
                Texture circle  = EditorGUIUtility.Load("FMOD/preview.png") as Texture;
                Texture circle2 = EditorGUIUtility.Load("FMOD/previewemitter.png") as Texture;

                var originalColour = GUI.color;
                if (!selectedEvent.Is3D)
                {
                    GUI.color = new Color(1.0f, 1.0f, 1.0f, 0.1f);
                }

                Rect rect = new Rect(isNarrow ? 120 : 150, 10, 128, 128);
                GUI.DrawTexture(rect, circle);

                Vector2 centre = rect.center;
                Rect    rect2  = new Rect(rect.center.x + eventPosition.x - 6, rect.center.y + eventPosition.y - 6, 12, 12);
                GUI.DrawTexture(rect2, circle2);

                GUI.color = originalColour;

                #if UNITY_2017_3_OR_NEWER
                if (selectedEvent.Is3D && (Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag) && rect.Contains(Event.current.mousePosition))
                #else
                if (selectedEvent.Is3D && (Event.current.type == EventType.mouseDown || Event.current.type == EventType.mouseDrag) && rect.Contains(Event.current.mousePosition))
                #endif
                {
                    var     newPosition = Event.current.mousePosition;
                    Vector2 delta       = (newPosition - centre);
                    float   distance    = delta.magnitude;
                    if (distance < 60)
                    {
                        eventPosition   = newPosition - rect.center;
                        previewDistance = distance / 60.0f * selectedEvent.MaxDistance;
                        delta.Normalize();
                        float angle = Mathf.Atan2(delta.y, delta.x);
                        previewOrientation = angle + Mathf.PI * 0.5f;
                    }
                    Event.current.Use();
                }

                EditorUtils.PreviewUpdatePosition(previewDistance, previewOrientation);
            }


            float   hoffset     = isNarrow ? 15 : 300;
            float   voffset     = isNarrow ? 50 : 10;
            Texture meterOn     = EditorGUIUtility.Load("FMOD/LevelMeter.png") as Texture;
            Texture meterOff    = EditorGUIUtility.Load("FMOD/LevelMeterOff.png") as Texture;
            float[] metering    = EditorUtils.GetMetering();
            int     meterHeight = isNarrow ? 86 : 128;
            int     meterWidth  = (int)((128 / (float)meterOff.height) * meterOff.width);
            foreach (float rms in metering)
            {
                GUI.DrawTexture(new Rect(hoffset, voffset, meterWidth, meterHeight), meterOff);

                float db = 20.0f * Mathf.Log10(rms * Mathf.Sqrt(2.0f));
                db = Mathf.Clamp(db, -80.0f, 10.0f);
                float   visible       = 0;
                int[]   segmentPixels = new int[] { 0, 18, 38, 60, 89, 130, 187, 244, 300 };
                float[] segmentDB     = new float[] { -80.0f, -60.0f, -50.0f, -40.0f, -30.0f, -20.0f, -10.0f, 0, 10.0f };
                int     segment       = 1;
                while (segmentDB[segment] < db)
                {
                    segment++;
                }
                visible = segmentPixels[segment - 1] + ((db - segmentDB[segment - 1]) / (segmentDB[segment] - segmentDB[segment - 1])) * (segmentPixels[segment] - segmentPixels[segment - 1]);

                visible *= meterHeight / (float)meterOff.height;

                Rect levelPosRect = new Rect(hoffset, meterHeight - visible + voffset, meterWidth, visible);
                Rect levelUVRect  = new Rect(0, 0, 1.0f, visible / meterHeight);
                GUI.DrawTextureWithTexCoords(levelPosRect, meterOn, levelUVRect);
                hoffset += meterWidth + 5.0f;
            }

            GUILayout.EndArea();

            Rect paramRect = new Rect(0, previewCustomRect.yMax + 10, previewRect.width, previewRect.height - (previewCustomRect.yMax + 10));
            GUILayout.BeginArea(paramRect);

            paramScroll = GUILayout.BeginScrollView(paramScroll, false, false);
            foreach (var paramRef in selectedEvent.Parameters)
            {
                if (!previewParamValues.ContainsKey(paramRef.Name))
                {
                    previewParamValues[paramRef.Name] = paramRef.Default;
                }
                previewParamValues[paramRef.Name] = EditorGUILayout.Slider(paramRef.Name, previewParamValues[paramRef.Name], paramRef.Min, paramRef.Max);
                EditorUtils.PreviewUpdateParameter(paramRef.Name, previewParamValues[paramRef.Name]);
            }
            GUILayout.EndScrollView();

            GUILayout.EndArea();
            GUILayout.EndArea();
        }
Пример #5
0
 void OnDestroy()
 {
     EditorUtils.PreviewStop();
 }
Пример #6
0
        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 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();
            }
        }
Пример #8
0
        void OnGUI()
        {
            if (!EventManager.IsLoaded)
            {
                this.ShowNotification(new GUIContent("No FMOD Studio banks loaded. Please check your settings."));
                return;
            }

            if (Event.current.type == EventType.Layout)
            {
                RebuildDisplayFromCache();
            }

            //if (eventStyle == null)
            {
                eventStyle = new GUIStyle(GUI.skin.button);
                eventStyle.normal.background    = null;
                eventStyle.focused.background   = null;
                eventStyle.active.background    = null;
                eventStyle.onFocused.background = null;
                eventStyle.onNormal.background  = null;
                eventStyle.onHover.background   = null;
                eventStyle.onActive.background  = null;
                eventStyle.stretchWidth         = false;
                eventStyle.padding.left         = 0;
                eventStyle.stretchHeight        = false;
                eventStyle.fixedHeight          = eventStyle.lineHeight + eventStyle.margin.top + eventStyle.margin.bottom;
                eventStyle.alignment            = TextAnchor.MiddleLeft;

                eventIcon        = EditorGUIUtility.Load("FMOD/EventIcon.png") as Texture;
                folderOpenIcon   = EditorGUIUtility.Load("FMOD/FolderIconOpen.png") as Texture;
                folderClosedIcon = EditorGUIUtility.Load("FMOD/FolderIconClosed.png") as Texture;
                searchIcon       = EditorGUIUtility.Load("FMOD/SearchIcon.png") as Texture;
                bankIcon         = EditorGUIUtility.Load("FMOD/BankIcon.png") as Texture;
                snapshotIcon     = EditorGUIUtility.Load("FMOD/SnapshotIcon.png") as Texture;
            }

            // Split the window int search box, tree view, preview pane (only if full browser)
            Rect  searchRect       = new Rect(0, 0, position.width, 16);
            float previewBoxHeight = fromInspector ? 0 : 400;
            Rect  listRect         = new Rect(0, searchRect.height + 2, position.width, position.height - previewBoxHeight - searchRect.height - 15);
            Rect  previewRect      = new Rect(0, position.height - previewBoxHeight, position.width, previewBoxHeight);

            // Scroll the selected item in the tree view - put above the search box otherwise it will take
            // our key presses
            if (selectedItem != null && Event.current.type == EventType.keyDown)
            {
                if (Event.current.keyCode == KeyCode.UpArrow)
                {
                    if (selectedItem.Prev != null)
                    {
                        SetSelectedItem(selectedItem.Prev);

                        // make sure it's visible
                        if (selectedItem.Rect.y < treeScroll.y)
                        {
                            treeScroll.y = selectedItem.Rect.y;
                        }
                    }
                    Event.current.Use();
                }
                if (Event.current.keyCode == KeyCode.DownArrow)
                {
                    if (selectedItem.Next != null)
                    {
                        SetSelectedItem(selectedItem.Next);
                        // make sure it's visible
                        if (selectedItem.Rect.y + selectedItem.Rect.height > treeScroll.y + listRect.height)
                        {
                            treeScroll.y += (selectedItem.Rect.y + selectedItem.Rect.height) - listRect.height;
                        }
                    }
                    Event.current.Use();
                }
            }

            // Show the search box at the top
            GUILayout.BeginArea(searchRect);
            GUILayout.BeginHorizontal();
            GUILayout.Label(new GUIContent(searchIcon), GUILayout.ExpandWidth(false));
            GUI.SetNextControlName("SearchBox");
            searchString = GUILayout.TextField(searchString);
            GUILayout.EndHorizontal();
            GUILayout.EndArea();

            if (fromInspector)
            {
                GUI.FocusControl("SearchBox");

                if (selectedItem != null && Event.current.isKey && Event.current.keyCode == KeyCode.Return)
                {
                    Event.current.Use();

                    if (selectedItem.EventRef != null)
                    {
                        outputProperty.stringValue = selectedItem.EventRef.Path;
                        EditorUtils.UpdateParamsOnEmmitter(outputProperty.serializedObject);
                    }
                    else
                    {
                        outputProperty.stringValue = selectedItem.BankRef.Name;
                    }
                    outputProperty.serializedObject.ApplyModifiedProperties();
                    Close();
                }
            }

            // Show the tree view

            Predicate <TreeItem> searchFilter = null;

            searchFilter = (x) => (x.Name.ToLower().Contains(searchString.ToLower()) || x.Children.Exists(searchFilter));

            // Check if our selected item still matches the search string
            if (selectedItem != null && !String.IsNullOrEmpty(searchString))
            {
                Predicate <TreeItem> containsSelected = null;
                containsSelected = (x) => (x == selectedItem || x.Children.Exists(containsSelected));
                Predicate <TreeItem> matchForSelected = null;
                matchForSelected = (x) => (x.Name.ToLower().Contains(searchString.ToLower()) && (x == selectedItem || x.Children.Exists(containsSelected))) || x.Children.Exists(matchForSelected);
                if (!treeItems.Exists(matchForSelected))
                {
                    SetSelectedItem(null);
                }
            }

            GUILayout.BeginArea(listRect);
            treeScroll = GUILayout.BeginScrollView(treeScroll, GUILayout.ExpandHeight(true));

            lastDrawnItem = null;
            itemCount     = 0;

            if (showEvents)
            {
                treeItems[0].Expanded = fromInspector ? true : treeItems[0].Expanded;
                ShowEventFolder(treeItems[0], searchFilter);
                ShowEventFolder(treeItems[1], searchFilter);
            }
            if (showBanks)
            {
                treeItems[2].Expanded = fromInspector ? true : treeItems[2].Expanded;
                ShowEventFolder(treeItems[2], searchFilter);
            }

            GUILayout.EndScrollView();
            GUILayout.EndArea();

            // If the standalone event browser show a preview of the selected item
            if (!fromInspector)
            {
                Rect previewAutoRect = new Rect(previewRect);
                previewAutoRect.height -= 140;
                Rect previewCustomBox = new Rect(previewRect);
                previewCustomBox.y      = previewAutoRect.y + previewAutoRect.height + 10;
                previewCustomBox.height = 128;


                GUI.Box(previewRect, GUIContent.none);


                if (selectedItem != null && selectedItem.EventRef != null && selectedItem.EventRef.Path.StartsWith("event:"))
                {
                    GUILayout.BeginArea(previewAutoRect);

                    var style = new GUIStyle(GUI.skin.FindStyle("label"));
                    style.richText = true;

                    var selectedEvent = selectedItem.EventRef;

                    // path
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Full Path</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.Path);
                    EditorGUILayout.EndHorizontal();

                    // guid
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>GUID</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.Guid.ToString("b"));
                    EditorGUILayout.EndHorizontal();

                    // Bank
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Bank</b>", style, style);
                    StringBuilder builder = new StringBuilder();
                    selectedEvent.Banks.ForEach((x) => { builder.Append(Path.GetFileNameWithoutExtension(x.Path)); builder.Append(", "); });
                    EditorGUILayout.LabelField(builder.ToString(0, Math.Max(0, builder.Length - 2)));
                    EditorGUILayout.EndHorizontal();

                    // Panning
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Panning</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.Is3D ? "3D" : "2D");
                    EditorGUILayout.EndHorizontal();

                    // One shot
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Oneshot</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.IsOneShot.ToString());
                    EditorGUILayout.EndHorizontal();

                    // Streaming
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Streaming</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.IsStream.ToString());
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    if (GUILayout.Button("Play"))
                    {
                        EditorUtils.PreviewEvent(selectedEvent);
                        forceRepaint = true;
                    }
                    if (GUILayout.Button("Pause"))
                    {
                        EditorUtils.PreviewPause();
                    }
                    if (GUILayout.Button("Stop"))
                    {
                        forceRepaint = false;
                        EditorUtils.PreviewStop();
                    }
                    if (GUILayout.Button("Show In Studio"))
                    {
                        string cmd = string.Format("studio.window.navigateTo(studio.project.lookup(\"{0}\"))", selectedEvent.Guid.ToString("b"));
                        EditorUtils.SendScriptCommand(cmd);
                    }
                    EditorGUILayout.EndHorizontal();

                    paramScroll = GUILayout.BeginScrollView(paramScroll, false, true);
                    foreach (var paramRef in selectedEvent.Parameters)
                    {
                        if (!previewParamValues.ContainsKey(paramRef.Name))
                        {
                            previewParamValues[paramRef.Name] = 0;
                        }
                        previewParamValues[paramRef.Name] = EditorGUILayout.Slider(paramRef.Name, previewParamValues[paramRef.Name], paramRef.Min, paramRef.Max);
                        EditorUtils.PreviewUpdateParameter(paramRef.Name, previewParamValues[paramRef.Name]);
                    }
                    GUILayout.EndScrollView();

                    GUILayout.EndArea();

                    GUILayout.BeginArea(previewCustomBox);



                    if (selectedEvent.Is3D)
                    {
                        Texture circle  = EditorGUIUtility.Load("FMOD/preview.png") as Texture;
                        Texture circle2 = EditorGUIUtility.Load("FMOD/previewemitter.png") as Texture;
                        Rect    rect    = new Rect(position.width / 2.0f - 150f, 0, 128, 128);
                        GUI.DrawTexture(rect, circle);

                        Vector2 centre = rect.center;

                        Rect rect2 = new Rect(rect.center + eventPosition - new Vector2(6, 6), new Vector2(12, 12));
                        GUI.DrawTexture(rect2, circle2);


                        if ((Event.current.type == EventType.mouseDown || Event.current.type == EventType.mouseDrag) && rect.Contains(Event.current.mousePosition))
                        {
                            var     newPosition = Event.current.mousePosition;
                            Vector2 delta       = (newPosition - centre);
                            float   distance    = delta.magnitude;
                            if (distance < 60)
                            {
                                eventPosition   = newPosition - rect.center;
                                previewDistance = distance / 60.0f * selectedEvent.MaxDistance;
                                delta.Normalize();
                                float angle = Mathf.Atan2(delta.y, delta.x);
                                previewOrientation = angle + Mathf.PI * 0.5f;
                            }
                            Event.current.Use();
                        }

                        EditorUtils.PreviewUpdatePosition(previewDistance, previewOrientation);
                    }


                    float   offset      = position.width / 2.0f;
                    Texture meterOn     = EditorGUIUtility.Load("FMOD/LevelMeter.png") as Texture;
                    Texture meterOff    = EditorGUIUtility.Load("FMOD/LevelMeterOff.png") as Texture;
                    float[] metering    = EditorUtils.GetMetering();
                    int     meterHeight = 128;
                    int     meterWidth  = (int)((128 / (float)meterOff.height) * meterOff.width);
                    foreach (float rms in metering)
                    {
                        GUI.DrawTexture(new Rect(offset, 0, meterWidth, meterHeight), meterOff);

                        float db = rms > 0 ? 20.0f * Mathf.Log10(rms * Mathf.Sqrt(2.0f)) : -80.0f;
                        if (db > 10.0f)
                        {
                            db = 10.0f;
                        }
                        float   visible       = 0;
                        int[]   segmentPixels = new int[] { 0, 18, 38, 60, 89, 130, 187, 244, 300 };
                        float[] segmentDB     = new float[] { -80.0f, -60.0f, -50.0f, -40.0f, -30.0f, -20.0f, -10.0f, 0, 10.0f };
                        int     segment       = 1;
                        while (segmentDB[segment] < db)
                        {
                            segment++;
                        }
                        visible  = segmentPixels[segment - 1] + ((db - segmentDB[segment - 1]) / (segmentDB[segment] - segmentDB[segment - 1])) * (segmentPixels[segment] - segmentPixels[segment - 1]);
                        visible *= 128 / (float)meterOff.height;
                        Rect levelPosRect = new Rect(offset, 128 - visible, meterWidth, visible);
                        Rect levelUVRect  = new Rect(0, 0, 1.0f, visible / meterHeight);
                        GUI.DrawTextureWithTexCoords(levelPosRect, meterOn, levelUVRect);
                        offset += meterWidth + 5.0f;
                    }
                    GUILayout.EndArea();
                }


                if (selectedItem != null && selectedItem.EventRef != null && selectedItem.EventRef.Path.StartsWith("snapshot:"))
                {
                    GUILayout.BeginArea(previewAutoRect);

                    var style = new GUIStyle(GUI.skin.FindStyle("label"));
                    style.richText = true;

                    var selectedEvent = selectedItem.EventRef;

                    // path
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>Full Path</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.Path);
                    EditorGUILayout.EndHorizontal();

                    // guid
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PrefixLabel("<b>GUID</b>", style, style);
                    EditorGUILayout.LabelField(selectedEvent.Guid.ToString("b"));
                    EditorGUILayout.EndHorizontal();

                    GUILayout.EndArea();
                }

                if (selectedItem != null && selectedItem.BankRef != null)
                {
                    GUILayout.BeginArea(previewRect);
                    string[] SizeSuffix   = { "B", "KB", "MB", "GB" };
                    var      selectedBank = selectedItem.BankRef;
                    var      style        = new GUIStyle(GUI.skin.FindStyle("label"));
                    style.richText = true;
                    GUILayout.Label("<b>Platform Bank Sizes</b>", style);
                    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--;

                    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;

                    AssetDatabase.CreateAsset(eventCache, CacheAssetFullName);
                }
            }

            if (EditorUtils.GetBankDirectory() == null)
            {
                ClearCache();
                return;
            }

            string defaultBankFolder = null;

            if (!Settings.Instance.HasPlatforms)
            {
                defaultBankFolder = EditorUtils.GetBankDirectory();
            }
            else
            {
                FMODPlatform platform = EditorUtils.GetFMODPlatform();
                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)));
            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

            // Stop editor preview so no stale data being held
            EditorUtils.PreviewStop();

            // Reload the strings bank
            EditorUtils.CheckResult(EditorUtils.System.loadBankFile(stringBankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out stringBank));
            if (stringBank == null)
            {
                ClearCache();
                return;
            }
            FileInfo stringBankFileInfo = new FileInfo(stringBankPath);

            eventCache.StringsBankWriteTime = stringBankFileInfo.LastWriteTime;
            string masterBankFileName = Path.GetFileName(stringBankPath).Replace(StringBankExtension, BankExtension);

            AssetDatabase.StartAssetEditing();

            if (eventCache.StringsBankRef == null)
            {
                eventCache.StringsBankRef           = ScriptableObject.CreateInstance <EditorBankRef>();
                eventCache.StringsBankRef.FileSizes = new List <EditorBankRef.NameValuePair>();
                eventCache.EditorBanks.Add(eventCache.StringsBankRef);
                AssetDatabase.AddObjectToAsset(eventCache.StringsBankRef, eventCache);
                AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(eventCache.StringsBankRef));
            }
            eventCache.StringsBankRef.Path         = stringBankPath;
            eventCache.StringsBankRef.LastModified = eventCache.StringsBankWriteTime;
            eventCache.StringsBankRef.FileSizes.Clear();
            if (Settings.Instance.HasPlatforms)
            {
                for (int i = 0; i < bankPlatforms.Length; i++)
                {
                    eventCache.StringsBankRef.FileSizes.Add(new EditorBankRef.NameValuePair(bankPlatforms[i], stringBankFileInfo.Length));
                }
            }
            else
            {
                eventCache.StringsBankRef.FileSizes.Add(new EditorBankRef.NameValuePair("", stringBankFileInfo.Length));
            }

            eventCache.EditorBanks.ForEach((x) => x.Exists = false);
            eventCache.StringsBankRef.Exists = true;

            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();
                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 (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();
            AssetDatabase.StopAssetEditing();
        }