2021-02-27 20:53:36 +00:00
public class AkWwiseInitializationSettings : AkCommonPlatformSettings
{
[UnityEngine.HideInInspector]
public System . Collections . Generic . List < string > PlatformSettingsNameList
= new System . Collections . Generic . List < string > ( ) ;
[UnityEngine.HideInInspector]
public System . Collections . Generic . List < PlatformSettings > PlatformSettingsList
= new System . Collections . Generic . List < PlatformSettings > ( ) ;
[UnityEngine.HideInInspector]
public System . Collections . Generic . List < string > InvalidReferencePlatforms
= new System . Collections . Generic . List < string > ( ) ;
public bool IsValid
{
get { return PlatformSettingsNameList . Count = = PlatformSettingsList . Count ; }
}
public int Count
{
get { return PlatformSettingsList . Count ; }
}
[UnityEngine.HideInInspector]
public AkCommonUserSettings UserSettings ;
[UnityEngine.HideInInspector]
public AkCommonAdvancedSettings AdvancedSettings ;
[UnityEngine.HideInInspector]
public AkCommonCommSettings CommsSettings ;
protected override AkCommonUserSettings GetUserSettings ( )
{
return UserSettings ;
}
protected override AkCommonAdvancedSettings GetAdvancedSettings ( )
{
return AdvancedSettings ;
}
protected override AkCommonCommSettings GetCommsSettings ( )
{
return CommsSettings ;
}
private static readonly string [ ] AllGlobalValues = new [ ]
{
"UserSettings.m_BasePath" ,
"UserSettings.m_StartupLanguage" ,
"UserSettings.m_EngineLogging" ,
"UserSettings.m_MaximumNumberOfPositioningPaths" ,
"UserSettings.m_MemoryCutoffThreshold" ,
"UserSettings.m_CommandQueueSize" ,
"UserSettings.m_SamplesPerFrame" ,
"UserSettings.m_MainOutputSettings.m_AudioDeviceShareset" ,
"UserSettings.m_MainOutputSettings.m_DeviceID" ,
"UserSettings.m_MainOutputSettings.m_PanningRule" ,
"UserSettings.m_MainOutputSettings.m_ChannelConfig.m_ChannelConfigType" ,
"UserSettings.m_MainOutputSettings.m_ChannelConfig.m_ChannelMask" ,
"UserSettings.m_MainOutputSettings.m_ChannelConfig.m_NumberOfChannels" ,
"UserSettings.m_StreamingLookAheadRatio" ,
"UserSettings.m_SampleRate" ,
"UserSettings.m_NumberOfRefillsInVoice" ,
"UserSettings.m_SpatialAudioSettings.m_MaxSoundPropagationDepth" ,
"UserSettings.m_SpatialAudioSettings.m_MovementThreshold" ,
"UserSettings.m_SpatialAudioSettings.m_NumberOfPrimaryRays" ,
"UserSettings.m_SpatialAudioSettings.m_MaxReflectionOrder" ,
"UserSettings.m_SpatialAudioSettings.m_MaxPathLength" ,
2021-04-30 07:09:07 +01:00
"UserSettings.m_SpatialAudioSettings.m_CPULimitPercentage" ,
2021-02-27 20:53:36 +00:00
"UserSettings.m_SpatialAudioSettings.m_EnableDiffractionOnReflections" ,
2021-04-30 07:09:07 +01:00
"UserSettings.m_SpatialAudioSettings.m_EnableGeometricDiffractionAndTransmission" ,
"UserSettings.m_SpatialAudioSettings.m_CalcEmitterVirtualPosition" ,
"UserSettings.m_SpatialAudioSettings.m_UseObstruction" ,
"UserSettings.m_SpatialAudioSettings.m_UseOcclusion" ,
2021-02-27 20:53:36 +00:00
"CommsSettings.m_PoolSize" ,
"CommsSettings.m_DiscoveryBroadcastPort" ,
"CommsSettings.m_CommandPort" ,
"CommsSettings.m_NotificationPort" ,
"CommsSettings.m_InitializeSystemComms" ,
"CommsSettings.m_NetworkName" ,
"AdvancedSettings.m_IOMemorySize" ,
"AdvancedSettings.m_TargetAutoStreamBufferLengthMs" ,
"AdvancedSettings.m_UseStreamCache" ,
"AdvancedSettings.m_MaximumPinnedBytesInCache" ,
"AdvancedSettings.m_EnableGameSyncPreparation" ,
"AdvancedSettings.m_ContinuousPlaybackLookAhead" ,
"AdvancedSettings.m_MonitorQueuePoolSize" ,
"AdvancedSettings.m_MaximumHardwareTimeoutMs" ,
"AdvancedSettings.m_SpatialAudioSettings.m_DiffractionShadowAttenuationFactor" ,
"AdvancedSettings.m_SpatialAudioSettings.m_DiffractionShadowDegrees" ,
"AdvancedSettings.m_RenderDuringFocusLoss" ,
"AdvancedSettings.m_UseAsyncOpen" ,
"AdvancedSettings.m_SoundBankPersistentDataPath" ,
"AdvancedSettings.m_DebugOutOfRangeCheckEnabled" ,
"AdvancedSettings.m_DebugOutOfRangeLimit"
} ;
public abstract class PlatformSettings : AkCommonPlatformSettings
{
#region Ignore property list management
[UnityEngine.SerializeField]
[UnityEngine.HideInInspector]
private System . Collections . Generic . List < string > IgnorePropertyNameList =
new System . Collections . Generic . List < string > ( ) ;
public void IgnorePropertyValue ( string propertyPath )
{
if ( IsPropertyIgnored ( propertyPath ) )
return ;
IgnorePropertyNameList . Add ( propertyPath ) ;
SetUseGlobalPropertyValue ( propertyPath , false ) ;
}
public bool IsPropertyIgnored ( string propertyPath )
{
return IgnorePropertyNameList . Contains ( propertyPath ) ;
}
#endregion
#region Global property list management
[UnityEngine.SerializeField]
[UnityEngine.HideInInspector]
private System . Collections . Generic . List < string > GlobalPropertyNameList =
new System . Collections . Generic . List < string > ( ) ;
protected PlatformSettings ( )
{
SetGlobalPropertyValues ( AllGlobalValues ) ;
}
public void SetUseGlobalPropertyValue ( string propertyPath , bool use )
{
if ( IsUsingGlobalPropertyValue ( propertyPath ) = = use )
return ;
if ( use )
GlobalPropertyNameList . Add ( propertyPath ) ;
else
GlobalPropertyNameList . Remove ( propertyPath ) ;
_GlobalPropertyHashSet = null ;
}
public void SetGlobalPropertyValues ( System . Collections . IEnumerable enumerable )
{
foreach ( var item in enumerable )
{
string propertyPath = item as string ;
if ( ! IsUsingGlobalPropertyValue ( propertyPath ) )
GlobalPropertyNameList . Add ( propertyPath ) ;
}
}
private bool IsUsingGlobalPropertyValue ( string propertyPath )
{
return GlobalPropertyNameList . Contains ( propertyPath ) ;
}
private System . Collections . Generic . HashSet < string > _GlobalPropertyHashSet = null ;
public System . Collections . Generic . HashSet < string > GlobalPropertyHashSet
{
get
{
if ( _GlobalPropertyHashSet = = null )
_GlobalPropertyHashSet = new System . Collections . Generic . HashSet < string > ( GlobalPropertyNameList ) ;
return _GlobalPropertyHashSet ;
}
set { _GlobalPropertyHashSet = value ; }
}
#endregion
#if UNITY_EDITOR
protected static void RegisterPlatformSettingsClass < T > ( string platformName ) where T : PlatformSettings
{
string className = typeof ( T ) . Name ;
string currentClassName ;
if ( m_PlatformSettingsClassNames . TryGetValue ( platformName , out currentClassName ) & & currentClassName = = className )
{
UnityEngine . Debug . LogWarning ( "WwiseUnity: The class <" + currentClassName + "> is being replaced by <" + className + "> for the reference platform: " + platformName ) ;
return ;
}
m_PlatformSettingsClassNames [ platformName ] = className ;
}
2021-04-30 07:09:07 +01:00
public static bool IsDistinctPlatform ( string platformName )
{
return m_PlatformSettingsClassNames . ContainsKey ( platformName ) ;
}
2021-02-27 20:53:36 +00:00
#endif
}
public class CommonPlatformSettings : PlatformSettings
{
protected override AkCommonUserSettings GetUserSettings ( )
{
return UserSettings ;
}
protected override AkCommonAdvancedSettings GetAdvancedSettings ( )
{
return AdvancedSettings ;
}
protected override AkCommonCommSettings GetCommsSettings ( )
{
return CommsSettings ;
}
[UnityEngine.HideInInspector]
public AkCommonUserSettings UserSettings ;
[UnityEngine.HideInInspector]
public AkCommonAdvancedSettings AdvancedSettings ;
[UnityEngine.HideInInspector]
public AkCommonCommSettings CommsSettings ;
}
#region Singleton management
private static AkWwiseInitializationSettings m_Instance = null ;
private static AkBasePlatformSettings m_ActivePlatformSettings = null ;
public static AkWwiseInitializationSettings Instance
{
get
{
if ( m_Instance = = null )
{
#if UNITY_EDITOR
var name = typeof ( AkWwiseInitializationSettings ) . Name ;
m_Instance = GetOrCreateAsset < AkWwiseInitializationSettings > ( name , name ) ;
#else
m_Instance = CreateInstance < AkWwiseInitializationSettings > ( ) ;
UnityEngine . Debug . LogWarning ( "WwiseUnity: No platform specific settings were created. Default initialization settings will be used." ) ;
#endif
}
return m_Instance ;
}
}
private static AkBasePlatformSettings GetPlatformSettings ( string platformName )
{
var instance = Instance ;
if ( ! instance . IsValid )
return instance ;
for ( var i = 0 ; i < instance . Count ; + + i )
{
var platformSettings = instance . PlatformSettingsList [ i ] ;
if ( platformSettings & & ( string . Equals ( platformName , instance . PlatformSettingsNameList [ i ] , System . StringComparison . OrdinalIgnoreCase ) ) )
return platformSettings ;
}
UnityEngine . Debug . LogWarning ( "WwiseUnity: Platform specific settings cannot be found for <" + platformName + ">. Using global settings." ) ;
return instance ;
}
public static AkBasePlatformSettings ActivePlatformSettings
{
get
{
if ( m_ActivePlatformSettings = = null )
m_ActivePlatformSettings = GetPlatformSettings ( AkBasePathGetter . GetPlatformName ( ) ) ;
return m_ActivePlatformSettings ;
}
}
private void OnEnable ( )
{
if ( m_Instance = = null )
m_Instance = this ;
else if ( m_Instance ! = this )
UnityEngine . Debug . LogWarning ( "WwiseUnity: There are multiple AkWwiseInitializationSettings objects instantiated; only one will be used." ) ;
}
#endregion
#region Sound Engine Initialization
2021-04-30 07:09:07 +01:00
public bool InitializeSoundEngine ( )
2021-02-27 20:53:36 +00:00
{
#if UNITY_EDITOR
Instance . ActiveSettingsHash = GetHashOfActiveSettings ( ) ;
Instance . ActiveSettingsHaveChanged = true ;
#endif
UnityEngine . Debug . LogFormat ( "WwiseUnity: Wwise(R) SDK Version {0}." , AkSoundEngine . WwiseVersion ) ;
var initResult = AkSoundEngine . Init ( ActivePlatformSettings . AkInitializationSettings ) ;
if ( initResult ! = AKRESULT . AK_Success )
{
UnityEngine . Debug . LogError ( $"WwiseUnity: Failed to initialize the sound engine. Reason: {initResult}" ) ;
AkSoundEngine . Term ( ) ;
return false ;
}
if ( AkSoundEngine . InitSpatialAudio ( ActivePlatformSettings . AkSpatialAudioInitSettings ) ! = AKRESULT . AK_Success )
{
UnityEngine . Debug . LogWarning ( "WwiseUnity: Failed to initialize spatial audio." ) ;
}
AkSoundEngine . InitCommunication ( ActivePlatformSettings . AkCommunicationSettings ) ;
AkBasePathGetter . EvaluateGamePaths ( ) ;
var soundBankBasePath = AkBasePathGetter . SoundBankBasePath ;
if ( string . IsNullOrEmpty ( soundBankBasePath ) )
{
// this is a nearly impossible situation
UnityEngine . Debug . LogError ( "WwiseUnity: Couldn't find SoundBanks base path. Terminating sound engine." ) ;
AkSoundEngine . Term ( ) ;
return false ;
}
var persistentDataPath = AkBasePathGetter . PersistentDataPath ;
var isBasePathSameAsPersistentPath = soundBankBasePath = = persistentDataPath ;
#if UNITY_ANDROID
var canSetBasePath = ! isBasePathSameAsPersistentPath ;
var canSetPersistentDataPath = true ;
#else
var canSetBasePath = true ;
var canSetPersistentDataPath = ! isBasePathSameAsPersistentPath ;
#endif
if ( canSetBasePath & & AkSoundEngine . SetBasePath ( soundBankBasePath ) ! = AKRESULT . AK_Success )
{
#if UNITY_EDITOR
var format = "WwiseUnity: Failed to set SoundBanks base path to <{0}>. Make sure SoundBank path is correctly set under Edit > Project Settings > Wwise > Editor > Asset Management." ;
#else
var format = "WwiseUnity: Failed to set SoundBanks base path to <{0}>. Make sure SoundBank path is correctly set under Edit > Project Settings > Wwise > Initialization." ;
#endif
2021-04-30 07:09:07 +01:00
#if ! UNITY_ANDROID | | UNITY_EDITOR
// It might be normal for SetBasePath to return AK_PathNotFound on Android. Silence the error log to avoid confusion.
2021-02-27 20:53:36 +00:00
UnityEngine . Debug . LogErrorFormat ( format , soundBankBasePath ) ;
2021-04-30 07:09:07 +01:00
#endif
2021-02-27 20:53:36 +00:00
}
if ( canSetPersistentDataPath & & ! string . IsNullOrEmpty ( persistentDataPath ) )
{
AkSoundEngine . AddBasePath ( persistentDataPath ) ;
}
var decodedBankFullPath = AkBasePathGetter . DecodedBankFullPath ;
if ( ! string . IsNullOrEmpty ( decodedBankFullPath ) )
{
// AkSoundEngine.SetDecodedBankPath creates the folders for writing to (if they don't exist)
AkSoundEngine . SetDecodedBankPath ( decodedBankFullPath ) ;
// Adding decoded bank path last to ensure that it is the first one used when writing decoded banks.
AkSoundEngine . AddBasePath ( decodedBankFullPath ) ;
}
AkSoundEngine . SetCurrentLanguage ( ActivePlatformSettings . InitialLanguage ) ;
AkCallbackManager . Init ( ActivePlatformSettings . CallbackManagerInitializationSettings ) ;
UnityEngine . Debug . Log ( "WwiseUnity: Sound engine initialized successfully." ) ;
2021-04-30 07:09:07 +01:00
LoadInitBank ( ) ;
2021-02-27 20:53:36 +00:00
return true ;
}
2021-04-30 07:09:07 +01:00
protected virtual void LoadInitBank ( )
{
AkBankManager . LoadInitBank ( ) ;
}
protected virtual void ClearBanks ( )
{
AkSoundEngine . ClearBanks ( ) ;
}
protected virtual void ResetBanks ( )
{
AkBankManager . Reset ( ) ;
}
public bool ResetSoundEngine ( bool isPlaying )
2021-02-27 20:53:36 +00:00
{
if ( isPlaying )
{
2021-04-30 07:09:07 +01:00
ClearBanks ( ) ;
LoadInitBank ( ) ;
2021-02-27 20:53:36 +00:00
}
AkCallbackManager . Init ( ActivePlatformSettings . CallbackManagerInitializationSettings ) ;
return true ;
}
2021-04-30 07:09:07 +01:00
public void TerminateSoundEngine ( )
2021-02-27 20:53:36 +00:00
{
if ( ! AkSoundEngine . IsInitialized ( ) )
return ;
// Stop everything, and make sure the callback buffer is empty. We try emptying as much as possible, and wait 10 ms before retrying.
// Callbacks can take a long time to be posted after the call to RenderAudio().
AkSoundEngine . StopAll ( ) ;
2021-04-30 07:09:07 +01:00
ClearBanks ( ) ;
2021-02-27 20:53:36 +00:00
AkSoundEngine . RenderAudio ( ) ;
for ( var retry = 0 ; retry < 5 ; )
{
if ( AkCallbackManager . PostCallbacks ( ) = = 0 )
{
SleepForMilliseconds ( 10 ) ;
+ + retry ;
}
SleepForMilliseconds ( 1 ) ;
}
AkSoundEngine . Term ( ) ;
// Make sure we have no callbacks left after Term. Some might be posted during termination.
AkCallbackManager . PostCallbacks ( ) ;
AkCallbackManager . Term ( ) ;
2021-04-30 07:09:07 +01:00
ResetBanks ( ) ;
2021-02-27 20:53:36 +00:00
#if UNITY_EDITOR
Instance . ActiveSettingsHash = string . Empty ;
Instance . ActiveSettingsHaveChanged = true ;
#endif
}
private static void SleepForMilliseconds ( double milliseconds )
{
using ( var tmpEvent = new System . Threading . ManualResetEvent ( false ) )
tmpEvent . WaitOne ( System . TimeSpan . FromMilliseconds ( milliseconds ) ) ;
}
#endregion
#if UNITY_EDITOR
public static T GetOrCreateAsset < T > ( string className , string fileName ) where T : AkCommonPlatformSettings
{
var path = System . IO . Path . Combine ( AkWwiseEditorSettings . WwiseScriptableObjectRelativePath , fileName + ".asset" ) ;
var asset = UnityEditor . AssetDatabase . LoadAssetAtPath < T > ( path ) ;
if ( asset )
return asset ;
var guids = UnityEditor . AssetDatabase . FindAssets ( "t:" + typeof ( T ) . Name ) ;
foreach ( var assetGuid in guids )
{
var assetPath = UnityEditor . AssetDatabase . GUIDToAssetPath ( assetGuid ) ;
asset = UnityEditor . AssetDatabase . LoadAssetAtPath < T > ( assetPath ) ;
if ( asset )
return asset ;
}
asset = CreateInstance ( className ) as T ;
AkUtilities . CreateFolder ( AkWwiseEditorSettings . WwiseScriptableObjectRelativePath ) ;
UnityEditor . AssetDatabase . CreateAsset ( asset , path ) ;
return asset ;
}
private static System . Collections . Generic . Dictionary < string , string > m_PlatformSettingsClassNames
= new System . Collections . Generic . Dictionary < string , string > ( ) ;
private const System . Reflection . BindingFlags BindingFlags
= System . Reflection . BindingFlags . Instance | System . Reflection . BindingFlags . Public | System . Reflection . BindingFlags . NonPublic ;
private static string GetHashOfActiveSettingsField ( string name , object obj )
{
var type = obj . GetType ( ) ;
if ( type . IsPrimitive | | type = = typeof ( string ) )
return name + ": " + obj . ToString ( ) + "\n" ;
string ret = string . Empty ;
foreach ( var subFieldInfo in type . GetFields ( BindingFlags ) )
{
var subObject = subFieldInfo . GetValue ( obj ) ;
var subType = subFieldInfo . FieldType ;
var fields = subType . GetFields ( BindingFlags ) ;
if ( fields . Length = = 0 )
ret + = subFieldInfo . Name + ": " + subObject . ToString ( ) + "\n" ;
else
ret + = GetHashOfActiveSettingsField ( subFieldInfo . Name , subObject ) ;
}
return ret ;
}
public static string GetHashOfActiveSettings ( )
{
try
{
return GetHashOfActiveSettingsField ( string . Empty , ActivePlatformSettings ) ;
}
catch
{
return string . Empty ;
}
}
[UnityEngine.HideInInspector]
private bool ActiveSettingsHaveChanged = true ;
[UnityEngine.HideInInspector]
private string ActiveSettingsHash ;
public static void UpdatePlatforms ( )
{
if ( ! AkUtilities . IsWwiseProjectAvailable )
return ;
var customPlatformSettingsMap = new System . Collections . Generic . Dictionary < string , PlatformSettings > ( ) ;
var instance = Instance ;
if ( instance . IsValid )
{
for ( var i = 0 ; i < instance . Count ; + + i )
{
var settings = instance . PlatformSettingsList [ i ] ;
var name = instance . PlatformSettingsNameList [ i ] ;
if ( settings & & ! string . IsNullOrEmpty ( name ) )
customPlatformSettingsMap . Add ( name , settings ) ;
}
}
var updated = false ;
var allCustomPlatforms = new System . Collections . Generic . List < string > ( ) ;
foreach ( var pair in AkUtilities . PlatformMapping )
{
var referencePlatform = pair . Key ;
var customPlatformList = pair . Value ;
2021-04-30 07:09:07 +01:00
string className , customClassName ;
2021-02-27 20:53:36 +00:00
if ( ! m_PlatformSettingsClassNames . TryGetValue ( referencePlatform , out className ) )
{
if ( ! instance . InvalidReferencePlatforms . Contains ( referencePlatform ) )
{
instance . InvalidReferencePlatforms . Add ( referencePlatform ) ;
UnityEngine . Debug . LogError ( "WwiseUnity: A class has not been registered for the reference platform: " + referencePlatform ) ;
}
continue ;
}
foreach ( var customWwisePlatform in customPlatformList )
{
allCustomPlatforms . Add ( customWwisePlatform ) ;
if ( customPlatformSettingsMap . ContainsKey ( customWwisePlatform ) )
continue ;
2021-04-30 07:09:07 +01:00
PlatformSettings settings ;
if ( m_PlatformSettingsClassNames . TryGetValue ( customWwisePlatform , out customClassName ) )
{
settings = GetOrCreateAsset < PlatformSettings > ( customClassName , customWwisePlatform ) ;
}
else
{
settings = GetOrCreateAsset < PlatformSettings > ( className , customWwisePlatform ) ;
}
2021-02-27 20:53:36 +00:00
customPlatformSettingsMap . Add ( customWwisePlatform , settings ) ;
updated = true ;
}
}
var customPlatformSettingsToRemoveMap = new System . Collections . Generic . Dictionary < string , PlatformSettings > ( ) ;
foreach ( var pair in customPlatformSettingsMap )
{
var instantiatedCustomPlatform = pair . Key ;
if ( ! allCustomPlatforms . Contains ( instantiatedCustomPlatform ) )
customPlatformSettingsToRemoveMap . Add ( instantiatedCustomPlatform , pair . Value ) ;
}
foreach ( var pair in customPlatformSettingsToRemoveMap )
{
var instantiatedCustomPlatform = pair . Key ;
customPlatformSettingsMap . Remove ( instantiatedCustomPlatform ) ;
var parentPath = System . IO . Path . Combine ( "Assets" , AkWwiseEditorSettings . WwiseScriptableObjectRelativePath ) ;
var assetPath = System . IO . Path . Combine ( parentPath , instantiatedCustomPlatform + ".asset" ) ;
UnityEditor . AssetDatabase . DeleteAsset ( assetPath ) ;
updated = true ;
}
if ( updated )
{
instance . PlatformSettingsNameList . Clear ( ) ;
instance . PlatformSettingsList . Clear ( ) ;
AkUtilities . RepaintInspector ( ) ;
var keys = System . Linq . Enumerable . ToList ( customPlatformSettingsMap . Keys ) ;
keys . Sort ( ) ;
foreach ( var key in keys )
{
instance . PlatformSettingsNameList . Add ( key ) ;
instance . PlatformSettingsList . Add ( customPlatformSettingsMap [ key ] ) ;
}
UnityEditor . EditorUtility . SetDirty ( instance ) ;
UnityEditor . AssetDatabase . SaveAssets ( ) ;
AkUtilities . RepaintInspector ( ) ;
}
}
#region Custom Editor
#if UNITY_2018_3_OR_NEWER
class SettingsProvider : UnityEditor . SettingsProvider
#else
[UnityEditor.MenuItem("Edit/Wwise Initialization Settings..", false, (int)AkWwiseWindowOrder.WwiseInitializationSettings)]
private static void WwiseInitializationSettingsMenuItem ( )
{
UnityEditor . Selection . activeObject = Instance ;
}
[UnityEditor.CustomEditor(typeof(AkWwiseInitializationSettings))]
public class Editor : UnityEditor . Editor
#endif
{
#if UNITY_2018_3_OR_NEWER
private SettingsProvider ( string path ) : base ( path , UnityEditor . SettingsScope . Project ) { }
[UnityEditor.SettingsProvider]
public static UnityEditor . SettingsProvider CreateMyCustomSettingsProvider ( )
{
return new SettingsProvider ( "Project/Wwise Initialization" ) ;
}
private UnityEditor . SerializedObject serializedObject ;
#endif
private const string UserSettings = "UserSettings" ;
private const string AdvancedSettings = "AdvancedSettings" ;
private const string CommsSettings = "CommsSettings" ;
private System . Collections . Generic . List < PlatformSettings > PreviousPlatformSettingsList
= new System . Collections . Generic . List < PlatformSettings > ( ) ;
private System . Collections . Generic . List < GlobalSettingsGroupData > GlobalSettingsGroups
= new System . Collections . Generic . List < GlobalSettingsGroupData > ( ) ;
private System . Collections . Generic . Dictionary < string , System . Collections . Generic . HashSet < string > > GlobalGroupSettingsMap
= new System . Collections . Generic . Dictionary < string , System . Collections . Generic . HashSet < string > > ( ) ;
private System . Collections . Generic . List < PlatformSpecificSettingsData > PlatformSpecificSettingsGroups
= new System . Collections . Generic . List < PlatformSpecificSettingsData > ( ) ;
#if UNITY_2019_1_OR_NEWER
public override void OnActivate ( string searchContext , UnityEngine . UIElements . VisualElement rootElement )
#elif UNITY_2018_3_OR_NEWER
public override void OnActivate ( string searchContext , UnityEngine . Experimental . UIElements . VisualElement rootElement )
#else
public void OnEnable ( )
#endif
{
UpdateRequired = true ;
#if UNITY_2018_3_OR_NEWER
serializedObject = new UnityEditor . SerializedObject ( Instance ) ;
#endif
GlobalGroupSettingsMap . Clear ( ) ;
foreach ( var settingsGroup in new [ ] { UserSettings , AdvancedSettings , CommsSettings } )
{
var property = serializedObject . FindProperty ( settingsGroup ) ;
if ( property = = null )
return ;
var type = System . Type . GetType ( property . type ) ;
foreach ( var field in type . GetFields ( ) )
{
var childProperty = property . FindPropertyRelative ( field . Name ) ;
if ( childProperty = = null )
continue ;
System . Collections . Generic . HashSet < string > hashSet = null ;
if ( ! GlobalGroupSettingsMap . TryGetValue ( settingsGroup , out hashSet ) )
{
hashSet = new System . Collections . Generic . HashSet < string > ( ) ;
GlobalGroupSettingsMap . Add ( settingsGroup , hashSet ) ;
}
hashSet . Add ( childProperty . propertyPath ) ;
}
}
GlobalSettingsGroups . Clear ( ) ;
GlobalSettingsGroups . Add ( new GlobalSettingsGroupData ( UserSettings , serializedObject , "" , GlobalGroupSettingsMap [ UserSettings ] ) ) ;
GlobalSettingsGroups . Add ( new GlobalSettingsGroupData ( AdvancedSettings , serializedObject , "" , GlobalGroupSettingsMap [ AdvancedSettings ] ) ) ;
GlobalSettingsGroups . Add ( new GlobalSettingsGroupData ( CommsSettings , serializedObject , "Wwise Communication Settings" , GlobalGroupSettingsMap [ CommsSettings ] ) ) ;
}
#if UNITY_2018_3_OR_NEWER
public override void OnGUI ( string searchContext )
#else
public override void OnInspectorGUI ( )
#endif
{
if ( ! Instance . IsValid )
{
UnityEditor . EditorGUILayout . HelpBox ( "Platform names do not correspond with their associated settings data." , UnityEditor . MessageType . Error ) ;
return ;
}
var labelWidth = UnityEditor . EditorGUIUtility . labelWidth ;
UnityEditor . EditorGUIUtility . labelWidth + = 100 ;
UpdatePlatformData ( ) ;
DrawHelpBox ( ) ;
UnityEditor . EditorGUILayout . Space ( ) ;
if ( PreviousPlatformSettingsList . Count = = 0 )
{
if ( ! AkUtilities . IsWwiseProjectAvailable )
{
UnityEditor . EditorGUILayout . HelpBox ( "The Wwise project is not available. Please specify its location within the Wwise Settings." , UnityEditor . MessageType . Warning ) ;
return ;
}
UnityEditor . EditorGUILayout . HelpBox ( "No Wwise platforms have been added. Editing global settings." , UnityEditor . MessageType . Warning ) ;
UnityEditor . EditorGUILayout . Space ( ) ;
}
UnityEditor . EditorGUI . BeginChangeCheck ( ) ;
serializedObject . Update ( ) ;
foreach ( var setting in GlobalSettingsGroups )
setting . Draw ( ) ;
serializedObject . ApplyModifiedProperties ( ) ;
UnityEditor . EditorGUILayout . Space ( ) ;
foreach ( var setting in PlatformSpecificSettingsGroups )
setting . Draw ( ) ;
if ( UnityEditor . EditorGUI . EndChangeCheck ( ) )
Instance . ActiveSettingsHaveChanged = true ;
UnityEditor . EditorGUIUtility . labelWidth = labelWidth ;
}
private bool UpdateRequired = false ;
private void UpdatePlatformData ( )
{
if ( ! UpdateRequired )
{
var firstNotSecond = System . Linq . Enumerable . Except ( PreviousPlatformSettingsList , Instance . PlatformSettingsList ) ;
var secondNotFirst = System . Linq . Enumerable . Except ( Instance . PlatformSettingsList , PreviousPlatformSettingsList ) ;
var refreshRequired = System . Linq . Enumerable . Any ( firstNotSecond ) | | System . Linq . Enumerable . Any ( secondNotFirst ) ;
if ( ! refreshRequired )
{
foreach ( var platformSettings in Instance . PlatformSettingsList )
{
if ( platformSettings = = null )
{
refreshRequired = true ;
break ;
}
}
if ( ! refreshRequired )
return ;
}
}
else
{
UpdateRequired = false ;
}
PreviousPlatformSettingsList . Clear ( ) ;
PlatformSpecificSettingsGroups . Clear ( ) ;
var platformNames = new System . Collections . Generic . HashSet < string > ( ) ;
foreach ( var setting in GlobalSettingsGroups )
setting . ClearPlatformData ( ) ;
for ( var i = 0 ; i < Instance . Count ; + + i )
{
var platformSettings = Instance . PlatformSettingsList [ i ] ;
if ( ! platformSettings )
continue ;
var platformName = Instance . PlatformSettingsNameList [ i ] ;
if ( string . IsNullOrEmpty ( platformName ) )
continue ;
if ( ! platformNames . Contains ( platformName ) )
{
platformNames . Add ( platformName ) ;
PreviousPlatformSettingsList . Add ( platformSettings ) ;
var platform = new PlatformData
{
Settings = platformSettings ,
Name = platformName ,
SerializedObject = new UnityEditor . SerializedObject ( platformSettings )
} ;
foreach ( var setting in GlobalSettingsGroups )
setting . SetupPlatform ( platform ) ;
foreach ( var settingsGroup in new [ ] { UserSettings , AdvancedSettings , CommsSettings } )
PlatformSpecificSettingsGroups . Add ( new PlatformSpecificSettingsData ( platform , settingsGroup , GlobalGroupSettingsMap [ settingsGroup ] ) ) ;
}
}
}
private static void DrawHelpBox ( )
{
if ( Instance . ActiveSettingsHaveChanged )
{
var hash = GetHashOfActiveSettings ( ) ;
Instance . ActiveSettingsHaveChanged = string . IsNullOrEmpty ( hash ) | | hash ! = Instance . ActiveSettingsHash ;
}
var helpBoxText = "No changes have been made. Please be advised that changes will take effect once the Editor exits play mode." ;
var messageType = UnityEditor . MessageType . Info ;
if ( UnityEditor . EditorApplication . isPlayingOrWillChangePlaymode | | UnityEditor . EditorApplication . isPlaying | | UnityEditor . BuildPipeline . isBuildingPlayer )
{
helpBoxText = "Changes will take effect once the Editor exits play mode." ;
}
else if ( Instance . ActiveSettingsHaveChanged )
{
helpBoxText = "Changes have been made and will take effect once the Editor exits play mode." ;
messageType = UnityEditor . MessageType . Warning ;
}
UnityEditor . EditorGUILayout . HelpBox ( helpBoxText , messageType ) ;
}
private static System . Collections . Generic . IEnumerable < UnityEditor . SerializedProperty > GetChildren ( UnityEditor . SerializedProperty property )
{
property = property . Copy ( ) ;
var nextElement = property . Copy ( ) ;
bool hasNextElement = nextElement . Next ( false ) ;
if ( ! hasNextElement )
nextElement = null ;
if ( ! property . Next ( true ) )
yield break ;
while ( ! UnityEditor . SerializedProperty . EqualContents ( property , nextElement ) )
{
yield return property . Copy ( ) ;
if ( ! property . Next ( false ) )
break ;
}
}
private static bool DrawFoldout ( UnityEditor . SerializedProperty property , UnityEngine . GUIContent label , UnityEngine . FontStyle fontStyle )
{
var settingsFoldoutStyle = new UnityEngine . GUIStyle ( UnityEditor . EditorStyles . foldout ) { fontStyle = fontStyle } ;
var value = UnityEditor . EditorGUILayout . Foldout ( property . isExpanded , label , true , settingsFoldoutStyle ) ;
property . isExpanded = value ;
return value ;
}
private class PlatformData
{
public PlatformSettings Settings ;
public UnityEditor . SerializedObject SerializedObject ;
public string Name ;
}
private class GlobalSettingsGroupData
{
string ToolTip ;
string DisplayName ;
UnityEditor . SerializedProperty Property ;
System . Collections . Generic . List < GlobalSettingData > SettingsList ;
public GlobalSettingsGroupData ( string settingsGroup , UnityEditor . SerializedObject serializedObject , string displayName , System . Collections . Generic . HashSet < string > propertyHashSet )
{
Property = serializedObject . FindProperty ( settingsGroup ) ;
if ( Property = = null )
return ;
ToolTip = AkUtilities . GetTooltip ( Property ) ;
DisplayName = string . IsNullOrEmpty ( displayName ) ? ( "Common " + Property . displayName ) : displayName ;
SettingsList = new System . Collections . Generic . List < GlobalSettingData > ( ) ;
foreach ( var childPropertyPath in propertyHashSet )
{
var childProperty = serializedObject . FindProperty ( childPropertyPath ) ;
if ( childProperty = = null )
continue ;
SettingsList . Add ( new GlobalSettingData ( childProperty , childPropertyPath ) ) ;
}
}
public void SetupPlatform ( PlatformData platform )
{
if ( SettingsList = = null | | SettingsList . Count = = 0 )
return ;
foreach ( var settings in SettingsList )
settings . SetupPlatform ( platform ) ;
}
public void ClearPlatformData ( )
{
if ( SettingsList ! = null )
foreach ( var setting in SettingsList )
setting . ClearPlatformData ( ) ;
}
public void Draw ( )
{
if ( SettingsList = = null | | SettingsList . Count = = 0 )
return ;
using ( var verticalScope = new UnityEditor . EditorGUILayout . VerticalScope ( "box" ) )
{
#if ! UNITY_2018_3_OR_NEWER
+ + UnityEditor . EditorGUI . indentLevel ;
#endif
var label = new UnityEngine . GUIContent { text = DisplayName , tooltip = ToolTip } ;
if ( DrawFoldout ( Property , label , UnityEngine . FontStyle . Bold ) )
foreach ( var settings in SettingsList )
settings . Draw ( ) ;
#if ! UNITY_2018_3_OR_NEWER
- - UnityEditor . EditorGUI . indentLevel ;
#endif
}
}
public class GlobalSettingData
{
string ToolTip ;
readonly string DisplayName ;
readonly string PropertyPath ;
readonly bool IsStringValue ;
UnityEditor . SerializedProperty Property ;
readonly UnityEditor . SerializedPropertyType PropertyType ;
System . Collections . Generic . List < PlatformSettingData > SettingsList ;
System . Collections . Generic . List < GlobalSettingData > Children ;
bool HasChildren { get { return Children ! = null & & Children . Count > 0 ; } }
public GlobalSettingData ( UnityEditor . SerializedProperty property , string propertyPath )
{
Property = property ;
PropertyType = property . propertyType ;
PropertyPath = propertyPath ;
DisplayName = property . displayName ;
ToolTip = AkUtilities . GetTooltip ( property ) ;
if ( property . type = = "string" )
{
IsStringValue = true ;
}
else if ( property . hasChildren )
{
Children = new System . Collections . Generic . List < GlobalSettingData > ( ) ;
foreach ( var child in GetChildren ( property ) )
Children . Add ( new GlobalSettingData ( child , child . propertyPath ) ) ;
}
}
public void SetupPlatform ( PlatformData platform )
{
if ( HasChildren )
{
foreach ( var child in Children )
child . SetupPlatform ( platform ) ;
}
else
{
if ( platform . Settings . IsPropertyIgnored ( PropertyPath ) )
return ;
if ( SettingsList = = null )
SettingsList = new System . Collections . Generic . List < PlatformSettingData > ( ) ;
SettingsList . Add ( new PlatformSettingData ( platform , PropertyPath , ToolTip ) ) ;
}
}
public void ClearPlatformData ( )
{
SettingsList = null ;
if ( HasChildren )
foreach ( var child in Children )
child . ClearPlatformData ( ) ;
}
private bool AnyChildUsesGlobalValue
{
get
{
if ( Children ! = null & & Children . Count > 0 )
{
foreach ( var child in Children )
if ( child . AnyChildUsesGlobalValue )
return true ;
return false ;
}
if ( SettingsList = = null | | SettingsList . Count = = 0 )
return true ;
foreach ( var settings in SettingsList )
if ( settings . Platform . Settings . GlobalPropertyHashSet . Contains ( PropertyPath ) )
return true ;
return false ;
}
}
private bool AllChildrenAreEqual
{
get
{
if ( Children ! = null & & Children . Count > 0 )
{
foreach ( var child in Children )
if ( ! child . AllChildrenAreEqual )
return false ;
return true ;
}
if ( SettingsList = = null )
return true ;
switch ( PropertyType )
{
case UnityEditor . SerializedPropertyType . Boolean :
var boolValue = Property . boolValue ;
foreach ( var settings in SettingsList )
if ( boolValue ! = settings . Property . boolValue )
return false ;
return true ;
case UnityEditor . SerializedPropertyType . Enum :
var enumValueIndex = Property . enumValueIndex ;
foreach ( var settings in SettingsList )
if ( enumValueIndex ! = settings . Property . enumValueIndex )
return false ;
return true ;
case UnityEditor . SerializedPropertyType . Float :
var floatValue = Property . floatValue ;
foreach ( var settings in SettingsList )
if ( floatValue ! = settings . Property . floatValue )
return false ;
return true ;
case UnityEditor . SerializedPropertyType . Integer :
var longValue = Property . longValue ;
foreach ( var settings in SettingsList )
if ( longValue ! = settings . Property . longValue )
return false ;
return true ;
case UnityEditor . SerializedPropertyType . String :
var stringValue = Property . stringValue ;
foreach ( var settings in SettingsList )
if ( stringValue ! = settings . Property . stringValue )
return false ;
return true ;
}
return true ;
}
}
public void Draw ( )
{
var hasChanged = false ;
var isString = IsStringValue ;
var hasChildren = HasChildren ;
if ( ! hasChildren & & ( SettingsList = = null | | SettingsList . Count = = 0 ) )
return ;
using ( var verticalScope = new UnityEditor . EditorGUILayout . VerticalScope ( ) )
{
var indentLevel = UnityEditor . EditorGUI . indentLevel + + ;
var forceExpand = ! AnyChildUsesGlobalValue ;
var label = new UnityEngine . GUIContent ( DisplayName , ToolTip ) ;
if ( hasChildren )
{
DrawFoldout ( Property , label , AllChildrenAreEqual ? UnityEngine . FontStyle . Normal : UnityEngine . FontStyle . Italic ) ;
}
else if ( ! forceExpand )
{
DrawFoldout ( Property , label , AllChildrenAreEqual ? UnityEngine . FontStyle . Normal : UnityEngine . FontStyle . Italic ) ;
UnityEditor . EditorGUI . BeginChangeCheck ( ) ;
var labelWithTooltipOnly = new UnityEngine . GUIContent { tooltip = ToolTip } ;
if ( isString )
UnityEditor . EditorGUILayout . DelayedTextField ( Property , labelWithTooltipOnly ) ;
else
UnityEditor . EditorGUILayout . PropertyField ( Property , labelWithTooltipOnly , false ) ;
hasChanged = UnityEditor . EditorGUI . EndChangeCheck ( ) ;
}
else
{
UnityEditor . EditorGUILayout . LabelField ( label ) ;
}
if ( hasChildren )
{
if ( Property . isExpanded )
foreach ( var child in Children )
child . Draw ( ) ;
}
else if ( forceExpand | | Property . isExpanded )
{
foreach ( var settings in SettingsList )
settings . Draw ( Property , PropertyPath , forceExpand , ToolTip ) ;
}
else if ( hasChanged )
{
foreach ( var settings in SettingsList )
if ( settings . Platform . Settings . GlobalPropertyHashSet . Contains ( PropertyPath ) )
settings . UpdateValue ( Property ) ;
}
UnityEditor . EditorGUI . indentLevel = indentLevel ;
}
}
public class PlatformSettingData
{
public UnityEditor . SerializedProperty Property ;
public PlatformData Platform ;
public PlatformSettingData ( PlatformData platform , string propertyPath , string tooltip )
{
Platform = platform ;
Property = Platform . SerializedObject . FindProperty ( propertyPath ) ;
}
public void UpdateValue ( UnityEditor . SerializedProperty globalProperty )
{
if ( Property = = null )
return ;
Platform . SerializedObject . Update ( ) ;
PropagateValue ( Property , globalProperty ) ;
Platform . SerializedObject . ApplyModifiedProperties ( ) ;
}
public void Draw ( UnityEditor . SerializedProperty globalProperty , string propertyPath , bool forceExpand , string tooltip )
{
if ( Property = = null )
return ;
var indentLevel = UnityEditor . EditorGUI . indentLevel + + ;
var position = UnityEngine . GUILayoutUtility . GetRect ( UnityEngine . GUIContent . none , UnityEngine . GUIStyle . none , UnityEngine . GUILayout . Height ( UnityEditor . EditorGUIUtility . singleLineHeight ) ) ;
var wasUsingGlobalValue = Platform . Settings . GlobalPropertyHashSet . Contains ( propertyPath ) ;
var width = position . width ;
if ( ! wasUsingGlobalValue )
position . width = UnityEditor . EditorGUIUtility . labelWidth ;
var isUsingGlobalValue = UnityEditor . EditorGUI . ToggleLeft ( position , new UnityEngine . GUIContent ( Platform . Name , tooltip ) , wasUsingGlobalValue ) ;
position . width = width ;
if ( wasUsingGlobalValue ! = isUsingGlobalValue )
Platform . Settings . SetUseGlobalPropertyValue ( propertyPath , isUsingGlobalValue ) ;
if ( ! isUsingGlobalValue )
{
position . x + = UnityEditor . EditorGUIUtility . labelWidth ;
position . width - = UnityEditor . EditorGUIUtility . labelWidth ;
UnityEditor . EditorGUI . indentLevel = 1 ; // Not zero, so that a control handle is available
Platform . SerializedObject . Update ( ) ;
UnityEditor . EditorGUI . PropertyField ( position , Property , new UnityEngine . GUIContent { tooltip = tooltip } ) ;
Platform . SerializedObject . ApplyModifiedProperties ( ) ;
}
else if ( forceExpand )
PropagateValue ( globalProperty , Property ) ;
else
UpdateValue ( globalProperty ) ;
UnityEditor . EditorGUI . indentLevel = indentLevel ;
}
private static void PropagateValue ( UnityEditor . SerializedProperty x , UnityEditor . SerializedProperty y )
{
//if (x.propertyType != y.propertyType)
// return;
switch ( x . propertyType )
{
case UnityEditor . SerializedPropertyType . Boolean :
x . boolValue = y . boolValue ;
break ;
case UnityEditor . SerializedPropertyType . Enum :
x . longValue = y . longValue ;
break ;
case UnityEditor . SerializedPropertyType . Float :
x . floatValue = y . floatValue ;
break ;
case UnityEditor . SerializedPropertyType . Integer :
x . longValue = y . longValue ;
break ;
case UnityEditor . SerializedPropertyType . String :
x . stringValue = y . stringValue ;
break ;
case UnityEditor . SerializedPropertyType . Generic :
if ( x . type = = y . type )
{
var XProperty = x . Copy ( ) ;
var YProperty = y . Copy ( ) ;
var XEndProperty = x . Copy ( ) ;
var YEndProperty = y . Copy ( ) ;
XEndProperty = XEndProperty . Next ( false ) ? XEndProperty : null ;
YEndProperty = YEndProperty . Next ( false ) ? YEndProperty : null ;
while ( XProperty . Next ( true ) & & YProperty . Next ( true ) & & ! UnityEditor . SerializedProperty . EqualContents ( XProperty , XEndProperty ) & & ! UnityEditor . SerializedProperty . EqualContents ( YProperty , YEndProperty ) )
PropagateValue ( XProperty , YProperty ) ;
}
break ;
}
}
}
}
}
private class PlatformSpecificSettingsData
{
public string ToolTip ;
public UnityEditor . SerializedProperty Property ;
public System . Collections . Generic . List < UnityEditor . SerializedProperty > SettingsList ;
public PlatformData Platform ;
public PlatformSpecificSettingsData ( PlatformData platform , string propertyPath , System . Collections . Generic . HashSet < string > globalPropertyHashSet )
{
Platform = platform ;
Property = Platform . SerializedObject . FindProperty ( propertyPath ) ;
if ( Property = = null )
return ;
ToolTip = AkUtilities . GetTooltip ( Property ) ;
System . Collections . Generic . HashSet < string > hashSet = new System . Collections . Generic . HashSet < string > ( ) ;
foreach ( var childProperty in GetChildren ( Property ) )
hashSet . Add ( childProperty . propertyPath ) ;
var remainder = System . Linq . Enumerable . ToArray ( System . Linq . Enumerable . Except ( hashSet , globalPropertyHashSet ) ) ;
if ( remainder . Length > 0 )
SettingsList = new System . Collections . Generic . List < UnityEditor . SerializedProperty > ( ) ;
foreach ( var childPropertyPath in remainder )
{
var childProperty = Platform . SerializedObject . FindProperty ( childPropertyPath ) ;
if ( childProperty ! = null )
SettingsList . Add ( childProperty ) ;
}
}
public void Draw ( )
{
if ( SettingsList = = null | | SettingsList . Count = = 0 )
return ;
Platform . SerializedObject . Update ( ) ;
using ( new UnityEditor . EditorGUILayout . VerticalScope ( "box" ) )
{
#if ! UNITY_2018_3_OR_NEWER
+ + UnityEditor . EditorGUI . indentLevel ;
#endif
var label = new UnityEngine . GUIContent ( Platform . Name + " Specific " + Property . displayName , ToolTip ) ;
if ( DrawFoldout ( Property , label , UnityEngine . FontStyle . Bold ) )
{
+ + UnityEditor . EditorGUI . indentLevel ;
foreach ( var child in SettingsList )
UnityEditor . EditorGUILayout . PropertyField ( child , true ) ;
- - UnityEditor . EditorGUI . indentLevel ;
}
#if ! UNITY_2018_3_OR_NEWER
- - UnityEditor . EditorGUI . indentLevel ;
#endif
}
Platform . SerializedObject . ApplyModifiedProperties ( ) ;
}
}
}
#endregion
#endif
}
2021-04-30 07:09:07 +01:00