/// <summary> /// Function to read a track containing rectangle data. /// </summary> /// <param name="reader">The JSON reader.</param> /// <param name="converter">The converter used to convert the data from JSON.</param> /// <param name="interpolation">The interpolation mode for the track.</param> /// <returns>A list of rectangle key frames.</returns> private static List <GorgonKeyRectangle> ReadRects(JsonReader reader, JsonRectKeyConverter converter, out TrackInterpolationMode interpolation) { List <GorgonKeyRectangle> ReadKeys() { var keys = new List <GorgonKeyRectangle>(); Type type = typeof(GorgonKeyRectangle); while ((reader.Read()) && (reader.TokenType != JsonToken.EndArray)) { if (reader.TokenType != JsonToken.StartObject) { continue; } keys.Add(converter.ReadJson(reader, type, null, false, null)); } return(keys); } List <GorgonKeyRectangle> bounds = null; interpolation = TrackInterpolationMode.None; while ((reader.Read()) && (reader.TokenType != JsonToken.EndObject)) { if (reader.TokenType != JsonToken.PropertyName) { continue; } string propName = reader.Value.ToString().ToUpperInvariant(); switch (propName) { case "INTERPOLATIONMODE": interpolation = (TrackInterpolationMode)(reader.ReadAsInt32() ?? 0); break; case "KEYFRAMES": bounds = ReadKeys(); break; } } return(bounds); }
/// <summary> /// Function to convert a JSON formatted string into a <see cref="IGorgonAnimation"/> object. /// </summary> /// <param name="renderer">The renderer for the animation.</param> /// <param name="json">The JSON string containing the animation data.</param> /// <returns>A new <see cref="IGorgonAnimation"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="renderer"/>, or the <paramref name="json"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="json"/> parameter is empty.</exception> /// <exception cref="GorgonException">Thrown if the JSON string does not contain animation data, or there is a version mismatch.</exception> public IGorgonAnimation FromJson(Gorgon2D renderer, string json) { if (renderer == null) { throw new ArgumentNullException(nameof(renderer)); } if (json == null) { throw new ArgumentNullException(nameof(json)); } if (string.IsNullOrWhiteSpace(json)) { throw new ArgumentEmptyException(nameof(json)); } string animName = string.Empty; float animLength = 0; int loopCount = 0; bool isLooped = false; var colorConvert = new JsonGorgonColorKeyConverter(); var textureConvert = new JsonTextureKeyConverter(renderer.Graphics); var vec3Converter = new JsonVector3KeyConverter(); var rectConverter = new JsonRectKeyConverter(); TrackInterpolationMode posInterp = TrackInterpolationMode.None; TrackInterpolationMode scaleInterp = TrackInterpolationMode.None; TrackInterpolationMode rotInterp = TrackInterpolationMode.None; TrackInterpolationMode sizeInterp = TrackInterpolationMode.None; TrackInterpolationMode colorInterp = TrackInterpolationMode.None; TrackInterpolationMode boundInterp = TrackInterpolationMode.None; List <GorgonKeyVector3> positions = null; List <GorgonKeyVector3> rotations = null; List <GorgonKeyVector3> scales = null; List <GorgonKeyVector3> sizes = null; List <GorgonKeyGorgonColor> colors = null; List <GorgonKeyRectangle> bounds = null; List <GorgonKeyTexture2D> textures = null; using (var baseReader = new StringReader(json)) using (var reader = new JsonTextReader(baseReader)) { if (!IsReadableJObject(reader)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2DIO_ERR_JSON_NOT_ANIM); } while (reader.Read()) { if (reader.TokenType != JsonToken.PropertyName) { continue; } string propName = reader.Value.ToString().ToUpperInvariant(); switch (propName) { case "POSITIONS": positions = ReadVector3(reader, vec3Converter, out posInterp); break; case "SCALES": scales = ReadVector3(reader, vec3Converter, out scaleInterp); break; case "ROTATIONS": rotations = ReadVector3(reader, vec3Converter, out rotInterp); break; case "SIZE": sizes = ReadVector3(reader, vec3Converter, out sizeInterp); break; case "BOUNDS": bounds = ReadRects(reader, rectConverter, out boundInterp); break; case "COLORS": colors = ReadColors(reader, colorConvert, out colorInterp); break; case "TEXTURES": textures = ReadTextures(reader, textureConvert); break; case "NAME": animName = reader.ReadAsString(); break; case "LENGTH": animLength = (float)(reader.ReadAsDecimal() ?? 0); break; case "ISLOOPED": isLooped = (reader.ReadAsBoolean() ?? false); break; case "LOOPCOUNT": loopCount = (reader.ReadAsInt32() ?? 0); break; } } } // There's no name, so it's a broken JSON. if (string.IsNullOrWhiteSpace(animName)) { throw new GorgonException(GorgonResult.CannotRead, Resources.GOR2DIO_ERR_JSON_NOT_ANIM); } var builder = new GorgonAnimationBuilder(); if ((positions != null) && (positions.Count > 0)) { builder.PositionInterpolationMode(posInterp) .EditPositions() .SetKeys(positions) .EndEdit(); } if ((scales != null) && (scales.Count > 0)) { builder.ScaleInterpolationMode(scaleInterp) .EditScale() .SetKeys(scales) .EndEdit(); } if ((rotations != null) && (rotations.Count > 0)) { builder.RotationInterpolationMode(rotInterp) .EditRotation() .SetKeys(rotations) .EndEdit(); } if ((sizes != null) && (sizes.Count > 0)) { builder.SizeInterpolationMode(sizeInterp) .EditSize() .SetKeys(sizes) .EndEdit(); } if ((colors != null) && (colors.Count > 0)) { builder.ColorInterpolationMode(colorInterp) .EditColors() .SetKeys(colors) .EndEdit(); } if ((bounds != null) && (bounds.Count > 0)) { builder.RotationInterpolationMode(boundInterp) .EditRectangularBounds() .SetKeys(bounds) .EndEdit(); } if ((textures != null) && (textures.Count > 0)) { builder.Edit2DTexture() .SetKeys(textures) .EndEdit(); } IGorgonAnimation result = builder.Build(animName, animLength); result.LoopCount = loopCount; result.IsLooped = isLooped; result.Speed = 1.0f; return(result); }