/// <summary> /// Find references of source in mine, and set their counterparts in Theirs to copy. This "start" function calls /// FindRefs which searches the whole object's hierarchy, and then calls UnsetFlagRecursive to reset the flag /// used to avoid searching the same object twice /// </summary> /// <param name="window">The ObjectMergeWindow doing the merge</param> /// <param name="source">The source object to find references within</param> /// <param name="copy">The copy we just made of source</param> /// <param name="isMine">Whether the source object is on the mine (left) side</param> /// <returns>Iterator, for coroutine update</returns> static IEnumerator FindAndSetRefs(ObjectMerge window, GameObject source, GameObject copy, bool isMine) { var root = window.root; var sourceObjs = new List <GameObject>(); var copyObjs = new List <GameObject>(); var srcProps = new List <SerializedProperty>(); var copyProps = new List <SerializedProperty>(); var sourceComps = new List <Component>(); var copyComps = new List <Component>(); Util.GameObjectToList(source, sourceObjs); yield return(null); Util.GameObjectToList(copy, copyObjs); yield return(null); #if UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER source.GetComponentsInChildren(sourceComps); yield return(null); copy.GetComponentsInChildren(copyComps); #else sourceComps.AddRange(source.GetComponents <Component>()); yield return(null); copyComps.AddRange(copy.GetComponents <Component>()); #endif yield return(null); var searchList = new List <GameObjectHelper>(); root.ToList(searchList); var properties = new List <PropertyHelper>(); var props = new List <SerializedProperty>(); var otherProps = new List <SerializedProperty>(); var objs = new List <object>(searchList.Count); var otherObjs = new List <GameObject>(searchList.Count); var comps = new List <object>(searchList.Count); var otherComps = new List <Component>(searchList.Count); window.updateType = RefreshType.Preparing; window.totalUpdateNum = searchList.Count; window.updateCount = 0; for (var i = 0; i < searchList.Count; i++) { window.updateCount++; var searchObj = searchList[i]; objs.Add(searchObj.GetObject(isMine)); otherObjs.Add(searchObj.GetObject(!isMine)); var searchComponents = searchObj.components; for (var j = 0; j < searchComponents.Count; j++) { var comp = searchComponents[j]; comps.Add(comp.GetComponent(isMine)); otherComps.Add(comp.GetComponent(!isMine)); properties.Clear(); comp.GetFullPropertyList(properties); for (var k = 0; k < properties.Count; k++) { var property = properties[k]; var prop = property.GetProperty(isMine); var otherProp = property.GetProperty(!isMine); if (prop != null && otherProp != null && prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue != null) { props.Add(prop); otherProps.Add(otherProp); } } } yield return(null); } window.updateType = RefreshType.Copying; window.totalUpdateNum = sourceObjs.Count; window.updateCount = 0; for (var i = 0; i < sourceObjs.Count; i++) { window.updateCount++; var sourceObject = sourceObjs[i]; var copyObject = copyObjs[i]; // Find and set refs to the GameObject for (var j = 0; j < props.Count; j++) { var prop = props[j]; var otherProp = otherProps[j]; if (prop.objectReferenceValue == sourceObject) { //Sometimes you get an error here in older versions of Unity about using a //SerializedProperty after the object has been deleted. Don't know how else to //detect this otherProp.objectReferenceValue = copyObject; if (window.log) { Debug.Log("Set reference to " + copyObject + " in " + prop.serializedObject.targetObject + "." + prop.name, prop.serializedObject.targetObject); } if (prop.serializedObject.targetObject != null) { prop.serializedObject.ApplyModifiedProperties(); } } } yield return(null); } window.updateType = RefreshType.Copying; window.totalUpdateNum = sourceComps.Count; window.updateCount = 0; for (var i = 0; i < sourceComps.Count; i++) { window.updateCount++; var sourceComponent = sourceComps[i]; // Missing scripts show up as null if (sourceComponent == null) { continue; } if (sourceComponent is Transform) { continue; } var copyComponent = copyComps[i]; // Find and set refs to the Component for (var l = 0; l < props.Count; l++) { var prop = props[l]; var otherProp = otherProps[l]; if (prop.objectReferenceValue == sourceComponent) { //Sometimes you get an error here in older versions of Unity about using a //SerializedProperty after the object has been deleted. Don't know how else to //detect this otherProp.objectReferenceValue = copyComponent; if (window.log) { Debug.Log("Set reference to " + copyComponent + " in " + prop.serializedObject.targetObject + "." + prop.name, prop.serializedObject.targetObject); } if (prop.serializedObject.targetObject != null) { prop.serializedObject.ApplyModifiedProperties(); } } } yield return(null); //Find references outside the copied hierarchy srcProps.Clear(); copyProps.Clear(); PropertyHelper.GetProperties(srcProps, new SerializedObject(sourceComponent)); PropertyHelper.GetProperties(copyProps, new SerializedObject(copyComponent)); for (var j = 0; j < srcProps.Count; j++) { var srcProp = srcProps[j]; if (srcProp.name == "m_Script") //Ignore the script { continue; } if (srcProp.propertyType == SerializedPropertyType.ObjectReference && srcProp.objectReferenceValue != null) { if (srcProp.objectReferenceValue == null) { continue; } var copyProp = copyProps[j]; if (srcProp.objectReferenceValue is GameObject) { var index = objs.IndexOf(srcProp.objectReferenceValue); if (index >= 0) { var otherobj = otherObjs[index]; if (window.log) { Debug.Log( "Set reference to " + otherobj + " in " + copyProp.serializedObject.targetObject + "." + copyProp.name, copyProp.serializedObject.targetObject); } copyProp.objectReferenceValue = otherobj; } } else { var index = comps.IndexOf(srcProp.objectReferenceValue); if (index >= 0) { var otherComp = otherComps[index]; if (window.log) { Debug.Log( "Set reference to " + otherComp + " in " + copyProp.serializedObject.targetObject + "." + copyProp.name, copyProp.serializedObject.targetObject); } copyProp.objectReferenceValue = otherComp; } } if (copyProp.serializedObject.targetObject != null) { copyProp.serializedObject.ApplyModifiedProperties(); } } yield return(null); } } }
/// <summary> /// Find references of source in mine, and set their counterparts in Theirs to copy. This "start" function calls /// FindRefs which searches the whole object's hierarchy, and then calls UnsetFlagRecursive to reset the flag /// used to avoid searching the same object twice /// </summary> /// <param name="window">The ObjectMergeWindow doing the merge</param> /// <param name="source">The source object to find references within</param> /// <param name="copy">The copy we just made of source</param> /// <param name="isMine">Whether the source object is on the mine (left) side</param> /// <returns>Iterator, for coroutine update</returns> static IEnumerator FindAndSetRefs(ObjectMerge window, UnityObject source, UnityObject copy, bool isMine) { var root = window.root; SrcProps.Clear(); CopyProps.Clear(); Properties.Clear(); Props.Clear(); OtherProps.Clear(); Objs.Clear(); OtherObjs.Clear(); Comps.Clear(); OtherComps.Clear(); SearchList.Clear(); root.ToList(SearchList); var count = SearchList.Count; window.updateType = RefreshType.Preparing; window.totalUpdateNum = count; window.updateCount = 0; for (var i = 0; i < count; i++) { window.updateCount++; var searchObj = SearchList[i]; Objs.Add(searchObj.GetObject(isMine)); OtherObjs.Add(searchObj.GetObject(!isMine)); var searchComponents = searchObj.components; var componentsCount = searchComponents.Count; for (var j = 0; j < componentsCount; j++) { var comp = searchComponents[j]; Comps.Add(comp.GetComponent(isMine)); OtherComps.Add(comp.GetComponent(!isMine)); Properties.Clear(); comp.GetFullPropertyList(Properties); var propertiesCount = Properties.Count; for (var k = 0; k < propertiesCount; k++) { var property = Properties[k]; var prop = property.GetProperty(isMine); var otherProp = property.GetProperty(!isMine); if (prop != null && otherProp != null && prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue != null) { Props.Add(prop); OtherProps.Add(otherProp); } } } yield return(null); } window.updateType = RefreshType.Copying; window.totalUpdateNum = Props.Count; window.updateCount = 0; // Find and set refs to the Component for (var j = 0; j < Props.Count; j++) { var prop = Props[j]; var otherProp = OtherProps[j]; if (prop.objectReferenceValue == source) { //Sometimes you get an error here in older versions of Unity about using a //SerializedProperty after the object has been deleted. Don't know how else to //detect this otherProp.objectReferenceValue = copy; if (window.log) { Debug.Log("Set reference to " + copy + " in " + prop.serializedObject.targetObject + "." + prop.name, prop.serializedObject.targetObject); } if (prop.serializedObject.targetObject != null) { prop.serializedObject.ApplyModifiedProperties(); } } yield return(null); } //Find references in properties SrcProps.Clear(); CopyProps.Clear(); PropertyHelper.GetProperties(SrcProps, new SerializedObject(source)); PropertyHelper.GetProperties(CopyProps, new SerializedObject(copy)); window.updateType = RefreshType.Copying; window.totalUpdateNum = SrcProps.Count; window.updateCount = 0; for (var j = 0; j < SrcProps.Count; j++) { window.updateCount++; var srcProp = SrcProps[j]; if (srcProp.name == "m_Script" || srcProp.name == "m_Father") //Ignore the script and transform parent { continue; } if (srcProp.propertyType == SerializedPropertyType.ObjectReference && srcProp.objectReferenceValue != null) { if (srcProp.objectReferenceValue == null) { continue; } var copyProp = CopyProps[j]; if (srcProp.objectReferenceValue is GameObject) { var index = Objs.IndexOf(srcProp.objectReferenceValue); if (index >= 0) { var otherobj = OtherObjs[index]; if (window.log) { Debug.Log( "Set reference to " + otherobj + " in " + copyProp.serializedObject.targetObject + "." + copyProp.name, copyProp.serializedObject.targetObject); } copyProp.objectReferenceValue = otherobj; } } else { var index = Comps.IndexOf(srcProp.objectReferenceValue); if (index >= 0) { var otherComp = OtherComps[index]; if (window.log) { Debug.Log( "Set reference to " + otherComp + " in " + copyProp.serializedObject.targetObject + "." + copyProp.name, copyProp.serializedObject.targetObject); } copyProp.objectReferenceValue = otherComp; } } if (copyProp.serializedObject.targetObject != null) { copyProp.serializedObject.ApplyModifiedProperties(); } yield return(null); } } }