public static bool OnDoubleClickAssets(int instanceID, int line)
        {
            string assetPath = AssetDatabase.GetAssetPath(instanceID);
            AudioFileSoundObject audioFile = AssetDatabase.LoadAssetAtPath <AudioFileSoundObject>(assetPath);

            if (audioFile)
            {
                Init();
                // Force a repaint
                Selection.activeObject       = null;
                EditorApplication.delayCall += () => Selection.activeObject = audioFile;
                return(true);
            }
            AudioFileMusicObject audioFileMusic = AssetDatabase.LoadAssetAtPath <AudioFileMusicObject>(assetPath);

            if (audioFileMusic)
            {
                Init();
                // Force a repaint
                Selection.activeObject       = null;
                EditorApplication.delayCall += () => Selection.activeObject = audioFileMusic;
                return(true);
            }
            return(false);
        }
        /// <summary>
        /// Conveniently draws a progress bar
        /// Referenced from the official Unity documentation
        /// https://docs.unity3d.com/ScriptReference/Editor.html
        /// </summary>
        /// <param name="value"></param>
        /// <param name="label"></param>
        /// <returns></returns>
        public static Rect ProgressBar(float value, AudioClip selectedClip, AudioFileSoundObject selectedSound = null, AudioFileMusicObject selectedMusic = null)
        {
            // Get a rect for the progress bar using the same margins as a text field
            // TODO: Make this dynamic, locks its previous size before showing the guide
            float maxHeight = (showHowTo) ? playbackPreviewClamped : 4000;
            float minHeight = (showHowTo) ? playbackPreviewClamped : 64;
            Rect  rect      = GUILayoutUtility.GetRect(64, 4000, minHeight, maxHeight);

            if (cachedTex == null || forceRepaint)
            {
                Texture2D waveformTexture;
                if (selectedSound)
                {
                    waveformTexture = AudioFileSoundObjectEditor.instance.PaintWaveformSpectrum(helperSource.clip, (int)rect.width, (int)rect.height, new Color(1, 0.5f, 0));
                }
                else if (selectedMusic)
                {
                    waveformTexture = AudioFileMusicObjectEditor.instance.PaintWaveformSpectrum(selectedClip, (int)rect.width, (int)rect.height, new Color(1, 0.5f, 0));
                }
                else
                {
                    waveformTexture = PaintWaveformSpectrum(selectedClip, (int)rect.width, (int)rect.height, new Color(1, 0.5f, 0));
                }
                cachedTex = waveformTexture;

                if (waveformTexture != null)
                {
                    GUI.DrawTexture(rect, waveformTexture);
                }
                forceRepaint = false;
            }
            else
            {
                GUI.DrawTexture(rect, cachedTex);
            }

            float left  = CalculateZoomedLeftValue();
            float right = CalculateZoomedRightValue();

            if (value >= left && value <= right)
            {
                Rect progressRect = new Rect(rect);
                progressRect.width *= Mathf.InverseLerp(left, right, value);
                progressRect.xMin   = progressRect.xMax - 1;
                GUI.Box(progressRect, "", "SelectionRect");
            }

            EditorGUILayout.Space();

            return(rect);
        }
        private void OnSelectionChange()
        {
            if (Selection.activeObject == null)
            {
                return;
            }
            System.Type activeType = Selection.activeObject.GetType();

            selectedClip  = null;
            selectedSound = null;
            selectedMusic = null;

            if (activeType.Equals(typeof(AudioClip)))
            {
                selectedClip = (AudioClip)Selection.activeObject;
                CreateAudioHelper(selectedClip);
            }
            else if (activeType.Equals(typeof(AudioFileSoundObject)))
            {
                selectedSound = ((AudioFileSoundObject)Selection.activeObject);
                selectedClip  = selectedSound.file;
                CreateAudioHelper(selectedClip);
            }
            else if (activeType.Equals(typeof(AudioFileMusicObject)))
            {
                selectedMusic = ((AudioFileMusicObject)Selection.activeObject);
                selectedClip  = selectedMusic.file;
                CreateAudioHelper(selectedClip, true);
            }
            else
            {
                DoForceRepaint(true);
                return;
            }
            helperSource.clip = selectedClip;

            DoForceRepaint(true);
        }
        /// <summary>
        /// Draws a playback
        /// </summary>
        /// <param name="music"></param>
        public void DrawPlaybackTool(AudioClip selectedClip, AudioFileSoundObject selectedSound = null, AudioFileMusicObject selectedMusic = null)
        {
            Rect progressRect = ProgressBar((float)helperSource.timeSamples / (float)helperSource.clip.samples, selectedClip, selectedSound, selectedMusic);

            EditorGUI.BeginChangeCheck();
            scrollbarProgress = GUILayout.HorizontalScrollbar(scrollbarProgress, scrollZoom, 0, MAX_SCROLL_ZOOM);
            if (EditorGUI.EndChangeCheck())
            {
                DoForceRepaint(true);
            }

            EditorGUILayout.BeginHorizontal();

            PollMouseEvents(progressRect);

            if (GUILayout.Button(s_BackIcon, new GUILayoutOption[] { GUILayout.MaxHeight(20) }))
            {
                if (selectedMusic)
                {
                    if (selectedMusic.loopMode == LoopMode.LoopWithLoopPoints && selectedMusic.clampToLoopPoints)
                    {
                        helperSource.timeSamples = Mathf.CeilToInt((selectedMusic.loopStart * selectedClip.frequency));
                    }
                }
                else
                {
                    helperSource.timeSamples = 0;
                }
                helperSource.Stop();
                mouseScrubbed = false;
                clipPaused    = false;
                clipPlaying   = false;
            }

            // Draw Play Button
            Color      colorbackup = GUI.backgroundColor;
            GUIContent buttonIcon  = (clipPlaying) ? s_PlayIcons[1] : s_PlayIcons[0];

            if (clipPlaying)
            {
                GUI.backgroundColor = buttonPressedColor;
            }
            if (GUILayout.Button(buttonIcon, new GUILayoutOption[] { GUILayout.MaxHeight(20) }))
            {
                clipPlaying = !clipPlaying;
                if (clipPlaying)
                {
                    // Note: For some reason, reading from helperSource.time returns 0 even if timeSamples is not 0
                    // However, writing a value to helperSource.time changes timeSamples to the appropriate value just fine
                    if (selectedSound)
                    {
                        AudioFileSoundObjectEditor.instance.StartFading(helperSource.clip);
                    }
                    else if (selectedMusic)
                    {
                        helperHelper.PlayDebug(selectedMusic, mouseScrubbed);
                        AudioFileMusicObjectEditor.firstPlayback = true;
                        AudioFileMusicObjectEditor.freePlay      = false;
                    }
                    else if (selectedClip)
                    {
                        helperHelper.PlayDebug(mouseScrubbed);
                    }
                    if (clipPaused)
                    {
                        helperSource.Pause();
                    }
                }
                else
                {
                    helperSource.Stop();
                    if (!mouseScrubbed)
                    {
                        helperSource.time = 0;
                    }
                    clipPaused = false;
                }
            }

            // Pause button
            GUI.backgroundColor = colorbackup;
            GUIContent theText = (clipPaused) ? s_PauseIcons[1] : s_PauseIcons[0];

            if (clipPaused)
            {
                GUI.backgroundColor = buttonPressedColor;
            }
            if (GUILayout.Button(theText, new GUILayoutOption[] { GUILayout.MaxHeight(20) }))
            {
                clipPaused = !clipPaused;
                if (clipPaused)
                {
                    helperSource.Pause();
                }
                else
                {
                    helperSource.UnPause();
                }
            }

            // Loop button
            GUI.backgroundColor = colorbackup;
            buttonIcon          = (loopClip) ? s_LoopIcons[1] : s_LoopIcons[0];
            if (loopClip)
            {
                GUI.backgroundColor = buttonPressedColor;
            }
            if (GUILayout.Button(buttonIcon, new GUILayoutOption[] { GUILayout.MaxHeight(20) }))
            {
                loopClip = !loopClip;
                // helperSource.loop = true;
            }
            GUI.backgroundColor = colorbackup;

            if (selectedSound)
            {
                using (new EditorGUI.DisabledScope(selectedSound.GetFileCount() < 2))
                {
                    if (GUILayout.Button(new GUIContent("Play Random", "Preview settings with a random track from your library. Only usable if this Audio File has \"Use Library\" enabled.")))
                    {
                        selectedClip = AudioFileSoundObjectEditor.instance.DesignateRandomAudioClip();
                        clipPlaying  = true;
                        helperSource.Stop();
                        AudioFileSoundObjectEditor.instance.StartFading(selectedClip);
                    }
                }
            }

            int loopPointInputMode = 0;

            // Reset loop point input mode if not using loop points so the duration shows up as time by default
            if (selectedMusic)
            {
                if (selectedMusic.loopMode != LoopMode.LoopWithLoopPoints)
                {
                    loopPointInputMode = 0;
                }
            }

            GUIContent blontent = new GUIContent();

            switch ((AudioFileMusicObjectEditor.LoopPointTool)loopPointInputMode)
            {
            case AudioFileMusicObjectEditor.LoopPointTool.Slider:
            case AudioFileMusicObjectEditor.LoopPointTool.TimeInput:
                blontent = new GUIContent(TimeToString((float)helperSource.timeSamples / helperSource.clip.frequency) + " / " + (TimeToString(helperSource.clip.length)),
                                          "The playback time in seconds");
                break;

            case AudioFileMusicObjectEditor.LoopPointTool.TimeSamplesInput:
                blontent = new GUIContent(helperSource.timeSamples + " / " + helperSource.clip.samples, "The playback time in samples");
                break;

            case AudioFileMusicObjectEditor.LoopPointTool.BPMInput:
                blontent = new GUIContent(string.Format("{0:0}", helperSource.time / (60f / selectedMusic.bpm)) + " / " + helperSource.clip.length / (60f / selectedMusic.bpm),
                                          "The playback time in beats");
                break;
            }
            GUIStyle rightJustified = new GUIStyle(EditorStyles.label);

            rightJustified.alignment = TextAnchor.UpperRight;
            EditorGUILayout.LabelField(blontent, rightJustified);

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
        }