#if UNITY_EDITOR using System; using UnityEditor; using System.Collections.Generic; using UnityEngine; using Wwise.Wooduan.Core; namespace Wwise.Wooduan.Tools { public class AudioConsole : EditorWindow { private readonly Queue _messages = new Queue(); private static Dictionary _componentInclusions = new Dictionary(); private static Dictionary _eventInclusions = new Dictionary(); private static Dictionary _gameSyncInclusions = new Dictionary(); private static Dictionary _spatialAudioInclusions = new Dictionary(); private bool _includeComponents = true; private bool _includeCode = true; private bool _includeConfig = true; private bool _includeSoundCaster = true; private bool _includeNotification = true; private bool _includeWarning = true; private bool _includeError = true; private bool _includeEvent = true; private bool _includeGameSync = true; private bool _includeBank = true; private bool _includeSpatialAudio = true; private bool _paused; private string _objectNameFilter; private void AddLog(AudioConsoleLog message) { if (_paused) return; if (FilterLog(message)) _messages.Enqueue(message); Repaint(); } #region Init private void OnEnable() { AkWooduanHelper.ConsoleCallback += AddLog; RegisterComponents(); } private void RegisterComponents() { _componentInclusions["AnimationSound"] = true; _componentInclusions["AkAudioListener"] = true; _componentInclusions["AkAmbient"] = true; _componentInclusions["AkBank"] = true; _componentInclusions["AkRoom"] = true; _componentInclusions["AkOutdoor"] = true; _componentInclusions["AkRoomPortal"] = true; _componentInclusions["AkSurfaceReflector"] = true; _componentInclusions["ParticleSound"] = true; _componentInclusions["AkState"] = true; _componentInclusions["AkSwitch"] = true; _eventInclusions["SFX"] = true; _eventInclusions["Music"] = true; _eventInclusions["Voice"] = true; _gameSyncInclusions["State"] = true; _gameSyncInclusions["Switch"] = true; _gameSyncInclusions["RTPC"] = true; _spatialAudioInclusions["Room"] = true; _spatialAudioInclusions["Portal"] = true; _spatialAudioInclusions["AuxBus"] = true; _spatialAudioInclusions["Bus"] = true; _spatialAudioInclusions["Geometry"] = true; _spatialAudioInclusions["Occlusion"] = true; _spatialAudioInclusions["Obstruction"] = true; } private void OnDestroy() { AkWooduanHelper.ConsoleCallback = null; } private void Update() { if (_messages.Count > 200) _messages.Dequeue(); } #endregion #region GUI private bool _autoScroll = true; private Vector2 _scrollPosition; private void OnGUI() { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Display Filter", EditorStyles.boldLabel); EditorGUILayout.LabelField("Name Contains", GUILayout.Width(100)); _objectNameFilter = EditorGUILayout.TextField(_objectNameFilter); if (GUILayout.Button("Select All", GUILayout.Width(100))) SelectAll(true); if (GUILayout.Button("Deselect All", GUILayout.Width(100))) SelectAll(false); GUILayout.EndHorizontal(); DrawVerbosityOptions(); DrawTriggerOptions(); DrawTypeOptions(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Pause")) _paused = true; if (GUILayout.Button("Resume")) _paused = false; if (GUILayout.Button("Clear")) _messages.Clear(); _autoScroll = GUILayout.Toggle(_autoScroll, "Auto Scroll", GUILayout.Width(100)); GUILayout.EndHorizontal(); using (new EditorGUILayout.VerticalScope(GUI.skin.box)) { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Verbosity", EditorStyles.boldLabel, GUILayout.Width(100)); EditorGUILayout.LabelField("Time", EditorStyles.boldLabel, GUILayout.Width(80)); EditorGUILayout.LabelField("Type", EditorStyles.boldLabel, GUILayout.Width(100)); EditorGUILayout.LabelField("Action", EditorStyles.boldLabel, GUILayout.Width(100)); EditorGUILayout.LabelField("Name", EditorStyles.boldLabel, GUILayout.MinWidth(150), GUILayout.MaxWidth(300)); EditorGUILayout.LabelField("Trigger", EditorStyles.boldLabel, GUILayout.Width(100)); EditorGUILayout.LabelField("GameObject", EditorStyles.boldLabel, GUILayout.MinWidth(120), GUILayout.MaxWidth(200)); EditorGUILayout.LabelField("Message", EditorStyles.boldLabel); GUILayout.EndHorizontal(); _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, GUILayout.Height(position.height - 130)); if (_autoScroll && Application.isPlaying && !EditorApplication.isPaused) _scrollPosition.y = Mathf.Infinity; foreach (var message in _messages) { if (!FilterLog(message)) continue; switch (message.AudioLogVerbosity) { case AudioLogVerbosity.Error: GUI.color = Color.red; break; case AudioLogVerbosity.Warning: GUI.color = Color.yellow; break; } GUILayout.BeginHorizontal(); EditorGUILayout.LabelField(message.AudioLogVerbosity.ToString(), GUILayout.Width(96)); GUI.color = Color.white; EditorGUILayout.LabelField(message.Time, GUILayout.Width(80)); DrawObject(message.ObjectType); DrawAction(message.Action); if (GUILayout.Button(message.ObjectName, GUI.skin.label, GUILayout.MinWidth(150), GUILayout.MaxWidth(300))) { if (SoundCaster.Instance) SoundCaster.Instance.PasteFromAudioConsole(message); } DrawTrigger(message.TriggerFrom); if (GUILayout.Button(message.GameObjectName, GUI.skin.label, GUILayout.MinWidth(120), GUILayout.MaxWidth(200))) Selection.activeGameObject = message.GameObject; EditorGUILayout.LabelField(message.Message); GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); } } private void DrawVerbosityOptions() { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Verbosity:", GUILayout.Width(80)); _includeNotification = GUILayout.Toggle(_includeNotification, "Notification", GUILayout.Width(100)); _includeWarning = GUILayout.Toggle(_includeWarning, "Warning", GUILayout.Width(100)); _includeError = GUILayout.Toggle(_includeError, "Error", GUILayout.Width(100)); GUILayout.EndHorizontal(); } private void DrawTriggerOptions() { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Trigger:", GUILayout.Width(80)); _includeCode = GUILayout.Toggle(_includeCode, "Code", GUILayout.Width(100)); _includeConfig = GUILayout.Toggle(_includeConfig, "Config", GUILayout.Width(100)); _includeComponents = GUILayout.Toggle(_includeComponents, GUIContent.none, GUILayout.Width(10)); if (GUILayout.Button("Components", GUI.skin.label, GUILayout.Width(86))) AudioConsoleSubToggle.Init(_componentInclusions); _includeSoundCaster = GUILayout.Toggle(_includeSoundCaster, "Sound Caster"); GUILayout.EndHorizontal(); } private void DrawTypeOptions() { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Type:", GUILayout.Width(80)); _includeEvent = GUILayout.Toggle(_includeEvent, GUIContent.none, GUILayout.Width(10)); if (GUILayout.Button("Events", GUI.skin.label, GUILayout.Width(86))) AudioConsoleSubToggle.Init(_eventInclusions); _includeGameSync = GUILayout.Toggle(_includeGameSync, GUIContent.none, GUILayout.Width(10)); if (GUILayout.Button("Game Sync", GUI.skin.label, GUILayout.Width(86))) AudioConsoleSubToggle.Init(_gameSyncInclusions); _includeSpatialAudio = GUILayout.Toggle(_includeSpatialAudio, GUIContent.none, GUILayout.Width(10)); if (GUILayout.Button("Spatial Audio", GUI.skin.label, GUILayout.Width(86))) AudioConsoleSubToggle.Init(_spatialAudioInclusions); _includeBank = GUILayout.Toggle(_includeBank, GUIContent.none, GUILayout.Width(10)); if (GUILayout.Button("Banks", GUI.skin.label, GUILayout.Width(66))) BankInstanceList.Init(); GUILayout.EndHorizontal(); } private bool FilterLog(AudioConsoleLog message) { if (!string.IsNullOrEmpty(_objectNameFilter) && !message.ObjectName.ToLower().Contains(_objectNameFilter.ToLower())) return false; switch (message.AudioLogVerbosity) { case AudioLogVerbosity.Notification: if (!_includeNotification) return false; break; case AudioLogVerbosity.Warning: if (!_includeWarning) return false; break; case AudioLogVerbosity.Error: if (!_includeError) return false; break; } switch (message.ObjectType) { case AudioObjectType.Music: case AudioObjectType.SFX: case AudioObjectType.Voice: if (!_includeEvent || !_eventInclusions[message.ObjectType.ToString()]) return false; break; case AudioObjectType.SoundBank: if (!_includeBank) return false; break; case AudioObjectType.Switch: case AudioObjectType.State: case AudioObjectType.RTPC: if (!_includeGameSync || !_gameSyncInclusions[message.ObjectType.ToString()]) return false; break; case AudioObjectType.AuxBus: case AudioObjectType.Bus: case AudioObjectType.Room: case AudioObjectType.Portal: case AudioObjectType.Geometry: case AudioObjectType.Occlusion: case AudioObjectType.Obstruction: if (!_includeSpatialAudio || !_spatialAudioInclusions[message.ObjectType.ToString()]) return false; break; } switch (message.TriggerFrom) { case AudioTriggerSource.Code: if (!_includeCode) return false; break; case AudioTriggerSource.Config: if (!_includeConfig) return false; break; case AudioTriggerSource.SoundCaster: if (!_includeSoundCaster) return false; break; case AudioTriggerSource.Initialization: return true; default: if (!_includeComponents || !_componentInclusions[message.TriggerFrom.ToString()]) return false; break; } return true; } private static readonly Color Yellow = new Color(1f, 0.9f, 0.6f); private static readonly Color Skin = new Color(1f, 0.67f, 0.67f); private static readonly Color Orange = new Color(1f, 0.5f, 0f); private static readonly Color Pink = new Color(1f, 0.67f, 1f); private static readonly Color Rose = new Color(1f, 0.33f, 0.67f); private static readonly Color Aqua = new Color(0.5f, 1f, 1f); private static readonly Color LightGreen = new Color(0.5f, 1f, 0f); private static readonly Color DarkGreen = new Color(0f, 0.67f, 0.33f); private static readonly Color Purple = new Color(0.67f, 0.5f, 1f); private static readonly Color Blue = new Color(0.33f, 0.67f, 1f); private void DrawObject(AudioObjectType type) { switch (type) { case AudioObjectType.SFX: GUI.color = Orange; break; case AudioObjectType.Room: case AudioObjectType.Geometry: GUI.color = Aqua; break; case AudioObjectType.Portal: case AudioObjectType.Occlusion: case AudioObjectType.Obstruction: GUI.color = LightGreen; break; case AudioObjectType.Music: case AudioObjectType.Trigger: GUI.color = Purple; break; case AudioObjectType.Voice: case AudioObjectType.Language: GUI.color = Yellow; break; case AudioObjectType.State: case AudioObjectType.Switch: case AudioObjectType.RTPC: GUI.color = Pink; break; case AudioObjectType.SoundBank: case AudioObjectType.AudioPackage: GUI.color = Blue; break; case AudioObjectType.Emitter: case AudioObjectType.Listener: case AudioObjectType.AuxBus: case AudioObjectType.Bus: GUI.color = Skin; break; } EditorGUILayout.LabelField(type.ToString(), GUILayout.Width(100)); GUI.color = Color.white; } private void DrawAction(AudioAction action) { switch (action) { case AudioAction.PostEvent: GUI.color = Skin; break; case AudioAction.StopEvent: GUI.color = Orange; break; case AudioAction.Load: case AudioAction.Reload: GUI.color = Aqua; break; case AudioAction.Unload: GUI.color = Blue; break; case AudioAction.Activate: case AudioAction.Reveal: GUI.color = Pink; break; case AudioAction.Deactivate: case AudioAction.Cull: GUI.color = Purple; break; case AudioAction.Mute: case AudioAction.Pause: GUI.color = DarkGreen; break; case AudioAction.Unmute: case AudioAction.Resume: GUI.color = LightGreen; break; case AudioAction.SetValue: case AudioAction.GetValue: GUI.color = Rose; break; } EditorGUILayout.LabelField(action.ToString(), GUILayout.Width(100)); GUI.color = Color.white; } private void DrawTrigger(AudioTriggerSource trigger) { switch (trigger) { case AudioTriggerSource.Code: GUI.color = Orange; break; case AudioTriggerSource.Initialization: GUI.color = Pink; break; } EditorGUILayout.LabelField(trigger.ToString(), GUILayout.Width(100)); GUI.color = Color.white; } private void SelectAll(bool enabled) { _includeEvent = _includeGameSync = _includeBank = _includeGameSync = _includeSpatialAudio = _includeError = _includeNotification = _includeWarning = _includeComponents = _includeCode = _includeConfig = _includeSoundCaster = enabled; } #endregion private class BankInstanceList : EditorWindow { private static Dictionary _bankList; public static void Init() { var position = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); position.y += 10; var window = CreateInstance(); _bankList = AkBankManager.LoadedBankList; window.ShowAsDropDown(new Rect(position, Vector2.zero), new Vector2(150, _bankList.Count * 20)); } private void OnGUI() { foreach (var bankLoadStatus in _bankList) { EditorGUILayout.LabelField(bankLoadStatus.Key + " @ " + bankLoadStatus.Value); } } } private class AudioConsoleSubToggle : EditorWindow { private static Dictionary _toggleMapping; //internal static Action onToggleChanged; public static void Init(Dictionary toggleMapping) { _toggleMapping = toggleMapping; var position = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); position.y += 10; var window = CreateInstance(); window.ShowAsDropDown(new Rect(position, Vector2.zero), new Vector2(130, _toggleMapping.Count * 20)); } private void OnGUI() { var tempDict = new Dictionary(_toggleMapping); foreach (var component in tempDict) { _toggleMapping[component.Key] = GUILayout.Toggle(component.Value, component.Key); } } } } } #endif