using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; using Wwise.Wooduan.Tools; public partial class AkAmbientInspector { public AttenuationSphereOptions currentAttSphereOp = AttenuationSphereOptions.Current_Event_Only; private int _insertRemoveIndex = 1; public new void OnEnable() { base.OnEnable(); m_AkAmbient = target as AkAmbient; multiPositionTypeProperty = serializedObject.FindProperty("positionMode"); largeModePositionArrayProperty = serializedObject.FindProperty("LargeModePositions"); if (!attSphereProperties.ContainsKey(target)) attSphereProperties.Add(target, AttenuationSphereOptions.Current_Event_Only); currentAttSphereOp = attSphereProperties[target]; } public override void OnChildInspectorGUI() { if (UnityEngine.Event.current.type == UnityEngine.EventType.ExecuteCommand && UnityEngine.Event.current.commandName == "ObjectSelectorClosed") { var pickedObject = UnityEditor.EditorGUIUtility.GetObjectPickerObject(); if (pickedObject != null) { int insertIndex = largeModePositionArrayProperty.arraySize; largeModePositionArrayProperty.InsertArrayElementAtIndex(insertIndex); var newElement = largeModePositionArrayProperty.GetArrayElementAtIndex(insertIndex); newElement.objectReferenceValue = pickedObject; return; } } UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing); using (new UnityEditor.EditorGUILayout.VerticalScope("box")) { UnityEditor.EditorGUILayout.PropertyField(multiPositionTypeProperty, new UnityEngine.GUIContent("Position Mode: ", "Simple Mode: Only one position is used.\n" + "Large Mode: Children of AkAmbient with AkAmbientLargeModePositioner component will be used as position source for multi-positioning.\n" + "Multiple Position Mode: Every AkAmbient using the same event will be used as position source for multi-positioning.\n" + "Volumetric Mode: Emitter stays on collider when player is outside and follows player when inside.\n" + "Linear Mode: Find an emitter point on line nearest to listener.\n" + "Polygon Mode: Find an emitter point on sides of polygon nearest to listener, and switch to 2D when listener enters polygon.")); var multiPositionType = (AmbientEmitterPositionMode)multiPositionTypeProperty.intValue; switch (multiPositionType) { case AmbientEmitterPositionMode.Volumetric: { if (!m_AkAmbient.GetComponent()) { UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing); UnityEditor.EditorGUILayout.HelpBox("Volumetric mode requires a Collider component!", UnityEditor.MessageType.Error); } m_AkAmbient.gameObject.isStatic = false; break; } case AmbientEmitterPositionMode.Large: case AmbientEmitterPositionMode.Linear: case AmbientEmitterPositionMode.Polygon: case AmbientEmitterPositionMode.MultiPosition: { foreach (AkAmbient ambient in targets) { if (!ambient.gameObject.isStatic) { UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing); UnityEditor.EditorGUILayout.HelpBox( string.Format( "Position Mode <{0}> requires an AkGameObj that does not move. Consider setting the associated GameObject to static.", multiPositionType), UnityEditor.MessageType.Warning); break; } } break; } } UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing); currentAttSphereOp = (AttenuationSphereOptions) UnityEditor.EditorGUILayout.EnumPopup("Show Attenuation Sphere: ", currentAttSphereOp); attSphereProperties[target] = currentAttSphereOp; switch (multiPositionType) { case AmbientEmitterPositionMode.Linear: EditorGUILayout.PropertyField(serializedObject.FindProperty("heightOrRadius"), new GUIContent("Radius")); break; case AmbientEmitterPositionMode.Polygon: { EditorGUILayout.PropertyField(serializedObject.FindProperty("followInside")); EditorGUILayout.PropertyField(serializedObject.FindProperty("invertInside")); EditorGUILayout.PropertyField(serializedObject.FindProperty("audioVerticalRange")); if (m_AkAmbient.audioVerticalRange == AudioVerticalRange.Limited) EditorGUILayout.PropertyField(serializedObject.FindProperty("heightOrRadius"), new GUIContent("Height")); break; } } EditorGUILayout.PropertyField(serializedObject.FindProperty("cullDistance")); switch (multiPositionType) { case AmbientEmitterPositionMode.Large: case AmbientEmitterPositionMode.Linear: case AmbientEmitterPositionMode.Polygon: { UnityEngine.GUILayout.BeginHorizontal(); if (UnityEngine.GUILayout.Button("Add Position Object")) { int addIndex = largeModePositionArrayProperty.arraySize; var addPosition = addIndex > 0 ? m_AkAmbient.LargeModePositions[addIndex - 1].Position : m_AkAmbient.transform.position; CreateNewPositionObject(addIndex, addPosition); } if (UnityEngine.GUILayout.Button("Insert before") && _insertRemoveIndex < largeModePositionArrayProperty.arraySize) { var previousPoint = _insertRemoveIndex > 0 ? m_AkAmbient.LargeModePositions[_insertRemoveIndex - 1] : m_AkAmbient.LargeModePositions[0]; var nextPoint = m_AkAmbient.LargeModePositions[_insertRemoveIndex]; var insertPosition = (previousPoint.Position + nextPoint.Position) / 2f; CreateNewPositionObject(_insertRemoveIndex, insertPosition); } if (UnityEngine.GUILayout.Button("Remove at") && _insertRemoveIndex < largeModePositionArrayProperty.arraySize) { var oldSize = largeModePositionArrayProperty.arraySize; largeModePositionArrayProperty.DeleteArrayElementAtIndex(_insertRemoveIndex); if (largeModePositionArrayProperty.arraySize == oldSize) largeModePositionArrayProperty.DeleteArrayElementAtIndex(_insertRemoveIndex); var point = m_AkAmbient.transform.GetChild(_insertRemoveIndex).gameObject; DestroyImmediate(point); } _insertRemoveIndex = EditorGUILayout.IntField("", _insertRemoveIndex, GUILayout.Width(30)); UnityEngine.GUILayout.EndHorizontal(); ++UnityEditor.EditorGUI.indentLevel; UnityEditor.EditorGUI.BeginChangeCheck(); for (int i = 0; i < largeModePositionArrayProperty.arraySize; ++i) { UnityEditor.EditorGUILayout.PropertyField(largeModePositionArrayProperty.GetArrayElementAtIndex(i), true); } if (UnityEditor.EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } --UnityEditor.EditorGUI.indentLevel; if (largeModePositionArrayProperty.arraySize > 1 && GUILayout.Button("Set In Same Plane")) SetInSamePlane(); break; } } } } private void CreateNewPositionObject(int insertIndex, Vector3 position) { largeModePositionArrayProperty.InsertArrayElementAtIndex(insertIndex); var newPoint = new UnityEngine.GameObject(string.Format("Point_{0}", insertIndex)); UnityEditor.Undo.RegisterCreatedObjectUndo(newPoint, "CreateNewAkAmbientPositionObject"); UnityEditor.Undo.AddComponent(newPoint); UnityEditor.Undo.SetTransformParent(newPoint.transform, m_AkAmbient.transform, "CreateNewAkAmbientPositionObjectSetParent"); newPoint.transform.position = position; newPoint.transform.localScale = Vector3.one; newPoint.transform.SetSiblingIndex(insertIndex); var newElement = largeModePositionArrayProperty.GetArrayElementAtIndex(insertIndex); newElement.objectReferenceValue = newPoint.GetComponent(); } private void SetInSamePlane() { var baseHeight = m_AkAmbient.LargeModePositions[0].Position.y; for (var i = 1; i < m_AkAmbient.LargeModePositions.Length; i++) { var position = m_AkAmbient.LargeModePositions[i].Position; m_AkAmbient.LargeModePositions[i].transform.position = new Vector3(position.x, baseHeight, position.z); } } public void RenderAttenuationSpheres() { switch (currentAttSphereOp) { case AttenuationSphereOptions.Dont_Show: return; case AttenuationSphereOptions.Current_Event_Only: { var data = AkWwiseProjectInfo.GetData(); if (!data) return; // Get the max attenuation for the event (if available) var radius = data.GetEventMaxAttenuation(m_AkAmbient.data.Id); switch (m_AkAmbient.positionMode) { case AmbientEmitterPositionMode.Single: AkWooduanScriptingTools.DrawSphere(m_AkAmbient.gameObject.transform.position, radius); break; case AmbientEmitterPositionMode.Large: case AmbientEmitterPositionMode.Polygon: case AmbientEmitterPositionMode.Linear: { var positionComponents = m_AkAmbient.GetComponentsInChildren(); for (int i = 0; i < positionComponents.Length; i++) { AkWooduanScriptingTools.DrawSphere(positionComponents[i].transform.position, radius); } break; } case AmbientEmitterPositionMode.MultiPosition: { var akAmbiants = FindObjectsOfType(); for (var i = 0; i < akAmbiants.Length; i++) { if (akAmbiants[i].positionMode == AmbientEmitterPositionMode.MultiPosition && akAmbiants[i].data.Id == m_AkAmbient.data.Id) { AkWooduanScriptingTools.DrawSphere(akAmbiants[i].gameObject.transform.position, radius); } } break; } } break; } case AttenuationSphereOptions.All_Events: { var akAmbiants = FindObjectsOfType(); for (var i = 0; i < akAmbiants.Length; i++) { // Get the max attenuation for the event (if available) var radius = AkWwiseProjectInfo.GetData().GetEventMaxAttenuation(akAmbiants[i].data.Id); if (akAmbiants[i].positionMode == AmbientEmitterPositionMode.Large) { var positionComponents = m_AkAmbient.GetComponentsInChildren(); for (int j = 0; j < positionComponents.Length; j++) { AkWooduanScriptingTools.DrawSphere(positionComponents[j].transform.position, radius); } } else { AkWooduanScriptingTools.DrawSphere(akAmbiants[i].gameObject.transform.position, radius); } } break; } } } private void OnSceneGUI() { for (int i = 0; i < m_AkAmbient.LargeModePositions.Length; ++i) { m_AkAmbient.LargeModePositions[i].gameObject.name = "Point_" + i; } RenderAttenuationSpheres(); if (m_AkAmbient.positionMode >= AmbientEmitterPositionMode.Linear) m_AkAmbient.DrawConnectingLines(); } }