1
0
mirror of synced 2025-01-19 09:17:30 +01:00

BFRES : Add JSON/YAML converting with scene animations.

This commit is contained in:
KillzXGaming 2020-01-12 17:39:47 -05:00
parent 7936762ec9
commit 65aa3598a2
5 changed files with 274 additions and 4 deletions

View File

@ -84,14 +84,40 @@ namespace Bfres.Structs
public override string ReplaceFilter => FileFilters.GetFilter(typeof(FSCN)); public override string ReplaceFilter => FileFilters.GetFilter(typeof(FSCN));
public override void Export(string FileName) public override void Export(string FileName)
{
string ext = Utils.GetExtension(FileName);
if (ext == ".bfscn")
{ {
SceneAnim.Export(FileName, ((BFRESGroupNode)Parent).GetResFile()); SceneAnim.Export(FileName, ((BFRESGroupNode)Parent).GetResFile());
} }
else if (ext == ".yaml")
{
System.IO.File.WriteAllText(FileName, YamlFscn.ToYaml(FileName, SceneAnim));
}
else if (ext == ".json")
{
System.IO.File.WriteAllText(FileName, YamlFscn.ToJson(FileName, SceneAnim));
}
}
public override void Replace(string FileName) { public override void Replace(string FileName) {
string ext = Utils.GetExtension(FileName);
if (ext == ".bfscn")
{
Replace(FileName, GetResFile(), GetResFileU()); Replace(FileName, GetResFile(), GetResFileU());
} }
else if (ext == ".yaml")
{
SceneAnim = YamlFscn.FromYaml(FileName);
}
else if (ext == ".json")
{
SceneAnim = YamlFscn.FromJson(FileName);
}
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU) public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU)
{ {

View File

@ -1454,6 +1454,7 @@
<Compile Include="YAML\YamlFmaa.cs" /> <Compile Include="YAML\YamlFmaa.cs" />
<Compile Include="YAML\YamlFmat.cs" /> <Compile Include="YAML\YamlFmat.cs" />
<Compile Include="YAML\YamlFska.cs" /> <Compile Include="YAML\YamlFska.cs" />
<Compile Include="YAML\YamlFscn.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@ -141,6 +141,8 @@ namespace FirstPlugin
private void GetShapeTransform() private void GetShapeTransform()
{ {
if (activeShape.boundingBoxes.Count == 0) return;
Vector3 translate = new Vector3(0); Vector3 translate = new Vector3(0);
Vector3 scale = new Vector3(1); Vector3 scale = new Vector3(1);
Vector4 rotate = new Vector4(0); Vector4 rotate = new Vector4(0);

View File

@ -38,10 +38,10 @@ namespace FirstPlugin
public static string FTXP = GetFilter(".bftxp", ".yaml", ".gif"); public static string FTXP = GetFilter(".bftxp", ".yaml", ".gif");
public static string FMTV = GetFilter(".bfmvi"); public static string FMTV = GetFilter(".bfmvi");
public static string FBNV = GetFilter(".bfbvi"); public static string FBNV = GetFilter(".bfbvi");
public static string FSCN = GetFilter(".bfscn"); public static string FSCN = GetFilter(".bfscn", ".yaml", ".json");
public static string FSHA = GetFilter(".bfspa"); public static string FSHA = GetFilter(".bfspa");
public static string CMDL = GetFilter(".dae"); public static string CMDL = GetFilter(".dae", ".cmdl");
public static string NUTEXB = GetFilter(".dds",".png", ".bmp", ".tga", ".jpg", ".tiff", ".tif", ".gif"); public static string NUTEXB = GetFilter(".dds",".png", ".bmp", ".tga", ".jpg", ".tiff", ".tif", ".gif");
public static string XTX = GetFilter(".dds", ".png", ".bmp", ".tga", ".jpg", ".tiff", ".tif", ".gif"); public static string XTX = GetFilter(".dds", ".png", ".bmp", ".tga", ".jpg", ".tiff", ".tif", ".gif");
@ -61,6 +61,7 @@ namespace FirstPlugin
else if (type == typeof(FTXP)) return FTXP; else if (type == typeof(FTXP)) return FTXP;
else if (type == typeof(FSHA)) return FSHA; else if (type == typeof(FSHA)) return FSHA;
else if (type == typeof(FTEX)) return FTEX; else if (type == typeof(FTEX)) return FTEX;
else if (type == typeof(FSCN)) return FSCN;
else if (type == typeof(FSHU)) else if (type == typeof(FSHU))
{ {
if (IsExporting) if (IsExporting)
@ -137,6 +138,7 @@ namespace FirstPlugin
case ".anim": filters.Add(ext, "Maya Animation"); break; case ".anim": filters.Add(ext, "Maya Animation"); break;
case ".yaml": filters.Add(ext, "Yet Another Markup Language"); break; case ".yaml": filters.Add(ext, "Yet Another Markup Language"); break;
case ".gif": filters.Add(ext, "Graphics Interchange Format"); break; case ".gif": filters.Add(ext, "Graphics Interchange Format"); break;
case ".cmdl": filters.Add(ext, "CTR Model"); break;
default: default:
filters.Add(ext, ""); break; filters.Add(ext, ""); break;
} }

View File

@ -0,0 +1,239 @@
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<AnimConfig>(
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<AnimConfig>(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<CameraAnimConfig> CameraAnimations = new List<CameraAnimConfig>();
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.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.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 CameraAnimData BaseData { get; set; }
[JsonProperty(Order = 6)]
public List<CameraAnimCurve> Curves = new List<CameraAnimCurve>();
public CameraAnimConfig() { }
public CameraAnimConfig(CameraAnim camAnim)
{
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<int, float> KeyFrames { get; set; }
public CameraAnimCurve() { }
public CameraAnimCurve(AnimCurve curve) {
KeyFrames = new Dictionary<int, float>();
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,
}
}
}