// ---------------------------------------------------------- public void Minimize(Options aOptions, Def aDef) { // reader _reader = new XmlDocument(); _reader.Load(aOptions.inFile); // writter with write settings var writterSettings = new XmlWriterSettings(); if (aOptions.prettyPrint) { writterSettings.Indent = true; writterSettings.IndentChars = " "; } _writer = XmlWriter.Create(aOptions.outFile, writterSettings); _writer.WriteStartDocument(); ProcessElement(_reader.DocumentElement, aDef); _writer.WriteEndDocument(); _writer.Close(); // print warnings foreach(string warning in _warnings) { Console.WriteLine(warning); } }
// ---------------------------------------------------------- private void PrintMissingElementDef(string aName, Def aDef) { StringBuilder stringBuilder = new StringBuilder(); while(aDef != null) { stringBuilder.Insert(0, aDef.name + "->"); aDef = aDef.parent; } stringBuilder.Append(aName); stringBuilder.Insert(0, "WARNING: missing new name for element "); _warnings.Add(stringBuilder.ToString()); }
// ---------------------------------------------------------- private void ReadSpriterDefs(XmlElement aElement, Def aDef, Dictionary<string, Item> aItems) { aDef.name = aElement.Attributes["name"].Value; if (!aElement.HasAttribute("item")) { Console.WriteLine("Missing item attribute for element " + aDef.name); return; } if (!aItems.ContainsKey(aElement.Attributes["item"].Value)) { Console.WriteLine("Missing item definition for item " + aElement.Attributes["item"].Value); return; } aDef.item = aItems[aElement.Attributes["item"].Value]; var children = aElement.ChildNodes; foreach (XmlNode node in children) { if (node.NodeType == XmlNodeType.Element) { XmlElement element = node as XmlElement; if (element.Name == "element") { // new def and set parent var def = new Def(); def.parent = aDef; ReadSpriterDefs(element, def, aItems); // add this element to current table aDef.childElements.Add(def.name, def); } else if (element.Name == "attribute") { // add attribute to current table var name = element.Attributes["name"].Value; if (!element.HasAttribute("item")) { Console.WriteLine("Missing item attribute for attribute " + name); return; } if (!aItems.ContainsKey(element.Attributes["item"].Value)) { Console.WriteLine("Missing item definition for item " + element.Attributes["item"].Value); return; } aDef.attributes.Add(name, aItems[element.Attributes["item"].Value]) ; } else { Console.WriteLine("ERROR: unknown element '" + element.Name + "'"); } } } }
// ---------------------------------------------------------- public void Convert(Options aOptions, Def aRootDef) { if (aOptions.smallOffset) { _bigOffset = false; _offsetSize = 2; } // reader XmlDocument reader = new XmlDocument(); reader.Load(aOptions.inFile); using (FileStream fs = new FileStream(aOptions.outFile, FileMode.Create)) { using (BinaryWriter writer = new BinaryWriter(fs)) { // write 0 for bigOffset and 1 for smallOffset writer.Write((byte)(_bigOffset ? 0 : 1)); // write all elements recursively ProcessElement(1, reader.DocumentElement, aRootDef, writer); } } }
// ---------------------------------------------------------- private void ProcessElement(XmlElement aElement, Def aDef) { bool isElementDef = aDef != null && (aElement.Name == aDef.name); // write element var newName = isElementDef ? aDef.item.minName : aElement.Name; _writer.WriteStartElement(newName); // special case for very first element - add attribute to say this file is minimized if (aElement.Name == "spriter_data") { _writer.WriteAttributeString("min", "true"); } // write all attributes foreach(XmlAttribute attribute in aElement.Attributes) { if (aDef != null && aDef.attributes.ContainsKey(attribute.Name)) { _writer.WriteAttributeString(aDef.attributes[attribute.Name].minName, attribute.Value); } else { PrintMissingAttributeDef(attribute.Name, aElement.Name); _writer.WriteAttributeString(attribute.Name, attribute.Value); } } // next elements foreach(XmlNode node in aElement.ChildNodes) { if (node.NodeType == XmlNodeType.Element) { XmlElement element = node as XmlElement; if (aDef != null && aDef.childElements.ContainsKey(element.Name)) { ProcessElement(element, aDef.childElements[element.Name]); } else { PrintMissingElementDef(element.Name, aDef); ProcessElement(element, null); } } } // end element _writer.WriteEndElement(); }
// ---------------------------------------------------------- private void ProcessElement(int aPosition, XmlElement aElement, Def aDef, BinaryWriter aWriter) { bool isElementDef = aDef != null && (aElement.Name == aDef.name); // save initial position int initialPosition = aPosition; // write element byte elementID = (byte) (aDef.item.binaryCode & 0xFF); aWriter.Write(elementID); // get subelements and count them var subElements = aElement.ChildNodes; byte subElementsCount = (byte)CountSubElements(subElements); aWriter.Write(subElementsCount); int subElsPosition = (int) aWriter.BaseStream.Position; int subElsPositionCurrent = subElsPosition; aWriter.Seek(subElementsCount * _offsetSize, SeekOrigin.Current); // write number of attributes aWriter.Write((byte)aElement.Attributes.Count); // write all attributes foreach (XmlAttribute attribute in aElement.Attributes) { if (aDef != null && aDef.attributes.ContainsKey(attribute.Name)) { var attribItem = aDef.attributes[attribute.Name]; // write attrib ID aWriter.Write((byte) attribItem.binaryCode); // write attrib value WriteAttribute(attribute.Value, attribItem.type, aWriter); } else { Console.WriteLine("Attribute '" + attribute.Name + "' item definition is missing"); } } // write sub elements foreach (XmlNode node in aElement.ChildNodes) { if (node.NodeType == XmlNodeType.Element) { XmlElement element = node as XmlElement; int currentPosition = (int) aWriter.BaseStream.Position; int offset = (currentPosition - subElsPosition); if (!_bigOffset && offset >= 65536) { Console.WriteLine("Offset to element is bigger than 65536"); } aWriter.Seek(subElsPositionCurrent, SeekOrigin.Begin); if (_bigOffset) { aWriter.Write(offset); } else { aWriter.Write((ushort) offset); } subElsPositionCurrent += _offsetSize; aWriter.Seek(currentPosition, SeekOrigin.Begin); if (aDef != null && aDef.childElements.ContainsKey(element.Name)) { ProcessElement(currentPosition, element, aDef.childElements[element.Name], aWriter); } else { Console.WriteLine("Child elements for " + aElement.Name + " do not contain " + element.Name); } } } }
// ---------------------------------------------------------- private void ProcessElement(int aPosition, XmlElement aElement, Def aDef, BinaryWriter aWriter) { bool isElementDef = aDef != null && (aElement.Name == aDef.name); // save initial position int initialPosition = aPosition; // write element byte elementID = (byte)(aDef.item.binaryCode & 0xFF); aWriter.Write(elementID); // get subelements and count them var subElements = aElement.ChildNodes; byte subElementsCount = (byte)CountSubElements(subElements); aWriter.Write(subElementsCount); int subElsPosition = (int)aWriter.BaseStream.Position; int subElsPositionCurrent = subElsPosition; aWriter.Seek(subElementsCount * _offsetSize, SeekOrigin.Current); // write number of attributes aWriter.Write((byte)aElement.Attributes.Count); // write all attributes foreach (XmlAttribute attribute in aElement.Attributes) { if (aDef != null && aDef.attributes.ContainsKey(attribute.Name)) { var attribItem = aDef.attributes[attribute.Name]; // write attrib ID aWriter.Write((byte)attribItem.binaryCode); // write attrib value WriteAttribute(attribute.Value, attribItem.type, aWriter); } else { Console.WriteLine("Attribute '" + attribute.Name + "' item definition is missing"); } } // write sub elements foreach (XmlNode node in aElement.ChildNodes) { if (node.NodeType == XmlNodeType.Element) { XmlElement element = node as XmlElement; int currentPosition = (int)aWriter.BaseStream.Position; int offset = (currentPosition - subElsPosition); if (!_bigOffset && offset >= 65536) { Console.WriteLine("Offset to element is bigger than 65536"); } aWriter.Seek(subElsPositionCurrent, SeekOrigin.Begin); if (_bigOffset) { aWriter.Write(offset); } else { aWriter.Write((ushort)offset); } subElsPositionCurrent += _offsetSize; aWriter.Seek(currentPosition, SeekOrigin.Begin); if (aDef != null && aDef.childElements.ContainsKey(element.Name)) { ProcessElement(currentPosition, element, aDef.childElements[element.Name], aWriter); } else { Console.WriteLine("Child elements for " + aElement.Name + " do not contain " + element.Name); } } } }