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); }
new protected void OnEnable() { base.OnEnable(); myScript = target as AudioFileMusicObject; SetupIcons(); EditorApplication.update += Update; Undo.undoRedoPerformed += OnUndoRedo; AudioPlaybackToolEditor.CreateAudioHelper(myScript.GetFile(), true); Undo.postprocessModifications += ApplyHelperEffects; loopMode = FindProp("loopMode"); clampToLoopPoints = FindProp("clampToLoopPoints"); loopStartProperty = FindProp("loopStart"); loopEndProperty = FindProp("loopEnd"); }
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> /// 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); }
/// <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(); }
void Update() { AudioFileMusicObject myScript = (AudioFileMusicObject)target; if (myScript == null) { return; } AudioClip music = myScript.GetFile(); if (music != cachedClip) { AudioPlaybackToolEditor.DoForceRepaint(true); cachedClip = music; AudioPlaybackToolEditor.helperSource.clip = cachedClip; } if (!AudioPlaybackToolEditor.helperSource.isPlaying && mouseDragging) { Repaint(); } if ((clipPlaying && !clipPaused) || (mouseDragging && clipPlaying)) { float clipPos = AudioPlaybackToolEditor.helperSource.timeSamples / (float)music.frequency; AudioPlaybackToolEditor.helperSource.volume = myScript.relativeVolume; AudioPlaybackToolEditor.helperSource.pitch = myScript.startingPitch; Repaint(); if (loopClip) { EditorApplication.QueuePlayerLoopUpdate(); if (myScript.loopMode == LoopMode.LoopWithLoopPoints) { if (!AudioPlaybackToolEditor.helperSource.isPlaying && clipPlaying && !clipPaused) { if (freePlay) { AudioPlaybackToolEditor.helperSource.Play(); } else { AudioPlaybackToolEditor.helperSource.Play(); AudioPlaybackToolEditor.helperSource.timeSamples = Mathf.CeilToInt(myScript.loopStart * music.frequency); } freePlay = false; } else if (myScript.clampToLoopPoints || !firstPlayback) { if (clipPos < myScript.loopStart || clipPos > myScript.loopEnd) { // CeilToInt to guarantee clip position stays within loop bounds AudioPlaybackToolEditor.helperSource.timeSamples = Mathf.CeilToInt(myScript.loopStart * music.frequency); firstPlayback = false; } } else if (clipPos >= myScript.loopEnd) { AudioPlaybackToolEditor.helperSource.timeSamples = Mathf.CeilToInt(myScript.loopStart * music.frequency); firstPlayback = false; } } } else if (!loopClip && myScript.loopMode == LoopMode.LoopWithLoopPoints) { if ((!AudioPlaybackToolEditor.helperSource.isPlaying && !clipPaused) || clipPos > myScript.loopEnd) { clipPlaying = false; AudioPlaybackToolEditor.helperSource.Stop(); } else if (myScript.clampToLoopPoints && clipPos < myScript.loopStart) { AudioPlaybackToolEditor.helperSource.timeSamples = Mathf.CeilToInt(myScript.loopStart * music.frequency); } } } if (myScript.loopMode != LoopMode.LoopWithLoopPoints) { if (!AudioPlaybackToolEditor.helperSource.isPlaying && !clipPaused && clipPlaying) { AudioPlaybackToolEditor.helperSource.time = 0; if (loopClip) { AudioPlaybackToolEditor.helperSource.Play(); } else { clipPlaying = false; } } } }
/// <summary> /// Draws a playback /// </summary> /// <param name="music"></param> public void DrawPlaybackTool(AudioFileMusicObject myScript) { GUIContent blontent = new GUIContent("Audio Playback Preview", "Allows you to preview how your AudioFileMusicObject will sound during runtime right here in the inspector. " + "Some effects, like spatialization, will not be available to preview"); showPlaybackTool = EditorCompatability.SpecialFoldouts(showPlaybackTool, blontent); if (showPlaybackTool) { AudioClip music = myScript.GetFile(); Rect progressRect = ProgressBar((float)AudioPlaybackToolEditor.helperSource.timeSamples / (float)AudioPlaybackToolEditor.helperSource.clip.samples, GetInfoString()); EditorGUILayout.BeginHorizontal(); Event evt = Event.current; if (evt.isMouse) { switch (evt.type) { case EventType.MouseUp: mouseDragging = false; break; case EventType.MouseDown: case EventType.MouseDrag: if (evt.type == EventType.MouseDown) { if (evt.mousePosition.y > progressRect.yMin && evt.mousePosition.y < progressRect.yMax) { mouseDragging = true; mouseScrubbed = true; } else { mouseDragging = false; } } if (!mouseDragging) { break; } float newProgress = Mathf.InverseLerp(progressRect.xMin, progressRect.xMax, evt.mousePosition.x); AudioPlaybackToolEditor.helperSource.time = Mathf.Clamp((newProgress * music.length), 0, music.length - AudioManager.EPSILON); if (myScript.loopMode == LoopMode.LoopWithLoopPoints && myScript.clampToLoopPoints) { float start = myScript.loopStart * myScript.GetFile().frequency; float end = myScript.loopEnd * myScript.GetFile().frequency; AudioPlaybackToolEditor.helperSource.timeSamples = (int)Mathf.Clamp(AudioPlaybackToolEditor.helperSource.timeSamples, start, end - AudioManager.EPSILON); } break; } } if (GUILayout.Button(s_BackIcon, new GUILayoutOption[] { GUILayout.MaxHeight(20) })) { if (myScript.loopMode == LoopMode.LoopWithLoopPoints && myScript.clampToLoopPoints) { AudioPlaybackToolEditor.helperSource.timeSamples = Mathf.CeilToInt((myScript.loopStart * music.frequency)); } else { AudioPlaybackToolEditor.helperSource.timeSamples = 0; } AudioPlaybackToolEditor.helperSource.Stop(); mouseScrubbed = false; clipPaused = false; clipPlaying = false; } 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 AudioPlaybackToolEditor.helperSource.time returns 0 even if timeSamples is not 0 // However, writing a value to AudioPlaybackToolEditor.helperSource.time changes timeSamples to the appropriate value just fine AudioPlaybackToolEditor.helperHelper.PlayDebug(myScript, mouseScrubbed); if (clipPaused) { AudioPlaybackToolEditor.helperSource.Pause(); } firstPlayback = true; freePlay = false; } else { AudioPlaybackToolEditor.helperSource.Stop(); if (!mouseScrubbed) { AudioPlaybackToolEditor.helperSource.time = 0; } clipPaused = false; } } 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) { AudioPlaybackToolEditor.helperSource.Pause(); } else { AudioPlaybackToolEditor.helperSource.UnPause(); } } 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; // AudioPlaybackToolEditor.helperSource.loop = true; } GUI.backgroundColor = colorbackup; if (GUILayout.Button(openIcon, new GUILayoutOption[] { GUILayout.MaxHeight(19) })) { AudioPlaybackToolEditor.Init(); } // Reset loop point input mode if not using loop points so the duration shows up as time by default if (myScript.loopMode != LoopMode.LoopWithLoopPoints) { loopPointInputMode = 0; } switch ((LoopPointTool)loopPointInputMode) { case LoopPointTool.Slider: case LoopPointTool.TimeInput: blontent = new GUIContent(AudioPlaybackToolEditor.TimeToString((float)AudioPlaybackToolEditor.helperSource.timeSamples / music.frequency) + " / " + (AudioPlaybackToolEditor.TimeToString(music.length)), "The playback time in seconds"); break; case LoopPointTool.TimeSamplesInput: blontent = new GUIContent(AudioPlaybackToolEditor.helperSource.timeSamples + " / " + music.samples, "The playback time in samples"); break; case LoopPointTool.BPMInput: blontent = new GUIContent(string.Format("{0:0}", AudioPlaybackToolEditor.helperSource.time / (60f / myScript.bpm)) + " / " + music.length / (60f / myScript.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(); } EditorCompatability.EndSpecialFoldoutGroup(); }