Exemplo n.º 1
0
        private void Cancel_Click(object sender, EventArgs e)
        {
            try
            {
                if (PrevTBox.Text != "")
                {
                    ((WzIntProperty)fh.Data["prev"]).Value = int.Parse(PrevTBox.Text);
                    fh.Data["prev"].ParentImage.Changed    = true;
                }
                if (NextTBox.Text != "")
                {
                    ((WzIntProperty)fh.Data["next"]).Value = int.Parse(NextTBox.Text);
                    fh.Data["next"].ParentImage.Changed    = true;
                }

                if (ForceTBox.Text != "")
                {
                    if (ForceLbl.Text == "None")
                    {
                        WzIntProperty forceProperty = new WzIntProperty("force", int.Parse(ForceTBox.Text));
                        fh.Data.AddProperty(forceProperty);
                        fh.Data.ParentImage.Changed = true;
                    }
                    else
                    {
                        ((WzIntProperty)fh.Data["force"]).Value = int.Parse(ForceTBox.Text);
                        fh.Data["force"].ParentImage.Changed    = true;
                    }
                }
                this.Close();
            }
            catch { MessageBox.Show(HaRepacker.Properties.Resources.FHMapperInvalidInput, HaRepacker.Properties.Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning); }
        }
        public ObjectInfo Add(Bitmap bmp, string name)
        {
            if (!IsNameValid(name))
            {
                throw new NameAlreadyUsedException();
            }

            Point origin = new Point(bmp.Width / 2, bmp.Height / 2);

            WzSubProperty    prop       = new WzSubProperty();
            WzCanvasProperty canvasProp = new WzCanvasProperty();

            canvasProp.PngProperty = new WzPngProperty();
            canvasProp.PngProperty.SetImage(bmp);
            canvasProp["origin"] = new WzVectorProperty("", new WzIntProperty("X", origin.X), new WzIntProperty("Y", origin.Y));
            canvasProp["z"]      = new WzIntProperty("", 0);
            prop["0"]            = canvasProp;

            ObjectInfo oi = new ObjectInfo(bmp, origin, oS, Program.APP_NAME, l1, name, prop);

            newObjects.Add(oi);
            newObjectsData.Add(name, SaveImageToBytes(bmp));
            SerializeObjects();
            l1prop[name] = prop;

            return(oi);
        }
Exemplo n.º 3
0
        private void CreateWzProp(IPropertyContainer parent, WzPropertyType propType, string propName, object value)
        {
            WzImageProperty addedProp;

            switch (propType)
            {
            case WzPropertyType.Float:
                addedProp = new WzFloatProperty(propName);
                break;

            case WzPropertyType.Canvas:
                addedProp = new WzCanvasProperty(propName);
                ((WzCanvasProperty)addedProp).PngProperty = new WzPngProperty();
                break;

            case WzPropertyType.Int:
                addedProp = new WzIntProperty(propName);
                break;

            case WzPropertyType.Double:
                addedProp = new WzDoubleProperty(propName);
                break;

            /*case WzPropertyType.Sound:
             *  addedProp = new WzSoundProperty(propName);
             *  break;*/
            case WzPropertyType.String:
                addedProp = new WzStringProperty(propName);
                break;

            case WzPropertyType.Short:
                addedProp = new WzShortProperty(propName);
                break;

            case WzPropertyType.Vector:
                addedProp = new WzVectorProperty(propName);
                ((WzVectorProperty)addedProp).X = new WzIntProperty("X");
                ((WzVectorProperty)addedProp).Y = new WzIntProperty("Y");
                break;

            case WzPropertyType.Lua:     // probably dont allow the user to create custom Lua for now..
            {
                addedProp = new WzLuaProperty(propName, new byte[] { });
                break;
            }

            default:
                throw new NotSupportedException("Not supported type");
            }
            addedProp.SetValue(value);
            parent.AddProperty(addedProp);
        }
        /// <summary>
        /// Update the checkboxes upon selection of a 'fieldLimit' WzIntProperty
        /// </summary>
        public void UpdateFieldLimitCheckboxes(WzIntProperty propertyValue)
        {
            initializingListViewForFieldLimit = true;

            // Fill checkboxes
            //int maxFieldLimitType = FieldLimitTypeExtension.GetMaxFieldLimitType();
            foreach (ListViewItem item in listView_fieldLimitType.Items)
            {
                item.Checked = FieldLimitTypeExtension.Check((int)item.Tag, propertyValue.GetLong());
            }
            initializingListViewForFieldLimit = false;
            ListView_fieldLimitType_ItemChecked(listView_fieldLimitType, null);
        }
Exemplo n.º 5
0
        public void TestWzFileWithImageAndPropertySerializes()
        {
            var intProp = new WzIntProperty("int1", 100);
            var img     = new WzImage("test.img");
            var file    = new WzFile(1, WzMapleVersionType.Classic);

            img.AddProperty(intProp);
            file.WzDirectory.WzImages.Add(img);

            using var ms = new MemoryStream();
            file.Serialize(ms);
            var contents        = Encoding.ASCII.GetString(ms.ToArray());
            var deserialized    = WzObject.DeserializeFile(contents);
            var deserializedImg = deserialized.WzDirectory.GetImageByName(img.Name);

            Assert.IsNotNull(deserializedImg);
            Assert.AreEqual(intProp.Value, deserializedImg[intProp.Name].GetInt());
        }
Exemplo n.º 6
0
        /// <summary>
        /// Easy access to editing image 'delay' properties
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_delayEdit_Click(object sender, RoutedEventArgs e)
        {
            if (isLoading)
            {
                return;
            }

            if (int.TryParse(textbox_delay.Text, out int newdelay))
            {
                WzIntProperty intProperty = _ParentWzCanvasProperty[WzCanvasProperty.AnimationDelayPropertyName] as WzIntProperty;
                if (intProperty != null)
                {
                    intProperty.Value = newdelay;

                    // Update local UI
                    Delay = newdelay;

                    button_delayEdit.IsEnabled = false;
                }
            }
        }
Exemplo n.º 7
0
        internal WzImageProperty ParsePropertyFromXMLElement(XmlElement element)
        {
            switch (element.Name)
            {
            case "imgdir":
                WzSubProperty sub = new WzSubProperty(element.GetAttribute("name"));
                foreach (XmlElement subelement in element)
                {
                    sub.AddProperty(ParsePropertyFromXMLElement(subelement));
                }
                return(sub);

            case "canvas":
                WzCanvasProperty canvas = new WzCanvasProperty(element.GetAttribute("name"));
                if (!element.HasAttribute("basedata"))
                {
                    throw new NoBase64DataException("no base64 data in canvas element with name " + canvas.Name);
                }
                canvas.PngProperty = new WzPngProperty();
                MemoryStream pngstream = new MemoryStream(Convert.FromBase64String(element.GetAttribute("basedata")));
                canvas.PngProperty.SetPNG((Bitmap)Image.FromStream(pngstream, true, true));
                foreach (XmlElement subelement in element)
                {
                    canvas.AddProperty(ParsePropertyFromXMLElement(subelement));
                }
                return(canvas);

            case "int":
                WzIntProperty compressedInt = new WzIntProperty(element.GetAttribute("name"), int.Parse(element.GetAttribute("value"), formattingInfo));
                return(compressedInt);

            case "double":
                WzDoubleProperty doubleProp = new WzDoubleProperty(element.GetAttribute("name"), double.Parse(element.GetAttribute("value"), formattingInfo));
                return(doubleProp);

            case "null":
                WzNullProperty nullProp = new WzNullProperty(element.GetAttribute("name"));
                return(nullProp);

            case "sound":
                if (!element.HasAttribute("basedata") || !element.HasAttribute("basehead") || !element.HasAttribute("length"))
                {
                    throw new NoBase64DataException("no base64 data in sound element with name " + element.GetAttribute("name"));
                }
                WzSoundProperty sound = new WzSoundProperty(element.GetAttribute("name"),
                                                            int.Parse(element.GetAttribute("length")),
                                                            Convert.FromBase64String(element.GetAttribute("basehead")),
                                                            Convert.FromBase64String(element.GetAttribute("basedata")));
                return(sound);

            case "string":
                WzStringProperty stringProp = new WzStringProperty(element.GetAttribute("name"), element.GetAttribute("value"));
                return(stringProp);

            case "short":
                WzShortProperty shortProp = new WzShortProperty(element.GetAttribute("name"), short.Parse(element.GetAttribute("value"), formattingInfo));
                return(shortProp);

            case "long":
                WzLongProperty longProp = new WzLongProperty(element.GetAttribute("name"), long.Parse(element.GetAttribute("value"), formattingInfo));
                return(longProp);

            case "uol":
                WzUOLProperty uol = new WzUOLProperty(element.GetAttribute("name"), element.GetAttribute("value"));
                return(uol);

            case "vector":
                WzVectorProperty vector = new WzVectorProperty(element.GetAttribute("name"), new WzIntProperty("x", Convert.ToInt32(element.GetAttribute("x"))), new WzIntProperty("y", Convert.ToInt32(element.GetAttribute("y"))));
                return(vector);

            case "float":
                WzFloatProperty floatProp = new WzFloatProperty(element.GetAttribute("name"), float.Parse(element.GetAttribute("value"), formattingInfo));
                return(floatProp);

            case "extended":
                WzConvexProperty convex = new WzConvexProperty(element.GetAttribute("name"));
                foreach (XmlElement subelement in element)
                {
                    convex.AddProperty(ParsePropertyFromXMLElement(subelement));
                }
                return(convex);
            }
            throw new InvalidDataException("unknown XML prop " + element.Name);
        }
Exemplo n.º 8
0
 protected void WritePropertyToXML(TextWriter tw, string depth, WzImageProperty prop)
 {
     if (prop is WzCanvasProperty)
     {
         WzCanvasProperty property3 = (WzCanvasProperty)prop;
         if (ExportBase64Data)
         {
             MemoryStream stream = new MemoryStream();
             property3.PngProperty.GetPNG(false).Save(stream, System.Drawing.Imaging.ImageFormat.Png);
             byte[] pngbytes = stream.ToArray();
             stream.Close();
             tw.Write(string.Concat(new object[] { depth, "<canvas name=\"", XmlUtil.SanitizeText(property3.Name), "\" width=\"", property3.PngProperty.Width, "\" height=\"", property3.PngProperty.Height, "\" basedata=\"", Convert.ToBase64String(pngbytes), "\">" }) + lineBreak);
         }
         else
         {
             tw.Write(string.Concat(new object[] { depth, "<canvas name=\"", XmlUtil.SanitizeText(property3.Name), "\" width=\"", property3.PngProperty.Width, "\" height=\"", property3.PngProperty.Height, "\">" }) + lineBreak);
         }
         string newDepth = depth + indent;
         foreach (WzImageProperty property in property3.WzProperties)
         {
             WritePropertyToXML(tw, newDepth, property);
         }
         tw.Write(depth + "</canvas>" + lineBreak);
     }
     else if (prop is WzIntProperty)
     {
         WzIntProperty property4 = (WzIntProperty)prop;
         tw.Write(string.Concat(new object[] { depth, "<int name=\"", XmlUtil.SanitizeText(property4.Name), "\" value=\"", property4.Value, "\"/>" }) + lineBreak);
     }
     else if (prop is WzDoubleProperty)
     {
         WzDoubleProperty property5 = (WzDoubleProperty)prop;
         tw.Write(string.Concat(new object[] { depth, "<double name=\"", XmlUtil.SanitizeText(property5.Name), "\" value=\"", property5.Value, "\"/>" }) + lineBreak);
     }
     else if (prop is WzNullProperty)
     {
         WzNullProperty property6 = (WzNullProperty)prop;
         tw.Write(depth + "<null name=\"" + XmlUtil.SanitizeText(property6.Name) + "\"/>" + lineBreak);
     }
     else if (prop is WzSoundProperty)
     {
         WzSoundProperty property7 = (WzSoundProperty)prop;
         if (ExportBase64Data)
         {
             tw.Write(string.Concat(new object[] { depth, "<sound name=\"", XmlUtil.SanitizeText(property7.Name), "\" length=\"", property7.Length.ToString(), "\" basehead=\"", Convert.ToBase64String(property7.Header), "\" basedata=\"", Convert.ToBase64String(property7.GetBytes(false)), "\"/>" }) + lineBreak);
         }
         else
         {
             tw.Write(depth + "<sound name=\"" + XmlUtil.SanitizeText(property7.Name) + "\"/>" + lineBreak);
         }
     }
     else if (prop is WzStringProperty)
     {
         WzStringProperty property8 = (WzStringProperty)prop;
         string           str       = XmlUtil.SanitizeText(property8.Value);
         tw.Write(depth + "<string name=\"" + XmlUtil.SanitizeText(property8.Name) + "\" value=\"" + str + "\"/>" + lineBreak);
     }
     else if (prop is WzSubProperty)
     {
         WzSubProperty property9 = (WzSubProperty)prop;
         tw.Write(depth + "<imgdir name=\"" + XmlUtil.SanitizeText(property9.Name) + "\">" + lineBreak);
         string newDepth = depth + indent;
         foreach (WzImageProperty property in property9.WzProperties)
         {
             WritePropertyToXML(tw, newDepth, property);
         }
         tw.Write(depth + "</imgdir>" + lineBreak);
     }
     else if (prop is WzShortProperty)
     {
         WzShortProperty property10 = (WzShortProperty)prop;
         tw.Write(string.Concat(new object[] { depth, "<short name=\"", XmlUtil.SanitizeText(property10.Name), "\" value=\"", property10.Value, "\"/>" }) + lineBreak);
     }
     else if (prop is WzLongProperty)
     {
         WzLongProperty long_prop = (WzLongProperty)prop;
         tw.Write(string.Concat(new object[] { depth, "<long name=\"", XmlUtil.SanitizeText(long_prop.Name), "\" value=\"", long_prop.Value, "\"/>" }) + lineBreak);
     }
     else if (prop is WzUOLProperty)
     {
         WzUOLProperty property11 = (WzUOLProperty)prop;
         tw.Write(depth + "<uol name=\"" + property11.Name + "\" value=\"" + XmlUtil.SanitizeText(property11.Value) + "\"/>" + lineBreak);
     }
     else if (prop is WzVectorProperty)
     {
         WzVectorProperty property12 = (WzVectorProperty)prop;
         tw.Write(string.Concat(new object[] { depth, "<vector name=\"", XmlUtil.SanitizeText(property12.Name), "\" x=\"", property12.X.Value, "\" y=\"", property12.Y.Value, "\"/>" }) + lineBreak);
     }
     else if (prop is WzFloatProperty)
     {
         WzFloatProperty property13 = (WzFloatProperty)prop;
         string          str2       = Convert.ToString(property13.Value, formattingInfo);
         if (!str2.Contains("."))
         {
             str2 = str2 + ".0";
         }
         tw.Write(depth + "<float name=\"" + XmlUtil.SanitizeText(property13.Name) + "\" value=\"" + str2 + "\"/>" + lineBreak);
     }
     else if (prop is WzConvexProperty)
     {
         tw.Write(depth + "<extended name=\"" + XmlUtil.SanitizeText(prop.Name) + "\">" + lineBreak);
         WzConvexProperty property14 = (WzConvexProperty)prop;
         string           newDepth   = depth + indent;
         foreach (WzImageProperty property in property14.WzProperties)
         {
             WritePropertyToXML(tw, newDepth, property);
         }
         tw.Write(depth + "</extended>" + lineBreak);
     }
 }
        public static void ExtractAnimation(WzSubProperty parent, string savePath, bool apngFirstFrame)
        {
            List <Bitmap> bmpList                    = new List <Bitmap>(parent.WzProperties.Count);
            List <int>    delayList                  = new List <int>(parent.WzProperties.Count);
            Point         biggestPng                 = new Point(0, 0);
            Point         SmallestEmptySpace         = new Point(65535, 65535);
            Point         MaximumPngMappingEndingPts = new Point(0, 0);

            foreach (WzImageProperty subprop in parent.WzProperties)
            {
                if (subprop is WzCanvasProperty)
                {
                    //System.Drawing.PointF origin = ((WzCanvasProperty)subprop).GetCanvasOriginPosition();
                    WzPngProperty png = ((WzCanvasProperty)subprop).PngProperty;
                    if (png.Height > biggestPng.Y)
                    {
                        biggestPng.Y = png.Height;
                    }
                    if (png.Width > biggestPng.X)
                    {
                        biggestPng.X = png.Width;
                    }
                }
            }
            List <WzCanvasProperty> sortedProps = new List <WzCanvasProperty>();

            foreach (WzImageProperty subprop in parent.WzProperties)
            {
                if (subprop is WzCanvasProperty)
                {
                    sortedProps.Add((WzCanvasProperty)subprop);
                    WzPngProperty         png    = ((WzCanvasProperty)subprop).PngProperty;
                    System.Drawing.PointF origin = ((WzCanvasProperty)subprop).GetCanvasOriginPosition();

                    Point StartPoints          = new Point(biggestPng.X - (int)origin.X, biggestPng.Y - (int)origin.Y);
                    Point PngMapppingEndingPts = new Point(StartPoints.X + png.Width, StartPoints.Y + png.Height);
                    if (StartPoints.X < SmallestEmptySpace.X)
                    {
                        SmallestEmptySpace.X = StartPoints.X;
                    }
                    if (StartPoints.Y < SmallestEmptySpace.Y)
                    {
                        SmallestEmptySpace.Y = StartPoints.Y;
                    }
                    if (PngMapppingEndingPts.X > MaximumPngMappingEndingPts.X)
                    {
                        MaximumPngMappingEndingPts.X = PngMapppingEndingPts.X;
                    }
                    if (PngMapppingEndingPts.Y > MaximumPngMappingEndingPts.Y)
                    {
                        MaximumPngMappingEndingPts.Y = PngMapppingEndingPts.Y;
                    }
                }
            }
            sortedProps.Sort(new Comparison <WzCanvasProperty>(PropertySorter));
            for (int i = 0; i < sortedProps.Count; i++)
            {
                WzCanvasProperty subprop = sortedProps[i];
                if (i.ToString() != subprop.Name)
                {
                    Warning.Error(string.Format(Properties.Resources.AnimError, i.ToString()));
                    return;
                }
                Bitmap bmp = subprop.PngProperty.GetImage(false);
                System.Drawing.PointF origin = subprop.GetCanvasOriginPosition();
                bmpList.Add(OptimizeBitmapTransparent(bmp, new WzVectorProperty("", origin.X, origin.Y), biggestPng, SmallestEmptySpace, MaximumPngMappingEndingPts));

                WzIntProperty delayProp = (WzIntProperty)subprop["delay"];
                int           delay     = 100;
                if (delayProp != null)
                {
                    delay = delayProp.Value;
                }
                delayList.Add(delay);
            }
            Apng apngBuilder = new Apng();

            if (apngFirstFrame)
            {
                apngBuilder.AddFrame(new Frame(CreateIncompatibilityFrame(new Size(bmpList[0].Width, bmpList[0].Height)), 1, 1));
            }
            for (int i = 0; i < bmpList.Count; i++)
            {
                apngBuilder.AddFrame(new Frame(bmpList[i], getNumByDelay(delayList[i]), getDenByDelay(delayList[i])));
            }
            apngBuilder.WriteApng(savePath, apngFirstFrame, true);
        }
Exemplo n.º 10
0
 // TODO: this is not deserializable due to missing type information
 protected void WritePropertyToJson(TextWriter tw, WzImageProperty prop, bool isArray = false)
 {
     tw.Write("\n");
     if (prop is WzCanvasProperty)
     {
         WzCanvasProperty property = (WzCanvasProperty)prop;
         if (!isArray)
         {
             tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\":");
         }
         if (ExportBase64Data)
         {
             MemoryStream stream = new MemoryStream();
             property.PngProperty.GetPNG(false).Save(stream, System.Drawing.Imaging.ImageFormat.Png);
             byte[] pngbytes = stream.ToArray();
             stream.Close();
             tw.Write($"{{" +
                      $"\"width\": {property.PngProperty.Width}, " +
                      $"\"height\": {property.PngProperty.Height}, " +
                      $"\"basedata\": {Convert.ToBase64String(pngbytes)}\",");
         }
         else
         {
             tw.Write($"{{" +
                      $"\"width\": {property.PngProperty.Width}, " +
                      $"\"height\": {property.PngProperty.Height},");
         }
         if (property.WzProperties.Count() > 0)
         {
             var last = property.WzProperties.Last();
             foreach (WzImageProperty p in property.WzProperties)
             {
                 WritePropertyToJson(tw, p);
                 if (!p.Equals(last))
                 {
                     tw.Write(",");
                 }
             }
         }
         tw.Write("}");
     }
     else if (prop is WzIntProperty)
     {
         WzIntProperty property = (WzIntProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {property.Value}");
     }
     else if (prop is WzDoubleProperty)
     {
         WzDoubleProperty property = (WzDoubleProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {property.Value}");
     }
     else if (prop is WzNullProperty)
     {
         WzNullProperty property = (WzNullProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": null");
     }
     else if (prop is WzSoundProperty)
     {
         WzSoundProperty property = (WzSoundProperty)prop;
         if (!isArray)
         {
             tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\":");
         }
         if (ExportBase64Data)
         {
             tw.Write($"{{" +
                      $"\"length\":\"{property.Length}\", " +
                      $"\"basehead\": \"{Convert.ToBase64String(property.Header)}\"" +
                      $"\"basedata\": \"{Convert.ToBase64String(property.GetBytes(false))}\"" +
                      $"}}");
         }
         else
         {
             tw.Write("{}");
         }
     }
     else if (prop is WzStringProperty)
     {
         WzStringProperty property = (WzStringProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {JsonConvert.ToString(property.Value)}");
     }
     else if (prop is WzSubProperty)
     {
         WzSubProperty property = (WzSubProperty)prop;
         if (!isArray)
         {
             tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\":");
         }
         // This has the same problem as the convex property
         bool propertyIsArray = property.WzProperties.TrueForAll(x => { int num; return(int.TryParse(x.Name, out num)); });
         tw.Write(propertyIsArray ? "[" : "{");
         if (property.WzProperties.Count() > 0)
         {
             var last = property.WzProperties.Last();
             foreach (WzImageProperty p in property.WzProperties)
             {
                 bool isObject = p is WzConvexProperty || p is WzSubProperty || p is WzSoundProperty || p is WzCanvasProperty || p is WzVectorProperty;
                 if (propertyIsArray)
                 {
                     tw.Write($"{{\"index\":{p.Name}, \"item\":");
                     tw.Write(!isObject ? "{" : "");
                 }
                 WritePropertyToJson(tw, p, propertyIsArray);
                 if (propertyIsArray)
                 {
                     tw.Write(!isObject ? "}" : "");
                     tw.Write("}");
                 }
                 if (!p.Equals(last))
                 {
                     tw.Write(",");
                 }
             }
         }
         tw.Write(propertyIsArray ? "]" : "}");
     }
     else if (prop is WzShortProperty)
     {
         WzShortProperty property = (WzShortProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {property.Value}");
     }
     else if (prop is WzLongProperty)
     {
         WzLongProperty property = (WzLongProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {property.Value}");
     }
     else if (prop is WzUOLProperty)
     {
         WzUOLProperty property = (WzUOLProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": \"{property.Value}\"");
     }
     else if (prop is WzVectorProperty)
     {
         WzVectorProperty property = (WzVectorProperty)prop;
         if (!isArray)
         {
             tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\":");
         }
         tw.Write($"{{" +
                  $"\"x\": {property.X.Value}, " +
                  $"\"y\": {property.Y.Value}" +
                  $"}}");
     }
     else if (prop is WzFloatProperty)
     {
         WzFloatProperty property = (WzFloatProperty)prop;
         tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\": {property.Value * 1.0}");
     }
     else if (prop is WzConvexProperty)
     {
         WzConvexProperty property = (WzConvexProperty)prop;
         if (!isArray)
         {
             tw.Write($"\"{XmlUtil.SanitizeText(property.Name)}\":");
         }
         tw.Write("[");
         if (property.WzProperties.Count() > 0)
         {
             var last = property.WzProperties.Last();
             foreach (WzImageProperty p in property.WzProperties)
             {
                 bool isObject = p is WzConvexProperty || p is WzSubProperty || p is WzSoundProperty || p is WzCanvasProperty || p is WzVectorProperty;
                 tw.Write(isObject ? "" : "{");
                 WritePropertyToJson(tw, p, true);
                 tw.Write(isObject ? "" : "}");
                 if (!p.Equals(last))
                 {
                     tw.Write(",");
                 }
             }
         }
         tw.Write("]");
     }
 }