using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SharpYaml; using SharpYaml.Events; using SharpYaml.Serialization; using SharpYaml.Serialization.Serializers; using Syroot.NintenTools.NSW.Bfres; using Newtonsoft.Json; namespace FirstPlugin { public class YamlFscn { public static string ToJson(string Name, SceneAnim sceneAnim) { var config = new AnimConfig(); config.ToYaml(sceneAnim); return JsonConvert.SerializeObject(config, Formatting.Indented); } public static SceneAnim FromJson(string Name) { AnimConfig config = JsonConvert.DeserializeObject( System.IO.File.ReadAllText(Name)); return config.FromYaml(); } public static string ToYaml(string Name, SceneAnim sceneAnim) { var serializerSettings = new SerializerSettings() { // EmitTags = false }; serializerSettings.DefaultStyle = YamlStyle.Any; serializerSettings.ComparerForKeySorting = null; serializerSettings.RegisterTagMapping("AnimConfig", typeof(AnimConfig)); var config = new AnimConfig(); config.ToYaml(sceneAnim); var serializer = new Serializer(serializerSettings); string yaml = serializer.Serialize(config, typeof(AnimConfig)); return yaml; } public static SceneAnim FromYaml(string Name) { var serializerSettings = new SerializerSettings() { // EmitTags = false }; serializerSettings.DefaultStyle = YamlStyle.Any; serializerSettings.ComparerForKeySorting = null; serializerSettings.RegisterTagMapping("AnimConfig", typeof(AnimConfig)); var serializer = new Serializer(serializerSettings); AnimConfig config = serializer.Deserialize(System.IO.File.ReadAllText(Name)); return config.FromYaml(); } public class AnimConfig { [JsonProperty(Order = 0)] public string Name { get; set; } [JsonProperty(Order = 1)] public string Path { get; set; } [JsonProperty(Order = 2)] public List CameraAnimations = new List(); public void ToYaml(SceneAnim sceneAnim) { Name = sceneAnim.Name; Path = sceneAnim.Path; foreach (var cameraAnim in sceneAnim.CameraAnims) CameraAnimations.Add(new CameraAnimConfig(cameraAnim)); } public SceneAnim FromYaml() { SceneAnim anim = new SceneAnim(); anim.Name = Name; anim.Path = Path; foreach (var camera in CameraAnimations) { CameraAnim camAnim = new CameraAnim(); camAnim.Name = camera.Name; camAnim.FrameCount = camera.FrameCount; camAnim.BakedSize = camera.BakedSize; camAnim.BaseData = camera.BaseData; if (camera.EulerZXY) camAnim.Flags |= CameraAnimFlags.EulerZXY; if (camera.Loop) camAnim.Flags |= CameraAnimFlags.Looping; if (camera.Perspective) camAnim.Flags |= CameraAnimFlags.Perspective; foreach (var curve in camera.Curves) { AnimCurve animCurve = new AnimCurve(); animCurve.AnimDataOffset = ConvertOffset(curve.Type); animCurve.Scale = 1; animCurve.CurveType = AnimCurveType.Linear; int FrameCount = curve.KeyFrames.Count; animCurve.Frames = new float[FrameCount]; animCurve.Keys = new float[FrameCount, 2]; var values = curve.KeyFrames.Values.ToList(); for (int i = 0; i < curve.KeyFrames.Count; i++) { var KeyFrame = curve.KeyFrames.ElementAt(i); animCurve.Frames[i] = KeyFrame.Key; animCurve.Keys[i, 0] = KeyFrame.Value; //Calculate delta float Delta = 0; if (i < values.Count - 1) Delta = values[i + 1] - values[i]; animCurve.Keys[i, 1] = Delta; } animCurve.StartFrame = animCurve.Frames.Max(); animCurve.EndFrame = animCurve.Frames.Max(); if (animCurve.Keys.Length > 1) animCurve.Delta = values[values.Count - 1] - values[0]; animCurve.KeyType = AnimCurveKeyType.Single; animCurve.FrameType = AnimCurveFrameType.Single; camAnim.Curves.Add(animCurve); } anim.CameraAnims.Add(camAnim); anim.CameraAnimDict.Add(camAnim.Name); } return anim; } private static uint ConvertOffset(string type) { CameraOffsetType flags; bool isValid = Enum.TryParse(type, out flags); if (!isValid) throw new Exception($"Invalid camera curve type {type}!"); return (uint)flags; } } public class CameraAnimConfig { [JsonProperty(Order = 0)] public string Name { get; set; } [JsonProperty(Order = 1)] public bool Loop { get; set; } [JsonProperty(Order = 2)] public int FrameCount { get; set; } [JsonProperty(Order = 3)] public bool EulerZXY { get; set; } [JsonProperty(Order = 4)] public bool Perspective { get; set; } [JsonProperty(Order = 5)] public uint BakedSize { get; set; } [JsonProperty(Order = 6)] public CameraAnimData BaseData { get; set; } [JsonProperty(Order = 7)] public List Curves = new List(); public CameraAnimConfig() { } public CameraAnimConfig(CameraAnim camAnim) { FrameCount = camAnim.FrameCount; BakedSize = camAnim.BakedSize; Name = camAnim.Name; Loop = camAnim.Flags.HasFlag(CameraAnimFlags.Looping); EulerZXY = camAnim.Flags.HasFlag(CameraAnimFlags.EulerZXY); Perspective = camAnim.Flags.HasFlag(CameraAnimFlags.Perspective); BaseData = camAnim.BaseData; foreach (var curve in camAnim.Curves) Curves.Add(new CameraAnimCurve(curve)); } } public class CameraAnimCurve { [JsonProperty(Order = 0)] public string Type; [JsonProperty(Order = 1)] public Dictionary KeyFrames { get; set; } public CameraAnimCurve() { } public CameraAnimCurve(AnimCurve curve) { KeyFrames = new Dictionary(); Type = ((CameraOffsetType)curve.AnimDataOffset).ToString(); for (int f = 0; f < curve.Frames.Length; f++) { int frame = (int)curve.Frames[f]; float Value = curve.Offset + curve.Keys[f, 0] * curve.Scale; KeyFrames.Add(frame, Value); } } } //Offsets to get data from "Values" public enum CameraOffsetType { ClipNear = 0, ClipFar = 4, AspectRatio = 8, FieldOFView = 12, PositionX = 16, PositionY = 20, PositionZ = 24, RotationX = 28, RotationY = 32, RotationZ = 36, Twist = 40, } } }