/// <summary> /// Produce an entity with given name. /// </summary> /// <param name="entityName">Name to construct the entity around</param> /// <param name="customizationData">Data to customize the entity with.</param> /// <returns>Entity produced based on a definition.</returns> public static Entity ProduceEntity(String entityName, XmlNode customizationData = null) { // First, check to make sure we have a definition for that entity. if (m_Entities.ContainsKey(entityName)) { // Extract the data (and possibly zip it together with the customization data. Entity ent = new Entity(); EntityDefinition entDef = EntityDefinition.ZipTogether(m_Entities[entityName], customizationData); // Now, for each property foreach (XmlNode node in entDef.m_Properties) { // Make sure it has a specified type if (node.Attributes["type"] != null) { // And get that type Type t = Type.GetType(node.Attributes["type"].Value); if (t != null) { // Then, construct a Property<T> based on the type above. Type propType = typeof(Property <>); propType = propType.MakeGenericType(t); // And invoke the initializer for that (with default params). IProperty prop = (IProperty)System.Activator.CreateInstance(propType); // Pass it the XML node to parse, prop.Parse(node.FirstChild); // And add it to the entity. ent.AddIProperty(node.Attributes["name"].Value, prop); } } } // Now, Components foreach (XmlNode node in entDef.m_Components) { // If it has a type, Add that to the entity, and then making it parse first child. if (node.Attributes["type"] != null) { String compType = node.Attributes["type"].Value; String compName = (node.Attributes["name"] == null) ? "" : node.Attributes["name"].Value; Component c = ent.AddComponent(compType, compName); if (c != null) { c.Parse(node); } } } return(ent); } return(null); }
/// <summary> /// Clone this entity definition. /// </summary> /// <returns>Cloned entity definition.</returns> public object Clone() { EntityDefinition ent = new EntityDefinition(this.Name); foreach (XmlNode node in m_Components) { ent.m_Components.Add(node.Clone()); } foreach (XmlNode node in m_Properties) { ent.m_Properties.Add(node.Clone()); } return(ent); }
/// <summary> /// Parse XML and produce an EntityDefinition from it. /// </summary> /// <param name="data">Data for the entity definition.</param> /// <returns>Constructed entity definition.</returns> public static EntityDefinition ParseEntity(XmlNode data) { EntityDefinition ent; // If the data says it's based on another unit, and the unit it's supposedly based off of exists, if (data.Attributes["base"] != null && m_Entities.ContainsKey(data.Attributes["base"].Value)) { // Zip that unit together with the data we were passed. ent = EntityDefinition.ZipTogether(m_Entities[data.Attributes["base"].Value], data); } else { // Otherwise, we're working from scratch ent = new EntityDefinition(data.Attributes["name"].Value); // For each of the children, determine if it's a property or a component, // and add the child node to the proper list. foreach (XmlNode node in data.ChildNodes) { switch (node.Name.ToLower()) { case "property": ent.m_Properties.Add(node); break; case "component": ent.m_Components.Add(node); break; default: break; } } } // And return the parsed entity definition return(ent); }
/// <summary> /// Customize a specific entity definition with some data. /// </summary> /// <param name="ent">Base entity to work with.</param> /// <param name="customizationData">Data to customize.</param> /// <returns>A customized entity.</returns> public static EntityDefinition ZipTogether(EntityDefinition ent, XmlNode customizationData) { // Clone the entity so we don't accidentaly modify the original. EntityDefinition newEnt = (EntityDefinition)ent.Clone(); // If there's no customization data, we're done here, so just return. if (customizationData != null) { // Otherwise, modify first the entities name if (customizationData.Attributes["name"] != null) { newEnt.Name = customizationData.Attributes["name"].Value; } else { newEnt.Name = "Nameless " + newEnt.Name + new Random().Next(); // This will make sure (to reasonalbe accuracy) entity names are unique. } // For each point of customization foreach (XmlNode comp in customizationData) { // Check it's mod type switch (comp.Attributes["mod"].Value.ToLower()) { case "add": // And check if it's component or property. if (comp.Name.ToLower() == "component") { XmlNode toAdd = comp.Clone(); toAdd.Attributes.Remove(toAdd.Attributes["mod"]); newEnt.m_Components.Add(toAdd); } else if (comp.Name.ToLower() == "property") { XmlNode toAdd = comp.Clone(); toAdd.Attributes.Remove(toAdd.Attributes["mod"]); newEnt.m_Properties.Add(toAdd); } break; case "remove": String name = comp.Attributes["name"].Value; if (comp.Name.ToLower() == "component") { newEnt.m_Components.RemoveAll((node) => node.Attributes["name"].Value == name); } else if (comp.Name.ToLower() == "property") { newEnt.m_Properties.RemoveAll((node) => node.Attributes["name"].Value == name); } break; case "modify": if (comp.Attributes["name"] != null) { name = comp.Attributes["name"].Value; if (comp.Name.ToLower() == "component") { // If we're modifying a component or property, we zip together the inner XML's of each of these nodes. foreach (XmlNode node in newEnt.m_Components) { if (node.Attributes["name"] != null && node.Attributes["name"].Value == name) { foreach (XmlAttribute attrib in comp.Attributes) { if (node.Attributes[attrib.Name] == null) { if (attrib.Name != "mod") { node.Attributes.Append(node.OwnerDocument.CreateAttribute(attrib.Name)); node.Attributes[attrib.Name].Value = attrib.Value; } } } node.InnerXml = node.ZipTogether(comp).InnerXml; } } } else if (comp.Name.ToLower() == "property") { foreach (XmlNode node in newEnt.m_Properties) { if (node.Attributes["name"] != null && node.Attributes["name"].Value == name) { node.InnerXml = node.ZipTogether(comp).InnerXml; } } } } break; } } } return(newEnt); }