public PropertyHelper(SerializedProperty mine, SerializedProperty theirs, string propertyPath, Helper parent = null, UniMergeWindow window = null) : base(parent, window) { this.mine = mine; this.theirs = theirs; this.propertyPath = propertyPath; objectMerge = window as ObjectMerge; sceneMerge = window as SceneMerge; gameObjectParent = parent as GameObjectHelper; componentParent = parent as ComponentHelper; propertyParent = parent as PropertyHelper; }
PropertyHelper(SerializedProperty mine, SerializedProperty theirs, string propertyPath, SerializedPropertyType propertyType, GameObjectHelper gameObjectParent, ComponentHelper componentParent, PropertyHelper propertyParent, Helper parent, UniMergeWindow window, ObjectMerge objectMerge, SceneMerge sceneMerge) : base(parent, window, objectMerge, sceneMerge) { this.mine = mine; this.theirs = theirs; this.propertyPath = propertyPath; this.propertyType = propertyType; this.gameObjectParent = gameObjectParent; this.componentParent = componentParent; this.propertyParent = propertyParent; }
void DrawComponent(bool isMine, GUILayoutOption indent, GUILayoutOption colWidth) { GUILayout.BeginVertical(colWidth); #if Unity3 GUILayout.Space(3); #endif componentArg = GetComponent(isMine); thisArg = this; Util.Indent(indent, DrawComponentRow); #if Unity3 GUILayout.Space(-4); #endif GUILayout.EndVertical(); }
/// <summary> /// Refresh is a very crucial function. Not only does it refresh the abstracted lists of ObjectHelpers and /// ComponentHelpers to reflect the actual scene, /// it is responsible for actually comparing objects /// </summary> /// <returns>IEnumerator for coroutine progress</returns> public IEnumerator DoRefresh() { Same = true; MyChildren.Clear(); TheirChildren.Clear(); MyComponents.Clear(); TheirComponents.Clear(); //Get lists of components and children if (mine) { window.updateCount++; MyChildren.AddRange(from Transform t in mine.transform select t.gameObject); #if UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER mine.GetComponents(MyComponents); #else MyComponents.AddRange(mine.GetComponents <Component>()); #endif } if (theirs) { window.updateCount++; TheirChildren.AddRange(from Transform t in theirs.transform select t.gameObject); #if UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER theirs.GetComponents(TheirComponents); #else TheirComponents.AddRange(theirs.GetComponents <Component>()); #endif } // Clear empty components components.RemoveAll(helper => helper.mine == null && helper.theirs == null); //TODO: turn these two chunks into one function... somehow //Merge Components ComponentHelper ch; for (var i = 0; i < MyComponents.Count; i++) { var component = MyComponents[i]; // Missing scripts show up as null if (component == null) { continue; } var match = TheirComponents.Where(g => g != null).FirstOrDefault(g => component.GetType() == g.GetType()); ch = components.Find(helper => helper.mine == component || match != null && helper.theirs == match); if (ch == null) { ch = new ComponentHelper(component, match, this, window); components.Add(ch); } else { ch.mine = component; ch.theirs = match; } var enumerator = ch.Refresh(); while (enumerator.MoveNext()) { yield return(null); } if (!ComponentIsFiltered(ch.type) && !ch.Same) { Same = false; } TheirComponents.Remove(match); } if (TheirComponents.Count > 0) { foreach (var g in TheirComponents) { // Missing scripts show up as null if (g == null) { continue; } ch = components.Find(helper => helper.theirs == g); if (ch == null) { ch = new ComponentHelper(null, g, this, window); var enumerator = ch.Refresh(); while (enumerator.MoveNext()) { yield return(null); } components.Add(ch); } if (!ComponentIsFiltered(ch.type) && !ch.Same) { Same = false; } } } // Clear empty components if (children != null) { children.RemoveAll(helper => helper.mine == null && helper.theirs == null); } //Merge Children GameObjectHelper oh = null; foreach (var child in MyChildren) { var match = TheirChildren.FirstOrDefault(g => SameObject(child, g)); if (children != null) { oh = children.Find(helper => helper.mine == child || match != null && helper.theirs == match); } if (oh == null) { oh = new GameObjectHelper(window, this) { mine = child, theirs = match }; if (children == null) { children = new List <GameObjectHelper>(); } children.Add(oh); } else { oh.mine = child; oh.theirs = match; } TheirChildren.Remove(match); } if (TheirChildren.Count > 0) { Same = false; foreach (var g in TheirChildren) { if (children != null) { oh = children.Find(helper => helper.theirs == g); } if (oh == null) { if (children == null) { children = new List <GameObjectHelper>(); } children.Add(new GameObjectHelper(window, this) { theirs = g }); } } } tmpList.Clear(); if (children != null) { tmpList.AddRange(children); foreach (var obj in tmpList) { if (obj.mine == null && obj.theirs == null) { children.Remove(obj); } } children.Sort(delegate(GameObjectHelper a, GameObjectHelper b) { if (a.mine && b.mine) { return(a.mine.name.CompareTo(b.mine.name)); } if (a.mine && b.theirs) { return(a.mine.name.CompareTo(b.theirs.name)); } if (a.theirs && b.mine) { return(a.theirs.name.CompareTo(b.mine.name)); } if (a.theirs && b.theirs) { return(a.theirs.name.CompareTo(b.theirs.name)); } return(0); }); tmpList.Clear(); tmpList.AddRange(children); foreach (var child in tmpList) { var enumerator = child.DoRefresh(); while (enumerator.MoveNext()) { yield return(null); } if (!child.Same) { Same = false; } } } if (mine) { mySO = new SerializedObject(mine); } if (theirs) { theirSO = new SerializedObject(theirs); } var e = PropertyHelper.UpdatePropertyList(attributes, mySO, theirSO, this, window, true); while (e.MoveNext()) { yield return(null); } sameAttrs = true; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < attributes.Count; i++) { var attribute = attributes[i]; if (!attribute.Same) { sameAttrs = false; } } if (!sameAttrs && window.compareAttrs) { Same = false; } }
public void Draw(float indent, GUILayoutOption colWidth, GUILayoutOption indentOption) { if (window.drawAbort) { return; } if (window.ScrollCheck()) { window.StartRow(Same); //Store foldout state before doing GUI to check if it changed var foldoutState = showChildren; indentArg = indent; thisArg = this; DrawComponent(true, indentOption, colWidth); //Swap buttons var parentMine = parent.mine; var parentTheirs = parent.theirs; if (parentMine && parentTheirs) { DrawMidButtons(mine, theirs, parentMine, parentTheirs, LeftButton, RightButton, LeftDeleteButton, RightDeleteButton); } else { GUILayout.Space(UniMergeConfig.DoubleMidWidth); } //Display theirs DrawComponent(false, indentOption, colWidth); if (showChildren != foldoutState) { InvalidateDrawCount(); //If foldout state changed and user was holding alt, set all child foldout states to this state if (Event.current.alt) { foreach (var property in properties) { property.SetFoldoutRecursively(showChildren); } } } window.EndRow(Same); } if (showChildren) { var tmp = new List <PropertyHelper>(properties); var newWidth = indent + Util.TabSize; var newIndent = GUILayout.Width(newWidth); foreach (var property in tmp) { property.Draw(newWidth, colWidth, newIndent); } } if (mySO != null && mySO.targetObject != null) { if (mySO.ApplyModifiedProperties()) { window.update = BubbleRefresh(); } } if (theirSO != null && theirSO.targetObject != null) { if (theirSO.ApplyModifiedProperties()) { window.update = BubbleRefresh(); } } }
public static IEnumerator <bool> UpdatePropertyList(List <PropertyHelper> properties, SerializedObject myObject, SerializedObject theirObject, GameObjectHelper gameObjectParent, ComponentHelper componentParent, PropertyHelper propertyParent, ObjectMerge objectMerge, SceneMerge sceneMerge, Helper parent, UniMergeWindow window, bool showHidden = false) { var myObjectIsNull = myObject == null; var theirObjectIsNull = theirObject == null; if (myObjectIsNull && theirObjectIsNull) { yield break; } SerializedProperty myIterator = null; if (!myObjectIsNull) { myIterator = myObject.GetIterator(); } SerializedProperty theirIterator = null; if (!theirObjectIsNull) { theirIterator = theirObject.GetIterator(); } if (theirIterator != null) { theirIterator.Reset(); } var isGameObject = (myObjectIsNull ? theirObject.targetObject : myObject.targetObject) is GameObject; var isTransform = (myObjectIsNull ? theirObject.targetObject : myObject.targetObject) is Transform; var tempShowHiddenDepth = -1; var tempShowHidden = false; var same = true; var mineHasNext = myIterator != null; var theirsHasNext = theirIterator != null; var lastDepth = 0; PropertyHelper lastHelper = null; var root = parent; var gameObjectRoot = gameObjectParent; var componentRoot = componentParent; var propertyRoot = propertyParent; var ignored = false; while (mineHasNext || theirsHasNext) { var _myIterator = myIterator; var _theirIterator = theirIterator; var iterator = _myIterator != null && mineHasNext ? _myIterator : _theirIterator; #if UNITY_4 || UNITY_5 || UNITY_5_3_OR_NEWER if (iterator.propertyType == SerializedPropertyType.Gradient) { tempShowHiddenDepth = iterator.depth; tempShowHidden = true; } else #endif if (iterator.depth == tempShowHiddenDepth) { tempShowHidden = false; tempShowHiddenDepth = -1; } if (mineHasNext && theirsHasNext) { if (myIterator.depth > theirIterator.depth) { //Catch up myIterator if (showHidden || tempShowHidden) { mineHasNext &= myIterator.Next(!ignored); } else { mineHasNext &= myIterator.NextVisible(!ignored); } } else if (theirIterator.depth > myIterator.depth && theirsHasNext) { // Catch up theirIterator if (showHidden || tempShowHidden) { theirsHasNext &= theirIterator.Next(!ignored); } else { theirsHasNext &= theirIterator.NextVisible(!ignored); } } else { if (showHidden || tempShowHidden) { mineHasNext &= myIterator.Next(!ignored); theirsHasNext &= theirIterator.Next(!ignored); } else { mineHasNext &= myIterator.NextVisible(!ignored); theirsHasNext &= theirIterator.NextVisible(!ignored); } } if (mineHasNext && theirsHasNext) { if (myIterator.depth > theirIterator.depth) // Missing elements in mine { _theirIterator = null; } if (theirIterator.depth > myIterator.depth) // Missing elements in theirs { _myIterator = null; } } } else { if (mineHasNext) { if (showHidden || tempShowHidden) { mineHasNext &= myIterator.Next(!ignored); } else { mineHasNext &= myIterator.NextVisible(!ignored); } } if (theirsHasNext) { if (showHidden || tempShowHidden) { theirsHasNext &= theirIterator.Next(!ignored); } else { theirsHasNext &= theirIterator.NextVisible(!ignored); } } } if (!mineHasNext && !theirsHasNext) { break; } if (!mineHasNext) { _myIterator = null; } if (!theirsHasNext) { _theirIterator = null; } // Get new iterator if one has become null // ReSharper disable once ConvertIfStatementToNullCoalescingExpression if (_myIterator == null) { iterator = _theirIterator; } else { iterator = _myIterator; } var path = iterator.propertyPath; var type = iterator.propertyType; ignored = path == "m_Script"; if (isGameObject) { ignored = type == SerializedPropertyType.ObjectReference || type == SerializedPropertyType.Generic; } else if (isTransform) { #if UNITY_4_5 || UNITY_4_5_0 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER ignored = type != SerializedPropertyType.Vector3 && type != SerializedPropertyType.Quaternion && type != SerializedPropertyType.Float; #elif !Unity3 ignored = type != SerializedPropertyType.Vector3 && type != (SerializedPropertyType)16 && type != SerializedPropertyType.Float; #else ignored = type != SerializedPropertyType.Vector3 && type != SerializedPropertyType.Float; #endif } if (ignored) { continue; } PropertyHelper ph = null; var count = properties.Count; // ReSharper disable once LoopVariableIsNeverChangedInsideLoop for (var i = 0; i < count; i++) { var property = properties[i]; if (property.propertyPath == path) { ph = property; break; } } var depth = iterator.depth; if (depth > lastDepth) { parent = lastHelper; propertyParent = lastHelper; } if (depth < lastDepth && parent != null) { parent = parent.parent; propertyParent = propertyParent.propertyParent; } if (depth > 0) { var children = propertyParent.children; if (children != null) { count = children.Count; for (var i = 0; i < count; i++) { var child = children[i]; if (child.propertyPath == path) { ph = child; break; } } } } SerializedProperty myIteratorCopy = null; if (_myIterator != null) { myIteratorCopy = _myIterator.Copy(); } SerializedProperty theirIteratorCopy = null; if (_theirIterator != null) { theirIteratorCopy = _theirIterator.Copy(); } if (ph == null) { if (depth == 0) { ph = new PropertyHelper(myIteratorCopy, theirIteratorCopy, path, type, gameObjectRoot, componentRoot, propertyRoot, root, window, objectMerge, sceneMerge); properties.Add(ph); } else { ph = new PropertyHelper(myIteratorCopy, theirIteratorCopy, path, type, gameObjectParent, componentParent, propertyParent, parent, window, objectMerge, sceneMerge); var children = propertyParent.children; if (children == null) { propertyParent.children = children = new List <PropertyHelper>(1); } children.Add(ph); } } else { ph.mine = myIteratorCopy; ph.theirs = theirIteratorCopy; } lastHelper = ph; lastDepth = depth; } for (var i = 0; i < properties.Count; i++) { var property = properties[i]; if (property.children == null) { property.CheckSame(); } else { var enumerator = DeepCheckSame(property); while (enumerator.MoveNext()) { yield return(false); } } if (!property.Same) { same = false; } } yield return(same); }