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); } }
public void AddNewComponent(ZComponent comp) { Type type = comp.GetType(); // Do NOT register ZApplication and its derived classes if (typeof(ZApplication).IsAssignableFrom(type)) return; allComponents.Add(comp); // Store the name in the name cache if (comp.HasName()) nameCache[comp.Name] = comp; // TODO: consider all ancestor types if (!typeMap.ContainsKey(type)) typeMap[type] = new HashSet<ZComponent>(); typeMap[type].Add(comp); }
public void RemoveComponent(ZComponent comp) { Type type = comp.GetType(); // Do NOT register ZApplication and its derived classes if (typeof(ZApplication).IsAssignableFrom(type)) return; allComponents.Remove(comp); //if (comp.HasName()) nameCache.Remove(comp.Name); // Remove the component from the nameMap - if necessary foreach (var item in nameCache.Where(kvp => kvp.Value == comp).ToList()) { nameCache.Remove(item.Key); } // TODO: consider all ancestor types if (typeMap.ContainsKey(type)) { typeMap[type].Remove(comp); if (typeMap[type].Count == 0) typeMap.Remove(type); } }
private void AddElementToTree(ZComponent component, TreeNodeCollection nodes) { // Add the element. TreeNode newNode = new TreeNode() { Tag = component }; newNode.Text = component.GetType().Name; if (component.HasName()) newNode.Text = newNode.Text + ": " + component.Name; else newNode.Text += " (No name)"; nodes.Add(newNode); // Add each child. //if (component.GetType() == typeof(Model)) foreach (var element in component.Children) AddElementToTree(element, newNode.Nodes); }
private static void ProcessNode(ZComponent parent, IList parent_list, TreeNodeCollection parent_nodes, XmlNode xmlNode) { if (xmlNode == null) return; //Console.WriteLine("Processing: {0}", xmlNode.Name); ZComponent comp = parent; IList list = null; if (xmlNode.Name == "ZApplication") { SetFields(comp, xmlNode); } else { // Check if this node is a List property of the parent FieldInfo fi = parent.GetType().GetField(xmlNode.Name, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance); //if (pi != null) Console.WriteLine(" Parent property found: {0}", pi.PropertyType.Name); if (parent is ZComponent && fi != null && typeof(IList).IsAssignableFrom(fi.FieldType)) { //Console.WriteLine("List found: {0}", xmlNode.Name); list = (IList) fi.GetValue(parent); } // Check if this node is a ZCode property of the parent else if (parent is ZComponent && fi != null && typeof(CodeLike).IsAssignableFrom(fi.FieldType)) { CodeLike code = (CodeLike) fi.GetValue(parent); // Activator.CreateInstance(fi.FieldType); code.Text = xmlNode.InnerText; //code.Owner = parent; Console.WriteLine("Code Text:\n{0}", code.Text); fi.SetValue(comp, code); //ZComponent.App.AddComponent(code); return; //no TreeNode should be created for this } else { comp = CreateComponent(xmlNode.Name, xmlNode, parent, parent_list); if (comp == null) { Console.WriteLine("SKIPPING subtree - Cannot find type: {0}", xmlNode.Name); return; } } } TreeNode treeNode = null; if (parent_nodes != null) { string displayName = xmlNode.Name; XmlAttribute attribute = xmlNode.Attributes["Name"]; if (attribute != null) displayName = displayName + " - " + attribute.Value; treeNode = new TreeNode(displayName); parent_nodes.Add(treeNode); // clear subtree if (treeNode != null) treeNode.Nodes.Clear(); } // recursively build SubTree foreach (XmlNode childNode in xmlNode.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element) { if (treeNode != null) ProcessNode(comp, list, treeNode.Nodes, childNode); else ProcessNode(comp, list, null, childNode); } } // construct ZNodeProperties object for the TreeNode and assign it to Tag property object target = (object) list ?? (object) comp; object parentObj = (object) parent_list ?? (object) parent; ZNodeProperties props = new ZNodeProperties(target, parentObj, xmlNode, treeNode); if (list == null) comp.Tag = props; if (_treeView != null) { treeNode.Tag = props; ZTreeView.HighlightTreeNode(treeNode, props); //props.XmlNodePropertyChanged += new XmlNodePropertyChangedEventHandler(_treeView.UpdateNodeText); } }
private static void SetFields(ZComponent comp, XmlNode xmlNode) { Type type = comp.GetType(); // Add attributes to the properties if (xmlNode.Attributes != null) { foreach (XmlAttribute attribute in xmlNode.Attributes) { string val = attribute.Value; FieldInfo fi = type.GetField(attribute.Name, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance); if (fi != null) { //Console.WriteLine(" Field found: {0}", attribute.Name); object obj = Deserialize(val, fi.FieldType); if (obj != null) fi.SetValue(comp, obj); /*else if (typeof(ZCode).IsAssignableFrom(fi.FieldType)) //CODE CANNOT BE STORED AS A PROPERTY { ZCode code = (ZCode)Activator.CreateInstance(fi.FieldType); code.Text = val; code.Owner = comp; //Console.WriteLine("Code Text:\n{0}", code.Text); fi.SetValue(comp, code); //ZComponent.App.AddComponent(code); }*/ else if (fi.FieldType.IsSubclassOf(typeof(ZComponent))) { _unresolved.Add(new Unresolved { comp = comp, prop = fi, value = val }); } else Console.WriteLine(" Unsupported field: {0}-{1}", attribute.Name, val); } else Console.WriteLine(" Field not found: {0}-{1}", attribute.Name, val); //properties.Add(new CustomProperty(attribute.Name, attribute.Value, typeof(string), false, true)); } } }
private int ProcessNode(ZComponent parent, IList parent_list, int next_index, TreeNodeCollection parent_nodes, XmlNode xmlNode) { //if (xmlNode == null) return; //Console.WriteLine("Processing: {0}", xmlNode.Name); ZComponent comp = parent; IList list = null; if (xmlNode.Name == "ZApplication") { //SetFields(comp, xmlNode); } else { // Check if this node is a List property of the parent FieldInfo fi = CodeGenerator.GetField(parent.GetType(), xmlNode.Name); //if (pi != null) Console.WriteLine(" Parent property found: {0}", pi.PropertyType.Name); if (fi != null && typeof(IList).IsAssignableFrom(fi.FieldType)) { //Console.WriteLine("List found: {0}", xmlNode.Name); list = (IList) fi.GetValue(parent); } // Check if this node is an event of the parent else if (fi != null && typeof(Delegate).IsAssignableFrom(fi.FieldType)) { return next_index; //no TreeNode was created for this event } // Check if this node is a ZCode property of the parent else if (fi != null && typeof(CodeLike).IsAssignableFrom(fi.FieldType)) { return next_index; //no TreeNode was created for this CodeLike component } else { // Find the component in the list or among the children comp = null; IList findList = (IList) parent.Children; if (parent_list != null) findList = parent_list; // parent_list has the priority for (int index = next_index; index < findList.Count; index++) { ZComponent candidate = findList[index] as ZComponent; if (IsCompatibleType(candidate, xmlNode)) { comp = candidate; next_index = index + 1; break; } } if (comp == null) { Console.WriteLine("SKIPPING subtree - Cannot find matching component: {0}", xmlNode.Name); return next_index; } } } TreeNode treeNode = null; if (parent_nodes != null) { string displayName = xmlNode.Name; XmlAttribute attribute = xmlNode.Attributes["Name"]; if (attribute != null) displayName = displayName + " - " + attribute.Value; treeNode = new TreeNode(displayName); parent_nodes.Add(treeNode); // clear subtree if (treeNode != null) treeNode.Nodes.Clear(); } // recursively build SubTree int i = 0; foreach (XmlNode childNode in xmlNode.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element) { i = ProcessNode(comp, list, i, treeNode.Nodes, childNode); } } // construct ZNodeProperties object for the TreeNode and assign it to Tag property object target = (object) list ?? (object) comp; object parentObj = (object) parent_list ?? (object) parent; ZNodeProperties props = new ZNodeProperties(target, parentObj, xmlNode, treeNode); if (list == null) comp.Tag = props; if (treeView != null) { treeNode.Tag = props; ZTreeView.HighlightTreeNode(treeNode, props); //props.XmlNodePropertyChanged += new XmlNodePropertyChangedEventHandler(treeView.UpdateNodeText); } return next_index; }
public bool IsCompatibleType(ZComponent comp, XmlNode xmlNode) { Type type = comp.GetType(); if (type.Name == xmlNode.Name) return true; if (xmlNode.Name == "Model" || xmlNode.Name == "GameObject") { if (typeof(Model).IsAssignableFrom(type)) return true; } return false; }