////////////////////////////////////////////////////////////////////// // // Copyright (c) 2018 Audiokinetic Inc. / All Rights Reserved // ////////////////////////////////////////////////////////////////////// using System.Collections.Generic; /// @brief Represents Wwise objects as Unity assets. public abstract class WwiseObjectReference : UnityEngine.ScriptableObject { #region Serialized fields [AkShowOnly] [UnityEngine.SerializeField] private string objectName = string.Empty; [AkShowOnly] [UnityEngine.SerializeField] private uint id = AkSoundEngine.AK_INVALID_UNIQUE_ID; [AkShowOnly] [UnityEngine.SerializeField] private string guid = string.Empty; #endregion #region Properties /// /// The Wwise GUID which is represented by the ScriptableObject's asset file name. /// public System.Guid Guid { get { return string.IsNullOrEmpty(guid) ? System.Guid.Empty : new System.Guid(guid); } } /// /// The name of the Wwise object. /// public string ObjectName { get { return objectName; } } /// /// The display name for the Wwise object. /// public virtual string DisplayName { get { return ObjectName; } } /// /// The Wwise ID. /// public uint Id { get { return id; } } /// /// The type of the Wwise object resource (for example: Event, State or Switch). /// public abstract WwiseObjectType WwiseObjectType { get; } #endregion #if UNITY_EDITOR private static Dictionary> s_objectReferenceDictionary = new Dictionary>(); public virtual bool IsComplete() { return true; } public virtual void CompleteData() { } #region Creation and File Management private static readonly System.Collections.Generic.Dictionary m_WwiseObjectReferenceClasses = new System.Collections.Generic.Dictionary { { WwiseObjectType.AcousticTexture, typeof(WwiseAcousticTextureReference) }, { WwiseObjectType.AuxBus, typeof(WwiseAuxBusReference) }, { WwiseObjectType.Soundbank, typeof(WwiseBankReference) }, { WwiseObjectType.Event, typeof(WwiseEventReference) }, { WwiseObjectType.GameParameter, typeof(WwiseRtpcReference) }, { WwiseObjectType.StateGroup, typeof(WwiseStateGroupReference) }, { WwiseObjectType.State, typeof(WwiseStateReference) }, { WwiseObjectType.SwitchGroup, typeof(WwiseSwitchGroupReference) }, { WwiseObjectType.Switch, typeof(WwiseSwitchReference) }, { WwiseObjectType.Trigger, typeof(WwiseTriggerReference) }, }; private static WwiseObjectReference Create(WwiseObjectType wwiseObjectType, System.Guid guid) { System.Type type = null; WwiseObjectReference objectReference = null; if (m_WwiseObjectReferenceClasses.TryGetValue(wwiseObjectType, out type)) { objectReference =(WwiseObjectReference)CreateInstance(type); } else { objectReference = CreateInstance(); } objectReference.guid = guid.ToString().ToUpper(); if (!s_objectReferenceDictionary.ContainsKey(wwiseObjectType)) { FetchAssetsOfType(wwiseObjectType); } if (s_objectReferenceDictionary[wwiseObjectType].ContainsKey(objectReference.Guid)) { s_objectReferenceDictionary[wwiseObjectType][objectReference.Guid] = objectReference; } else { s_objectReferenceDictionary[wwiseObjectType].Add(objectReference.Guid, objectReference); } return objectReference; } protected static WwiseObjectReference FindExistingWwiseObject(WwiseObjectType wwiseObjectType, System.Guid guid, string path) { var asset = UnityEditor.AssetDatabase.LoadAssetAtPath(path); if (asset) return asset; System.Type type = null; if (!m_WwiseObjectReferenceClasses.TryGetValue(wwiseObjectType, out type)) return null; if (!s_objectReferenceDictionary.ContainsKey(wwiseObjectType)) { FetchAssetsOfType(wwiseObjectType); } if (s_objectReferenceDictionary[wwiseObjectType].ContainsKey(guid)) { return s_objectReferenceDictionary[wwiseObjectType][guid]; } return null; } private static void FetchAssetsOfType(WwiseObjectType wwiseObjectType) { System.Type type = null; if (!m_WwiseObjectReferenceClasses.TryGetValue(wwiseObjectType, out type)) type = typeof(WwiseObjectReference); var objectReferenceDictionary = new Dictionary(); var guids = UnityEditor.AssetDatabase.FindAssets("t:" + type.Name); foreach (var assetGuid in guids) { var assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assetGuid); var asset = UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath); objectReferenceDictionary[asset.Guid] = asset; } s_objectReferenceDictionary[wwiseObjectType] = objectReferenceDictionary; } private static bool UpdateWwiseObjectData(WwiseObjectReference wwiseObjectReference, string name) { var id = AkUtilities.ShortIDGenerator.Compute(name); var changed = false; if (wwiseObjectReference.objectName != name || wwiseObjectReference.id != id) changed = true; wwiseObjectReference.objectName = name; wwiseObjectReference.id = id; if (!wwiseObjectReference.IsComplete()) { changed = true; wwiseObjectReference.CompleteData(); } return changed; } public static string GetParentPath(WwiseObjectType wwiseObjectType) { return System.IO.Path.Combine(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath, wwiseObjectType.ToString()); } public static string GetAssetFileName(System.Guid guid) { return guid.ToString().ToUpper() + ".asset"; } public static WwiseObjectReference FindOrCreateWwiseObject(WwiseObjectType wwiseObjectType, string name, System.Guid guid) { var parentPath = GetParentPath(wwiseObjectType); var path = System.IO.Path.Combine(parentPath, GetAssetFileName(guid)); var asset = FindExistingWwiseObject(wwiseObjectType, guid, path); var assetExists = asset != null; if (!assetExists) { AkUtilities.CreateFolder(parentPath); asset = Create(wwiseObjectType, guid); } var changed = UpdateWwiseObjectData(asset, name); if (!assetExists) UnityEditor.AssetDatabase.CreateAsset(asset, path); else if (changed) UnityEditor.EditorUtility.SetDirty(asset); return asset; } public static WwiseObjectReference FindWwiseObject(WwiseObjectType wwiseObjectType, System.Guid guid) { var parentPath = GetParentPath(wwiseObjectType); var path = System.IO.Path.Combine(parentPath, GetAssetFileName(guid)); return FindExistingWwiseObject(wwiseObjectType, guid, path); } public static void UpdateWwiseObject(WwiseObjectType wwiseObjectType, string name, System.Guid guid) { var path = System.IO.Path.Combine(GetParentPath(wwiseObjectType), GetAssetFileName(guid)); var asset = FindExistingWwiseObject(wwiseObjectType, guid, path); if (asset && UpdateWwiseObjectData(asset, name)) UnityEditor.EditorUtility.SetDirty(asset); } public static void DeleteWwiseObject(WwiseObjectType wwiseObjectType, System.Guid guid) { var path = System.IO.Path.Combine(GetParentPath(wwiseObjectType), GetAssetFileName(guid)); var guidString = UnityEditor.AssetDatabase.AssetPathToGUID(path); if (!string.IsNullOrEmpty(guidString)) UnityEditor.AssetDatabase.DeleteAsset(path); } #endregion #region WwiseMigration private class WwiseObjectData { public string objectName; } private static System.Collections.Generic.Dictionary> WwiseObjectDataMap = new System.Collections.Generic.Dictionary>(); public static void ClearWwiseObjectDataMap() { WwiseObjectDataMap.Clear(); } public static void UpdateWwiseObjectDataMap(WwiseObjectType wwiseObjectType, string name, System.Guid guid) { System.Collections.Generic.Dictionary map = null; if (!WwiseObjectDataMap.TryGetValue(wwiseObjectType, out map)) { map = new System.Collections.Generic.Dictionary(); WwiseObjectDataMap.Add(wwiseObjectType, map); } WwiseObjectData data = null; if (!map.TryGetValue(guid, out data)) { data = new WwiseObjectData(); map.Add(guid, data); } data.objectName = name; } public static WwiseObjectReference GetWwiseObjectForMigration(WwiseObjectType wwiseObjectType, byte[] valueGuid, int id) { if (valueGuid == null) { return null; } System.Collections.Generic.Dictionary map = null; if (!WwiseObjectDataMap.TryGetValue(wwiseObjectType, out map) || map == null) { UnityEngine.Debug.LogWarning("WwiseUnity: Cannot find WwiseObjectReferences of type ."); return null; } var guid = System.Guid.Empty; WwiseObjectData data = null; try { guid = new System.Guid(valueGuid); } catch { UnityEngine.Debug.LogWarning("WwiseUnity: Invalid guid for WwiseObjectReference of type ."); return null; } var formattedId = (uint)id; if (guid != System.Guid.Empty && !map.TryGetValue(guid, out data)) { UnityEngine.Debug.LogWarning("WwiseUnity: Cannot find guid <" + guid.ToString() + "> for WwiseObjectReference of type in Wwise Project."); foreach (var pair in map) { if (AkUtilities.ShortIDGenerator.Compute(pair.Value.objectName) == formattedId) { guid = pair.Key; data = pair.Value; UnityEngine.Debug.LogWarning("WwiseUnity: Found guid <" + guid.ToString() + "> for <" + pair.Value.objectName + ">."); break; } } } if (data == null) { return null; } var objectReference = FindOrCreateWwiseObject(wwiseObjectType, data.objectName, guid); if (objectReference && objectReference.Id != formattedId) { UnityEngine.Debug.LogWarning("WwiseUnity: ID mismatch for WwiseObjectReference of type . Expected <" + formattedId + ">. Found <" + objectReference.Id + ">."); } return objectReference; } #endregion #endif } /// @brief Represents Wwise group value objects (such as states and switches) as Unity assets. public abstract class WwiseGroupValueObjectReference : WwiseObjectReference { #region Properties /// /// The group object reference. /// public abstract WwiseObjectReference GroupObjectReference { get; set; } /// /// The type of the Wwise object resource (for example: Event, State or Switch). /// public abstract WwiseObjectType GroupWwiseObjectType { get; } /// /// The display name for the Wwise object. /// public override string DisplayName { get { #if AK_DISPLAY_GROUP_TYPES_WITH_SINGLE_NAME return ObjectName; #else var groupReference = GroupObjectReference; if (!groupReference) return ObjectName; return groupReference.ObjectName + " / " + ObjectName; #endif // AK_DISPLAY_GROUP_TYPES_WITH_SINGLE_NAME } } #endregion #if UNITY_EDITOR public void SetupGroupObjectReference(string name, System.Guid guid) { var objectReference = FindOrCreateWwiseObject(GroupWwiseObjectType, name, guid); if (objectReference != GroupObjectReference) { GroupObjectReference = objectReference; UnityEditor.EditorUtility.SetDirty(this); } } #region WwiseMigration public static WwiseGroupValueObjectReference GetWwiseObjectForMigration(WwiseObjectType wwiseObjectType, byte[] valueGuid, int id, byte[] groupGuid, int groupId) { var objectReference = GetWwiseObjectForMigration(wwiseObjectType, valueGuid, id); if (!objectReference) return null; var groupValueObjectReference = objectReference as WwiseGroupValueObjectReference; if (!groupValueObjectReference) { UnityEngine.Debug.LogWarning("WwiseUnity: Not setting WwiseObjectReference since it is not a WwiseGroupValueObjectReference."); return null; } var groupObjectReference = GetWwiseObjectForMigration(groupValueObjectReference.GroupWwiseObjectType, groupGuid, groupId); if (!groupObjectReference) { UnityEngine.Debug.LogWarning("WwiseUnity: Not setting WwiseObjectReference since its GroupObjectReference cannot be determined."); return null; } groupValueObjectReference.GroupObjectReference = groupObjectReference; UnityEditor.EditorUtility.SetDirty(groupValueObjectReference); return groupValueObjectReference; } #endregion #endif } #if UNITY_EDITOR public static class AkWwiseTypes { private const string DragAndDropId = "AkDragDropId"; public static WwiseObjectReference DragAndDropObjectReference { set { UnityEditor.DragAndDrop.SetGenericData(DragAndDropId, value); } get { return UnityEditor.DragAndDrop.GetGenericData(DragAndDropId) as WwiseObjectReference; } } } #endif