public static void Restore(ZComponent newObj, ZComponent oldObj) { if (newObj == null || oldObj == null) return; //Console.WriteLine("Restore: {0}({1}) -> {2}({3})", oldObj.GetType().Name, oldObj.Name ?? "", newObj.GetType().Name, newObj.Name ?? ""); MemberwiseCopy(newObj, newObj.GetType(), oldObj, oldObj.GetType()); // A reference to oldObj should be updated to newObj in its Children foreach (ZComponent child in newObj.Children) { if (child.Owner == oldObj) child.ReplaceOwner(newObj); } // If it is NOT a ZApplication if (typeof(ZApplication).IsAssignableFrom(newObj.GetType()) == false) { ZComponent.App.RemoveComponent(oldObj); // remove the old component //ZComponent.App.AddNewComponent(newObj); // add the new component // We should always set the Owner <= old Owner has been copied to newObj if (newObj.OwnerList != null) // replace old object in OwnerList { //newObj.OwnerList = oldObj.OwnerList; int idx = newObj.OwnerList.IndexOf(oldObj); if (idx != -1) newObj.OwnerList[idx] = newObj; } else if (newObj.Owner != null) // replace old object among Owner's Children { int idx = newObj.Owner.Children.IndexOf(oldObj); if (idx != -1) newObj.Owner.Children[idx] = newObj; } oldObj.ReplaceOwner(null); if (typeof(Model).IsAssignableFrom(newObj.GetType())) { ZComponent.App.RemoveModel(oldObj as Model); Model newMod = newObj as Model; // Find named reference in App (only necessary for GameObjects) if (newMod != null && newMod.Prototype == false && newMod.HasName()) { FieldInfo fi = ZComponent.App.GetType().GetField(newMod.Name, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null && fi.FieldType == newObj.GetType()) { //Console.WriteLine("Setting named reference {0} / {1}", fi.Name, fi.FieldType.Name); fi.SetValue(ZComponent.App, newObj); } } // Clear the static CustomGame reference 'App' in the old model classes // It is enough to do this for the prototypes (there is one prototype for each class) // If we don't null this, the old application will never be finalized if (newMod.Prototype) { FieldInfo fi = oldObj.GetType().GetField("App", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (fi != null) { //Console.WriteLine("Setting named reference {0} / {1}", fi.Name, fi.FieldType.Name); fi.SetValue(oldObj, null); } } } } // Correct the Treeview tags ZNodeProperties props = newObj.Tag as ZNodeProperties; if (props != null) { props.Component = newObj; TreeNode treeNode = props.treeNode; if (treeNode != null) foreach (TreeNode childNode in treeNode.Nodes) { ZNodeProperties props1 = childNode.Tag as ZNodeProperties; // Clear the reference to oldObj in the ZNodeProperties of all children / member lists if (props1 != null && props1.Parent == oldObj) { props1.Parent = newObj; } /*foreach (TreeNode grandchildNode in childNode.Nodes) { ZNodeProperties props2 = grandchildNode.Tag as ZNodeProperties; if (props2 != null && props2.parent_component == oldObj) { props2.parent_component = newObj; // oldObj can also be the Owner of its grandchildren (in various member lists) // this reference must be updated to newObj ZComponent grandchild = props2.component as ZComponent; if (grandchild != null && grandchild.Owner == oldObj) grandchild.Owner = newObj; } }*/ } } // oldObj can also be the Owner of its grandchildren (in various member lists) // the Owner reference must be updated to newObj in all components foreach(ZComponent comp in ZComponent.App.GetAllComponents()) if (comp.Owner == oldObj) comp.ReplaceOwner(newObj); // oldObj can also be the Owner of ZEvent instances // update the Owner reference to newObj foreach (ZEvent ev in ZComponent.App.FindEvents(oldObj)) ev.Owner = newObj; // If it is a ZApplication if (typeof(ZApplication).IsAssignableFrom(newObj.GetType())) { // Check named references in CustomGame foreach(FieldInfo fi in newObj.GetType().GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { // If the named reference is null, then try to find the component // This is necessary for all newly-added or renamed components if (fi.GetValue(newObj) == null) { ZComponent comp = ZComponent.App.Find(fi.Name); if (comp != null && fi.FieldType == comp.GetType()) { Console.WriteLine("Setting new named reference {0} / {1}", fi.Name, fi.FieldType.Name); fi.SetValue(newObj, comp); } } } } // If the oldObj was selected in the editor, then we have to replace it with newObj if (editor.SelectedComponent == oldObj) { editor.SelectedComponent = newObj; //Console.WriteLine("SelectedComponent changed to {0}", newObj.GetType().AssemblyQualifiedName); } }