using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Xml.Serialization; using UnityEditor; using UnityEngine; namespace DarkTonic.MasterAudio.EditorScripts { // ReSharper disable once CheckNamespace public class MAComponentPatch { private const string IgnoredPropertyNames = ";useConeFriction;sleepVelocity;sleepAngularVelocity;WillCleanUpDelegatesAfterStop;roomRolloffFactor;"; private Dictionary _values; public MAComponentPatch(Component component) { ComponentObject = component; } private bool _isComponentObjectNull = true; private Component _componentObject; private Component ComponentObject { get { return _componentObject; } set { _componentObject = value; _isComponentObjectNull = _componentObject == null; } } public string ComponentName { get { var parts = ComponentObject.GetType().ToString().Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); return parts[parts.Length - 1]; } } public void StoreSettings() { if (ComponentObject == null) { return; } _values = new Dictionary(StringComparer.OrdinalIgnoreCase); var properties = GetProperties(); var fields = GetFields(); foreach (var property in properties) { if (IgnoredPropertyNames.Contains(";" + property.Name + ";")) { continue; } if (_values.ContainsKey(property.Name)) { continue; } _values.Add(property.Name, property.GetValue(ComponentObject, null)); } foreach (var field in fields) { if (_values.ContainsKey(field.Name)) { continue; } _values.Add(field.Name, field.GetValue(ComponentObject)); } } private IEnumerable GetFields() { var fields = new List(); foreach (var fieldInfo in ComponentObject.GetType().GetFields()) { if (!fieldInfo.IsPublic) { continue; } if (!Attribute.IsDefined(fieldInfo, typeof(HideInInspector))) { fields.Add(fieldInfo); } } return fields; } private IEnumerable GetProperties() { var properties = new List(); foreach (var propertyInfo in ComponentObject.GetType().GetProperties()) { if (Attribute.IsDefined(propertyInfo, typeof(HideInInspector))) { continue; } var setMethod = propertyInfo.GetSetMethod(); if (null != setMethod && setMethod.IsPublic) { properties.Add(propertyInfo); } } return properties; } //return component is changes have been made public Component RestoreSettings() { Component resultChangedComponent = null; if (!_isComponentObjectNull) { ComponentObject = EditorUtility.InstanceIDToObject(ComponentObject.GetInstanceID()) as Component; } else { ComponentObject = null; } if (ComponentObject != null && _values != null) { foreach (var name in _values.Keys) { var newValue = _values[name]; var property = ComponentObject.GetType().GetProperty(name); if (null != property) { var currentValue = property.GetValue(ComponentObject, null); if (!HasValueChanged(newValue, currentValue)) { continue; } property.SetValue(ComponentObject, newValue, null); resultChangedComponent = ComponentObject; } else { var field = ComponentObject.GetType().GetField(name); var currentValue = field.GetValue(ComponentObject); if (!HasValueChanged(newValue, currentValue)) { continue; } if (ComponentObject.ToString().Contains("DarkTonic.MasterAudio.MasterAudio")) { switch (field.Name) { case "customEvents": FilterOutDGSCCustomEvents(ref newValue); break; case "customEventCategories": FilterOutDGSCCustomEventCategories(ref newValue); break; case "musicPlaylists": FilterOutDGSCPlaylists(ref newValue); break; case "groupBuses": FilterOutDGSCBuses(ref newValue); break; case "musicDuckingSounds": FilterOutDGSCDuckGroups(ref newValue); break; } } field.SetValue(ComponentObject, newValue); resultChangedComponent = ComponentObject; } } } _values = null; return resultChangedComponent; } private static void FilterOutDGSCDuckGroups(ref object duckGroups) { var ducks = duckGroups as List; if (ducks == null) { return; } var itemsToDelete = new List(ducks.Count); for (var i = 0; i < ducks.Count; i++) { var aDuck = ducks[i]; if (aDuck.isTemporary) { itemsToDelete.Add(aDuck); } } for (var i = 0; i < itemsToDelete.Count; i++) { ducks.Remove(itemsToDelete[i]); } duckGroups = ducks; } private static void FilterOutDGSCBuses(ref object busList) { var buses = busList as List; if (buses == null) { return; } var itemsToDelete = new List(buses.Count); for (var i = 0; i < buses.Count; i++) { var aBus = buses[i]; if (aBus.isTemporary) { itemsToDelete.Add(aBus); } } for (var i = 0; i < itemsToDelete.Count; i++) { buses.Remove(itemsToDelete[i]); } busList = buses; } private static void FilterOutDGSCPlaylists(ref object pList) { var playlists = pList as List; if (playlists == null) { return; } var itemsToDelete = new List(playlists.Count); for (var i = 0; i < playlists.Count; i++) { var aPlaylist = playlists[i]; if (aPlaylist.isTemporary) { itemsToDelete.Add(aPlaylist); } } for (var i = 0; i < itemsToDelete.Count; i++) { playlists.Remove(itemsToDelete[i]); } pList = playlists; } private static void FilterOutDGSCCustomEventCategories(ref object cats) { var custEventCats = cats as List; if (custEventCats == null) { return; } var itemsToDelete = new List(custEventCats.Count); for (var i = 0; i < custEventCats.Count; i++) { var aCat = custEventCats[i]; if (aCat.IsTemporary) { itemsToDelete.Add(aCat); } } for (var i = 0; i < itemsToDelete.Count; i++) { custEventCats.Remove(itemsToDelete[i]); } cats = custEventCats; } private static void FilterOutDGSCCustomEvents(ref object events) { var custEvents = events as List; if (custEvents == null) { return; } var itemsToDelete = new List(custEvents.Count); for (var i = 0; i < custEvents.Count; i++) { var anEvent = custEvents[i]; if (anEvent.isTemporary) { itemsToDelete.Add(anEvent); } } for (var i = 0; i < itemsToDelete.Count; i++) { custEvents.Remove(itemsToDelete[i]); } events = custEvents; } private static bool HasValueChanged(object newValue, object oldValue) { var valuesChanged = true; if (null != newValue && null != oldValue) { var valueToCompare = newValue as IComparable; if (null == valueToCompare) { try { var serializer = new XmlSerializer(newValue.GetType()); using (var streamNew = new MemoryStream()) { serializer.Serialize(streamNew, newValue); var encoding = new UTF8Encoding(); var oldValueSerialized = encoding.GetString(streamNew.ToArray()); using (var streamOld = new MemoryStream()) { serializer.Serialize(streamOld, oldValue); var newValueSerialized = encoding.GetString(streamOld.ToArray()); valuesChanged = !string.Equals(newValueSerialized, oldValueSerialized); } } } catch { valuesChanged = true; } } else { valuesChanged = valueToCompare.CompareTo(oldValue) != 0; } } else if (null == oldValue && null == newValue) { valuesChanged = false; } return valuesChanged; } } }