using UnityEngine; using System.Collections.Generic; namespace GitMerge { /// /// Dictionaries that categorize the scene's objects into our objects, their objects, and temporary /// copies of their objects that have been instantiated while merging. /// public static class ObjectDictionaries { //This dict holds all of "our" objects //Needed for Reference handling // private static Dictionary ourObjects = new Dictionary(); //This dict maps our instances of their objects //Whenever we instantiate a copy of "their" new object, they're both added here private static Dictionary ourInstances = new Dictionary(); //This dict holds all of "their" GameObjects //Needed for scene cleaning after merge // private static Dictionary theirObjects = new Dictionary(); //This dict holds all GameObjects that might or might not exist, //depending on the current merge state. The referenced objects are the versions that will definitely exist throughout the merge. //Also maps the MergeActions responsible for their existence to them. private static Dictionary schroedingersObjects = new Dictionary(); public static void SetAsOurObjects(List objects) { foreach(var obj in objects) { SetAsOurObject(obj); } } public static void SetAsTheirObjects(List objects) { foreach(var obj in objects) { SetAsTheirs(obj, false); } } public static void SetAsOurObject(GameObject go) { AddOurObject(go); foreach(var c in go.GetComponents()) { AddOurObject(c); } } public static void SetAsOurObject(Component c) { AddOurObject(c); } private static void AddOurObject(Object o) { if(o == null) return; ourObjects.Add(ObjectIDFinder.GetIdentifierFor(o), o); } public static void RemoveOurObject(GameObject go) { foreach(var c in go.GetComponents()) { RemoveOurSingleObject(c); } RemoveOurSingleObject(go); } public static void RemoveOurObject(Component c) { RemoveOurSingleObject(c); } private static void RemoveOurSingleObject(Object o) { if(o == null) return; ourObjects.Remove(ObjectIDFinder.GetIdentifierFor(o)); } public static Object GetOurObject(int id) { Object result = null; ourObjects.TryGetValue(id, out result); return result; } /// /// Returns: /// * the given object if it is "ours" /// * "our" counterpart of obj if it is "theirs" /// * null if the object is deleted for some reason /// The returned object can be an instance of "their" object temporarily added for the merge /// /// the original object /// the counterpart of the object in "our" version public static Object GetOurCounterpartFor(Object obj) { var result = obj; if(IsTheirs(obj)) { result = GetOurObject(ObjectIDFinder.GetIdentifierFor(obj)); if(!result) { result = GetOurInstanceOfCopy(obj); } } return result; } public static void Clear() { ourObjects.Clear(); theirObjects.Clear(); ourInstances.Clear(); schroedingersObjects.Clear(); } /// /// Mark o as an instance of theirs /// public static void SetAsCopy(GameObject o, GameObject theirs) { ourInstances.Add(theirs, o); var instanceComponents = o.GetComponents(); var theirComponents = theirs.GetComponents(); for(int i = 0; i < instanceComponents.Length; ++i) { SetAsCopy(instanceComponents[i], theirComponents[i]); } } public static void SetAsCopy(Component c, Component theirs) { if(c == null) return; ourInstances.Add(theirs, c); } public static void RemoveCopyOf(GameObject theirs) { ourInstances.Remove(theirs); foreach(var c in theirs.GetComponents()) { if(c != null) { ourInstances.Remove(c); } } } public static void RemoveCopyOf(Component theirs) { ourInstances.Remove(theirs); } /// /// Returns: /// * the given object if it is "ours" /// * "our" instance of obj if it is "theirs" /// * null if there is no such instance /// /// the original object /// the instance of the original object public static Object GetOurInstanceOfCopy(Object obj) { var result = obj; if(IsTheirs(obj)) { ourInstances.TryGetValue(obj, out result); } return result; } private static bool IsTheirs(Object obj) { var go = obj as GameObject; if(go) { return theirObjects.ContainsKey(go); } var c = obj as Component; if(c) { return theirObjects.ContainsKey(c.gameObject); } return false; } public static void SetAsTheirs(GameObject go, bool active) { if(!theirObjects.ContainsKey(go)) { theirObjects.Add(go, go.activeSelf); } go.SetActiveForMerging(false); } /// /// Copy an object that has been disabled and hidden for merging into the scene, /// enable and unhide the copy. /// /// The original GameObject. /// The copy GameObject. public static GameObject InstantiateFromMerging(GameObject go) { var copy = GameObject.Instantiate(go) as GameObject; //Destroy children foreach(Transform t in copy.GetComponent()) { Object.DestroyImmediate(t.gameObject); } bool wasActive; if(!theirObjects.TryGetValue(go, out wasActive)) { wasActive = go.activeSelf; } //Apply some special properties of the GameObject copy.SetActive(wasActive); copy.hideFlags = HideFlags.None; copy.name = go.name; copy.GetComponent().parent = GetOurCounterpartFor(go.GetComponent().parent) as Transform; return copy; } public static void DestroyTheirObjects() { foreach(var obj in theirObjects.Keys) { Object.DestroyImmediate(obj); } theirObjects.Clear(); } public static void AddToSchroedingersObjects(GameObject go, MergeActionExistence mergeAction) { schroedingersObjects.Add(go, mergeAction); } public static void EnsureExistence(GameObject go) { schroedingersObjects[go].EnsureExistence(); } } }