1
0
mirror of synced 2024-11-27 17:00:50 +01:00

Push support for V10 BFRES saving, TXTG load/saving, Anim fixes, and more.

This commit is contained in:
KillzXGaming 2023-05-27 19:33:14 -04:00
parent 15e6c1c7fd
commit 2c75de1f1c
31 changed files with 765 additions and 2017 deletions

View File

@ -7,6 +7,8 @@ using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
using System.IO;
using VGAudio.Utilities;
namespace FirstPlugin
{
@ -80,9 +82,24 @@ namespace FirstPlugin
uint CompressionType = reader.ReadUInt32();
uint DecompressedSize = reader.ReadUInt32();
uint CompressedSize = reader.ReadUInt32();
byte[] input = reader.ReadBytes((int)CompressedSize);
if (CompressionType == 1) input = BPE.Decompress(input, DecompressedSize, CompressedSize);
if (CompressionType == 2) input = LZ77_WII.Decompress(input);
if (CompressionType == 3) input = LZ77_WII.Decompress(input); //same as 2
using (var r = new FileReader(input))
{
for (int i = 0; i < FileCount; i++)
{
r.SeekBegin(files[i].Offset - DataOffset);
files[i].FileData = r.ReadBytes((int)files[i].Size);
}
}
}
}
public void Unload()
{
@ -146,13 +163,15 @@ namespace FirstPlugin
public class FileEntry : ArchiveFileInfo
{
public uint Hash { get; set; }
public uint Offset { get; set; }
public uint Size { get; set; }
public void Read(FileReader reader)
{
Hash = reader.ReadUInt32();
FileName = GetName(reader);
uint Size = reader.ReadUInt32();
uint Offset = reader.ReadUInt32();
Size = reader.ReadUInt32();
Offset = reader.ReadUInt32();
}
}
@ -164,5 +183,114 @@ namespace FirstPlugin
return reader.ReadZeroTerminatedString();
}
}
class BPE
{
//Decompiled from MasterF0X tool for BPE decompression
static int index = 0;
static bool end = false;
public static byte[] Decompress(byte[] input, uint decompressedSize, uint cs)
{
char[] chArray1 = new char[16777215];
char[] chArray2 = new char[16777215];
char[] chArray3 = new char[16777215];
var mem = new MemoryStream();
BinaryWriter binaryWriter = new BinaryWriter(mem);
label_26:
int num1;
int num2;
while (index < input.Length)
{
if (end)
{
binaryWriter.Close();
end = false;
index = 0;
num1 = 0;
num2 = 0;
return mem.ToArray();
}
for (int index = 0; index < 256; ++index)
chArray1[index] = (char)index;
int num3 = (int)getc(input, cs);
int index1 = 0;
while (true)
{
if (num3 > (int)sbyte.MaxValue)
{
index1 += num3 - (int)sbyte.MaxValue;
num3 = 0;
}
if (index1 != 256)
{
int num4 = 0;
while (num4 <= num3)
{
chArray1[index1] = getc(input, cs);
if (index1 != (int)chArray1[index1])
chArray2[index1] = getc(input, cs);
++num4;
++index1;
}
if (index1 != 256)
num3 = (int)getc(input, cs);
else
break;
}
else
break;
}
int num5 = 256 * (int)getc(input, cs) + (int)getc(input, cs);
int num6 = 0;
while (true)
{
int index2;
if (num6 > 0)
index2 = (int)chArray3[--num6];
else if (num5-- != 0)
index2 = (int)getc(input, cs);
else
goto label_26;
if (index2 == (int)chArray1[index2])
{
binaryWriter.Write((byte)index2);
}
else
{
char[] chArray4 = chArray3;
int index3 = num6;
int num7 = index3 + 1;
int num8 = (int)chArray2[index2];
chArray4[index3] = (char)num8;
char[] chArray5 = chArray3;
int index4 = num7;
num6 = index4 + 1;
int num9 = (int)chArray1[index2];
chArray5[index4] = (char)num9;
}
}
}
binaryWriter.Close();
end = false;
index = 0;
num1 = 0;
num2 = 0;
return mem.ToArray();
}
static char getc(byte[] input, uint uncompS)
{
if (index >= uncompS)
{
end = true;
return '0';
}
char ch = (char)input[index];
++index;
return ch;
}
}
}
}

View File

@ -7,6 +7,8 @@ using Syroot.NintenTools.NSW.Bfres;
using Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using Toolbox.Library.Animations;
using AampLibraryCSharp;
using static FirstPlugin.CSAB;
namespace Bfres.Structs
{
@ -26,76 +28,94 @@ namespace Bfres.Structs
else return AnimCurveKeyType.Single;
}
public static Animation.KeyGroup CreateTrackWiiU(ResU.AnimCurve animCurve)
public static Animation.KeyGroup CreateTrackWiiU(ResU.AnimCurve curve, bool valuesAsInts = false)
{
Animation.KeyGroup track = new Animation.KeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
track.AnimDataOffset = curve.AnimDataOffset;
track.Scale = curve.Scale;
track.Offset = curve.Offset;
track.StartFrame = curve.StartFrame;
track.EndFrame = curve.EndFrame;
track.Delta = curve.Delta;
float tanscale = animCurve.Delta;
float tanscale = curve.Delta;
if (tanscale == 0)
tanscale = 1;
if (animCurve.Scale == 0)
animCurve.Scale = 1;
if (curve.Scale == 0)
curve.Scale = 1;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
float valueScale = curve.Scale > 0 ? curve.Scale : 1;
for (int i = 0; i < curve.Frames.Length; i++)
{
switch (animCurve.CurveType)
var frame = curve.Frames[i];
if (frame == 0 && track.Keys.Any(x => x.Frame == 0))
track.Keys.RemoveAt(0);
switch (curve.CurveType)
{
case ResU.AnimCurveType.Cubic: //4 elements are stored for cubic
track.InterpolationType = InterpolationType.HERMITE;
var coef0 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale);
var coef1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale);
var coef2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale);
var coef3 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale);
var slopes = GetSlopes(animCurve, i);
case ResU.AnimCurveType.Cubic:
{
track.InterpolationType = InterpolationType.HERMITE;
//Important to not offset the other 3 values, just the first one!
var value = curve.Keys[i, 0] * valueScale + curve.Offset;
var slopes = GetSlopes(curve, i);
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.HERMITE,
Frame = (int)animCurve.Frames[i],
Value = coef0,
// Slope1 = slopes[0],
// Slope2 = slopes[1],
});
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
In = slopes[0],
Out = slopes[1],
});
}
break;
case ResU.AnimCurveType.Linear: //2 elements are stored for linear
track.InterpolationType = InterpolationType.LINEAR;
track.Keys.Add(new Animation.KeyFrame()
case ResU.AnimCurveType.Linear:
{
IsKeyed = true,
InterType = InterpolationType.LINEAR,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
track.InterpolationType = InterpolationType.LINEAR;
var value = curve.Keys[i, 0] * valueScale + curve.Offset;
var delta = curve.Keys[i, 1] * valueScale;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
Delta = delta,
});
}
break;
case ResU.AnimCurveType.StepInt: //1 element are stored for step
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
case ResU.AnimCurveType.StepBool:
{
IsKeyed = true,
InterType = InterpolationType.STEP,
Frame = (int)animCurve.Frames[i],
Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
});
Console.WriteLine($"Frame {animCurve.Frames[i]} FrameINT {(int)animCurve.Frames[i]} Offset " + (int)animCurve.Offset + " " + ((int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale));
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = curve.KeyStepBoolData[i] ? 1 : 0,
});
}
break;
default:
throw new Exception("Unsupported anim type!");
{
track.InterpolationType = InterpolationType.STEP;
var value = curve.Keys[i, 0] + curve.Offset;
if (valuesAsInts)
value = (int)curve.Keys[i, 0] + curve.Offset;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
});
}
break;
}
}
return track;
}
//Method to extract the slopes from a cubic curve
//Need to get the time, delta, out and next in slope values
public static float[] GetSlopes(AnimCurve curve, float index)
{
float[] slopes = new float[2];
@ -106,9 +126,9 @@ namespace Bfres.Structs
for (int i = 0; i < curve.Frames.Length; i++)
{
var coef0 = curve.Keys[i, 0] * curve.Scale + curve.Offset;
var coef1 = curve.Keys[i, 1] * curve.Scale + curve.Offset;
var coef2 = curve.Keys[i, 2] * curve.Scale + curve.Offset;
var coef3 = curve.Keys[i, 3] * curve.Scale + curve.Offset;
var coef1 = curve.Keys[i, 1] * curve.Scale;
var coef2 = curve.Keys[i, 2] * curve.Scale;
var coef3 = curve.Keys[i, 3] * curve.Scale;
float time = 0;
float delta = 0;
if (i < curve.Frames.Length - 1)
@ -118,7 +138,7 @@ namespace Bfres.Structs
time = curve.Frames[i + 1] - curve.Frames[i];
}
var slopeData = CurveInterpolationHelper.GetCubicSlopes(time, delta,
var slopeData = GetCubicSlopes(time, delta,
new float[4] { coef0, coef1, coef2, coef3, });
if (index == i)
@ -135,6 +155,7 @@ namespace Bfres.Structs
return slopes;
}
public static float[] GetSlopes(ResU.AnimCurve curve, float index)
{
float[] slopes = new float[2];
@ -145,9 +166,9 @@ namespace Bfres.Structs
for (int i = 0; i < curve.Frames.Length; i++)
{
var coef0 = curve.Keys[i, 0] * curve.Scale + curve.Offset;
var coef1 = curve.Keys[i, 1] * curve.Scale + curve.Offset;
var coef2 = curve.Keys[i, 2] * curve.Scale + curve.Offset;
var coef3 = curve.Keys[i, 3] * curve.Scale + curve.Offset;
var coef1 = curve.Keys[i, 1] * curve.Scale;
var coef2 = curve.Keys[i, 2] * curve.Scale;
var coef3 = curve.Keys[i, 3] * curve.Scale;
float time = 0;
float delta = 0;
if (i < curve.Frames.Length - 1)
@ -157,7 +178,7 @@ namespace Bfres.Structs
time = curve.Frames[i + 1] - curve.Frames[i];
}
var slopeData = CurveInterpolationHelper.GetCubicSlopes(time, delta,
var slopeData = GetCubicSlopes(time, delta,
new float[4] { coef0, coef1, coef2, coef3, });
if (index == i)
@ -174,6 +195,14 @@ namespace Bfres.Structs
return slopes;
}
public static float[] GetCubicSlopes(float time, float delta, float[] coef)
{
float outSlope = coef[1] / time;
float param = coef[3] - (-2 * delta);
float inSlope = param / time - outSlope;
return new float[2] { inSlope, coef[1] == 0 ? 0 : outSlope };
}
public static BooleanKeyGroup CreateBooleanTrackWiiU(ResU.AnimCurve animCurve)
{
BooleanKeyGroup track = new BooleanKeyGroup();
@ -235,75 +264,86 @@ namespace Bfres.Structs
return track;
}
public static Animation.KeyGroup CreateTrack(AnimCurve animCurve)
public static Animation.KeyGroup CreateTrack(AnimCurve curve, bool valuesAsInts = false)
{
Animation.KeyGroup track = new Animation.KeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
track.AnimDataOffset = curve.AnimDataOffset;
track.Scale = curve.Scale;
track.Offset = curve.Offset;
track.StartFrame = curve.StartFrame;
track.EndFrame = curve.EndFrame;
track.Delta = curve.Delta;
float tanscale = animCurve.Delta;
float tanscale = curve.Delta;
if (tanscale == 0)
tanscale = 1;
if (animCurve.Scale == 0)
animCurve.Scale = 1;
if (curve.Scale == 0)
curve.Scale = 1;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
float valueScale = curve.Scale > 0 ? curve.Scale : 1;
for (int i = 0; i < curve.Frames.Length; i++)
{
switch (animCurve.CurveType)
var frame = curve.Frames[i];
if (frame == 0 && track.Keys.Any(x => x.Frame == 0))
track.Keys.RemoveAt(0);
switch (curve.CurveType)
{
case AnimCurveType.Cubic: //4 elements are stored for cubic
track.InterpolationType = InterpolationType.HERMITE;
var coef0 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale);
var coef1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale);
var coef2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale);
var coef3 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale);
var slopes = GetSlopes(animCurve, i);
var inSlope = slopes[0] * animCurve.Scale + animCurve.Offset;
var outSlope = slopes[1] * animCurve.Scale + animCurve.Offset;
track.Keys.Add(new Animation.KeyFrame()
case AnimCurveType.Cubic:
{
IsKeyed = true,
InterType = InterpolationType.HERMITE,
Frame = (int)animCurve.Frames[i],
Value = coef0,
Slope1 = inSlope,
Slope2 = outSlope,
});
track.InterpolationType = InterpolationType.HERMITE;
//Important to not offset the other 3 values, just the first one!
var value = curve.Keys[i, 0] * valueScale + curve.Offset;
var slopes = GetSlopes(curve, i);
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
In = slopes[0],
Out = slopes[1],
});
}
break;
case AnimCurveType.Linear: //2 elements are stored for linear
track.InterpolationType = InterpolationType.LINEAR;
track.Keys.Add(new Animation.KeyFrame()
case AnimCurveType.Linear:
{
IsKeyed = true,
InterType = InterpolationType.LINEAR,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
track.InterpolationType = InterpolationType.LINEAR;
var value = curve.Keys[i, 0] * valueScale + curve.Offset;
var delta = curve.Keys[i, 1] * valueScale;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
Delta = delta,
});
}
break;
case AnimCurveType.StepInt: //1 element are stored for step
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
case AnimCurveType.StepBool:
{
IsKeyed = true,
InterType = InterpolationType.STEP,
Frame = (int)animCurve.Frames[i],
Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
Value1 = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
});
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = curve.KeyStepBoolData[i] ? 1 : 0,
});
}
break;
default:
throw new Exception("Unsupported anim type!");
{
track.InterpolationType = InterpolationType.STEP;
var value = curve.Keys[i, 0] + curve.Offset;
if (valuesAsInts)
value = (int)curve.Keys[i, 0] + curve.Offset;
track.Keys.Add(new Animation.KeyFrame()
{
Frame = frame,
Value = value,
});
}
break;
}
}

View File

@ -431,7 +431,7 @@ namespace Bfres.Structs
{
int index = (int)SamplerInfo.CurveIndex;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]);
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index], true);
sampler.AnimDataOffset = matanim.Curves[index].AnimDataOffset;
sampler.Keys = keyGroup.Keys;

View File

@ -610,6 +610,7 @@ namespace Bfres.Structs
Dictionary<string, List<FSHP.VertexAttribute>> AttributeMatcher = new Dictionary<string, List<FSHP.VertexAttribute>>();
bool IsWiiU = (resFileU != null);
var boneMappings = Model != null ? Model.Skeleton.userIndices : new ushort[0];
int MatStartIndex = materials.Count;
string ext = System.IO.Path.GetExtension(FileName);
@ -1365,6 +1366,9 @@ namespace Bfres.Structs
if (IsEdited)
UpdateVertexData();
if (Model != null)
Model.Skeleton.userIndices = boneMappings;
}
public FMAT GetMaterial(int index)

View File

@ -11,6 +11,7 @@ using Toolbox.Library.Animations;
using Toolbox.Library.Forms;
using SELib;
using FirstPlugin.Forms;
using static Toolbox.Library.Animations.Animation;
namespace Bfres.Structs
{
@ -748,16 +749,16 @@ namespace Bfres.Structs
keyGroup.AnimDataOffset = bn.Curves[curve].AnimDataOffset;
switch (keyGroup.AnimDataOffset)
{
case (int)TrackType.XPOS: bone.XPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YPOS: bone.YPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZPOS: bone.ZPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XROT: bone.XROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YROT: bone.YROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZROT: bone.ZROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.WROT: bone.WROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XSCA: bone.XSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YSCA: bone.YSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZSCA: bone.ZSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XPOS: bone.XPOS = keyGroup; break;
case (int)TrackType.YPOS: bone.YPOS = keyGroup; break;
case (int)TrackType.ZPOS: bone.ZPOS = keyGroup; break;
case (int)TrackType.XROT: bone.XROT = keyGroup; break;
case (int)TrackType.YROT: bone.YROT = keyGroup; break;
case (int)TrackType.ZROT: bone.ZROT = keyGroup; break;
case (int)TrackType.WROT: bone.WROT = keyGroup; break;
case (int)TrackType.XSCA: bone.XSCA = keyGroup; break;
case (int)TrackType.YSCA: bone.YSCA = keyGroup; break;
case (int)TrackType.ZSCA: bone.ZSCA = keyGroup; break;
default: throw new Exception("Unknown Anim Offset " + keyGroup.AnimDataOffset);
}
}
@ -811,16 +812,16 @@ namespace Bfres.Structs
keyGroup.AnimDataOffset = bn.Curves[curve].AnimDataOffset;
switch (keyGroup.AnimDataOffset)
{
case (int)TrackType.XPOS: bone.XPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YPOS: bone.YPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZPOS: bone.ZPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XROT: bone.XROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YROT: bone.YROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZROT: bone.ZROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.WROT: bone.WROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XSCA: bone.XSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YSCA: bone.YSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZSCA: bone.ZSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XPOS: bone.XPOS = keyGroup; break;
case (int)TrackType.YPOS: bone.YPOS = keyGroup; break;
case (int)TrackType.ZPOS: bone.ZPOS = keyGroup; break;
case (int)TrackType.XROT: bone.XROT = keyGroup; break;
case (int)TrackType.YROT: bone.YROT = keyGroup; break;
case (int)TrackType.ZROT: bone.ZROT = keyGroup; break;
case (int)TrackType.WROT: bone.WROT = keyGroup; break;
case (int)TrackType.XSCA: bone.XSCA = keyGroup; break;
case (int)TrackType.YSCA: bone.YSCA = keyGroup; break;
case (int)TrackType.ZSCA: bone.ZSCA = keyGroup; break;
default: throw new Exception("Unknown Anim Offset " + keyGroup.AnimDataOffset);
}
}

View File

@ -85,7 +85,7 @@ namespace Bfres.Structs
{
int index = (int)SamplerInfo.CurveIndex;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matanim.Curves[index]);
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matanim.Curves[index], true);
sampler.AnimDataOffset = matanim.Curves[index].AnimDataOffset;
sampler.Keys = keyGroup.Keys;

View File

@ -1534,7 +1534,9 @@ namespace FirstPlugin
//Max mip level will be set automatically unless overwritten
//The tex format can be adjusted in the function if necessary. Will normally be set to format in settings
public void Replace(string FileName, uint MaxMipLevel = 0, uint ArrayIndex = 0, TEX_FORMAT DefaultFormat = TEX_FORMAT.BC1_UNORM_SRGB, SurfaceDim surfaceDim = SurfaceDim.Dim2D)
public void Replace(string FileName, uint MaxMipLevel = 0, uint ArrayIndex = 0,
TEX_FORMAT DefaultFormat = TEX_FORMAT.BC1_UNORM_SRGB, SurfaceDim surfaceDim = SurfaceDim.Dim2D,
int alignment = 512)
{
Console.WriteLine("surfaceDim" + surfaceDim);
@ -1545,6 +1547,9 @@ namespace FirstPlugin
BinaryTextureImporterList importer = new BinaryTextureImporterList();
setting.SurfaceDim = surfaceDim;
setting.Alignment = alignment;
//Check if alignment is required for combining individual levels or not
setting.CombineMipLevel = alignment != 0 ? true : false;
var ImageDataCached = new List<List<byte[]>>();
if (Texture != null && Texture.TextureData != null)

View File

@ -244,7 +244,7 @@ namespace FirstPlugin
writer.Write((byte)mip);
writer.Write((byte)1);
var surface = Zstb.SCompress(ImageList[array][mip]);
var surface = Zstb.SCompress(ImageList[array][mip], 20);
surfaceSizes.Add((uint)surface.Length);
surfaceData.Add(surface);
@ -293,7 +293,7 @@ namespace FirstPlugin
{
//Replace the data using an instance of a switch texture
var tex = new TextureData();
tex.Replace(FileName, MipCount, 0, Format);
tex.Replace(FileName, MipCount, 0, Format, Syroot.NintenTools.NSW.Bntx.GFX.SurfaceDim.Dim2D, 1);
//Get swappable array level
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
@ -310,6 +310,9 @@ namespace FirstPlugin
if (tex.Texture == null)
return;
for (int i = 0; i < ImageList[0].Count; i++)
Console.WriteLine($"SIZE 1 mip{i} {ImageList[0][i].Length}");
//Ensure the format matches if image requires multiple surface levels
if (ImageList.Count > 1 && this.Format != tex.Format)
throw new Exception($"Imported texture must use the original format for surface injecting! Expected {this.Format} but got {tex.Format}! If you need ASTC, use an astc encoder with .astc file format.");
@ -326,6 +329,10 @@ namespace FirstPlugin
ImageList.Add(surface);
}
for (int i = 0; i < ImageList[0].Count; i++)
Console.WriteLine($"SIZE 2 mip{i} {ImageList[0][i].Length}");
Width = tex.Texture.Width;
Height = tex.Texture.Height;
MipCount = tex.Texture.MipCount;
@ -363,6 +370,7 @@ namespace FirstPlugin
{ 0x203, TEX_FORMAT.BC1_UNORM_SRGB },
{ 0x302, TEX_FORMAT.BC1_UNORM },
{ 0x606, TEX_FORMAT.BC4_UNORM },
{ 0x607, TEX_FORMAT.BC4_UNORM },
{ 0x702, TEX_FORMAT.BC5_UNORM },
{ 0x703, TEX_FORMAT.BC5_UNORM },
{ 0x707, TEX_FORMAT.BC5_UNORM },

View File

@ -1557,6 +1557,7 @@
<Compile Include="FileFormats\Texture\NUTEXB.cs" />
<Compile Include="FileFormats\Texture\TexConv.cs" />
<Compile Include="FileFormats\Texture\XTX.cs" />
<Compile Include="FileFormats\Texture\TXTG.cs" />
<Compile Include="FileFormats\Rom\XCI.cs" />
<Compile Include="GetSwitchKeys.cs" />
<Compile Include="GL\BFRES\BFRES_Render.cs" />

View File

@ -821,8 +821,8 @@ namespace FirstPlugin
{
if (mat.shaderassign.options.ContainsKey(propertyName))
{
float value = float.Parse(mat.shaderassign.options[propertyName]);
shader.SetFloat(propertyName, value);
//float value = float.Parse(mat.shaderassign.options[propertyName]);
//shader.SetFloat(propertyName, value);
}
Dictionary<string, BfresShaderParam> matParams = mat.matparam;

View File

@ -61,6 +61,8 @@
this.chkBoxFlipUvsY = new Toolbox.Library.Forms.STCheckBox();
this.chkBoxImportBones = new Toolbox.Library.Forms.STCheckBox();
this.panel8 = new Toolbox.Library.Forms.STPanel();
this.stLabel4 = new Toolbox.Library.Forms.STLabel();
this.lodCountUD = new Toolbox.Library.Forms.NumericUpDownUint();
this.chkCreateDummyLODs = new Toolbox.Library.Forms.STCheckBox();
this.stLabel3 = new Toolbox.Library.Forms.STLabel();
this.gamePresetCB = new Toolbox.Library.Forms.STComboBox();
@ -103,8 +105,6 @@
this.stCheckBox1 = new Toolbox.Library.Forms.STCheckBox();
this.chkMapOriginalMaterials = new Toolbox.Library.Forms.STCheckBox();
this.ogSkinCountChkBox = new Toolbox.Library.Forms.STCheckBox();
this.lodCountUD = new Toolbox.Library.Forms.NumericUpDownUint();
this.stLabel4 = new Toolbox.Library.Forms.STLabel();
this.contentContainer.SuspendLayout();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
@ -114,6 +114,7 @@
this.panel6.SuspendLayout();
this.panel7.SuspendLayout();
this.panel8.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.lodCountUD)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.panel9.SuspendLayout();
this.tabControl1.SuspendLayout();
@ -121,7 +122,6 @@
this.tabPageAdvanced.SuspendLayout();
this.stPanel1.SuspendLayout();
this.tabPage1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.lodCountUD)).BeginInit();
this.SuspendLayout();
//
// contentContainer
@ -492,6 +492,27 @@
this.panel8.Size = new System.Drawing.Size(524, 341);
this.panel8.TabIndex = 11;
//
// stLabel4
//
this.stLabel4.AutoSize = true;
this.stLabel4.Location = new System.Drawing.Point(237, 291);
this.stLabel4.Name = "stLabel4";
this.stLabel4.Size = new System.Drawing.Size(63, 13);
this.stLabel4.TabIndex = 39;
this.stLabel4.Text = "LOD Count:";
//
// lodCountUD
//
this.lodCountUD.Location = new System.Drawing.Point(319, 289);
this.lodCountUD.Maximum = new decimal(new int[] {
2147483647,
0,
0,
0});
this.lodCountUD.Name = "lodCountUD";
this.lodCountUD.Size = new System.Drawing.Size(120, 20);
this.lodCountUD.TabIndex = 38;
//
// chkCreateDummyLODs
//
this.chkCreateDummyLODs.AutoSize = true;
@ -582,6 +603,7 @@
this.chkBoxRotNegative90Y.Text = "Rotate -90 degrees";
this.chkBoxRotNegative90Y.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.chkBoxRotNegative90Y.UseVisualStyleBackColor = true;
this.chkBoxRotNegative90Y.CheckedChanged += new System.EventHandler(this.chkBoxSettings_CheckedChanged);
//
// textBoxMaterialPath
//
@ -814,7 +836,7 @@
this.tabPageAdvanced.Location = new System.Drawing.Point(4, 25);
this.tabPageAdvanced.Name = "tabPageAdvanced";
this.tabPageAdvanced.Padding = new System.Windows.Forms.Padding(3);
this.tabPageAdvanced.Size = new System.Drawing.Size(530, 333);
this.tabPageAdvanced.Size = new System.Drawing.Size(530, 347);
this.tabPageAdvanced.TabIndex = 0;
this.tabPageAdvanced.Text = "Advanced Settings";
//
@ -831,7 +853,7 @@
this.stPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.stPanel1.Location = new System.Drawing.Point(3, 3);
this.stPanel1.Name = "stPanel1";
this.stPanel1.Size = new System.Drawing.Size(524, 327);
this.stPanel1.Size = new System.Drawing.Size(524, 341);
this.stPanel1.TabIndex = 17;
//
// tabPage1
@ -848,7 +870,7 @@
this.tabPage1.Location = new System.Drawing.Point(4, 25);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(530, 333);
this.tabPage1.Size = new System.Drawing.Size(530, 347);
this.tabPage1.TabIndex = 2;
this.tabPage1.Text = "Inject Mode";
this.tabPage1.UseVisualStyleBackColor = true;
@ -959,27 +981,6 @@
this.ogSkinCountChkBox.Text = "Keep Original Skin Count (can help crashes)";
this.ogSkinCountChkBox.UseVisualStyleBackColor = true;
//
// lodCountUD
//
this.lodCountUD.Location = new System.Drawing.Point(319, 289);
this.lodCountUD.Maximum = new decimal(new int[] {
2147483647,
0,
0,
0});
this.lodCountUD.Name = "lodCountUD";
this.lodCountUD.Size = new System.Drawing.Size(120, 20);
this.lodCountUD.TabIndex = 38;
//
// stLabel4
//
this.stLabel4.AutoSize = true;
this.stLabel4.Location = new System.Drawing.Point(237, 291);
this.stLabel4.Name = "stLabel4";
this.stLabel4.Size = new System.Drawing.Size(63, 13);
this.stLabel4.TabIndex = 39;
this.stLabel4.Text = "LOD Count:";
//
// BfresModelImportSettings
//
this.ClientSize = new System.Drawing.Size(547, 412);
@ -1003,6 +1004,7 @@
this.panel7.PerformLayout();
this.panel8.ResumeLayout(false);
this.panel8.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.lodCountUD)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.panel9.ResumeLayout(false);
this.panel9.PerformLayout();
@ -1012,7 +1014,6 @@
this.stPanel1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.lodCountUD)).EndInit();
this.ResumeLayout(false);
}

View File

@ -492,10 +492,12 @@ namespace FirstPlugin
int assimpIndex = assimpMeshListView.SelectedIndices[0];
if (objectNameTB.Text == originalMeshListView.Items[assimpIndex].Text)
objectNameTB.BackColor = System.Drawing.Color.Green;
else
objectNameTB.BackColor = System.Drawing.Color.DarkRed;
objectNameTB.BackColor = System.Drawing.Color.DarkRed;
foreach (ListViewItem item in originalMeshListView.Items)
{
if (objectNameTB.Text == item.Text)
objectNameTB.BackColor = System.Drawing.Color.Green;
}
NewMeshlist[assimpIndex].ObjectName = objectNameTB.Text;
}

View File

@ -28,17 +28,66 @@
/// </summary>
private void InitializeComponent()
{
this.chkFilterDefaults = new Toolbox.Library.Forms.STCheckBox();
this.shaderOptionsListView = new Toolbox.Library.Forms.STListView();
this.ovlColumn1 = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.ovlColumn2 = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.btnScrolDown = new Toolbox.Library.Forms.STButton();
this.btnScrollUp = new Toolbox.Library.Forms.STButton();
this.btnEdit = new Toolbox.Library.Forms.STButton();
this.btnRemove = new Toolbox.Library.Forms.STButton();
this.btnAdd = new Toolbox.Library.Forms.STButton();
this.shaderOptionsListView = new Toolbox.Library.Forms.STListView();
this.ovlColumn1 = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.ovlColumn2 = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
((System.ComponentModel.ISupportInitialize)(this.shaderOptionsListView)).BeginInit();
this.SuspendLayout();
//
// chkFilterDefaults
//
this.chkFilterDefaults.AutoSize = true;
this.chkFilterDefaults.Checked = true;
this.chkFilterDefaults.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkFilterDefaults.Location = new System.Drawing.Point(165, 7);
this.chkFilterDefaults.Name = "chkFilterDefaults";
this.chkFilterDefaults.Size = new System.Drawing.Size(120, 17);
this.chkFilterDefaults.TabIndex = 31;
this.chkFilterDefaults.Text = "Filter Default Values";
this.chkFilterDefaults.UseVisualStyleBackColor = true;
this.chkFilterDefaults.CheckedChanged += new System.EventHandler(this.chkFilterDefaults_CheckedChanged);
//
// shaderOptionsListView
//
this.shaderOptionsListView.AllColumns.Add(this.ovlColumn1);
this.shaderOptionsListView.AllColumns.Add(this.ovlColumn2);
this.shaderOptionsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.shaderOptionsListView.CellEditUseWholeCell = false;
this.shaderOptionsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.ovlColumn1,
this.ovlColumn2});
this.shaderOptionsListView.Cursor = System.Windows.Forms.Cursors.Default;
this.shaderOptionsListView.HideSelection = false;
this.shaderOptionsListView.Location = new System.Drawing.Point(3, 32);
this.shaderOptionsListView.Name = "shaderOptionsListView";
this.shaderOptionsListView.ShowGroups = false;
this.shaderOptionsListView.Size = new System.Drawing.Size(449, 400);
this.shaderOptionsListView.TabIndex = 30;
this.shaderOptionsListView.UseCompatibleStateImageBehavior = false;
this.shaderOptionsListView.View = System.Windows.Forms.View.Details;
this.shaderOptionsListView.SelectedIndexChanged += new System.EventHandler(this.shaderOptionsListView_SelectedIndexChanged);
this.shaderOptionsListView.DoubleClick += new System.EventHandler(this.shaderOptionsListView_DoubleClick);
//
// ovlColumn1
//
this.ovlColumn1.AspectName = "Name";
this.ovlColumn1.Text = "Name";
this.ovlColumn1.Width = 170;
//
// ovlColumn2
//
this.ovlColumn2.AspectName = "Value";
this.ovlColumn2.Text = "Value";
this.ovlColumn2.Width = 385;
//
// btnScrolDown
//
this.btnScrolDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
@ -97,45 +146,11 @@
this.btnAdd.UseVisualStyleBackColor = true;
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// shaderOptionsListView
//
this.shaderOptionsListView.AllColumns.Add(this.ovlColumn1);
this.shaderOptionsListView.AllColumns.Add(this.ovlColumn2);
this.shaderOptionsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.shaderOptionsListView.CellEditUseWholeCell = false;
this.shaderOptionsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.ovlColumn1,
this.ovlColumn2});
this.shaderOptionsListView.Cursor = System.Windows.Forms.Cursors.Default;
this.shaderOptionsListView.Location = new System.Drawing.Point(3, 32);
this.shaderOptionsListView.Name = "shaderOptionsListView";
this.shaderOptionsListView.ShowGroups = false;
this.shaderOptionsListView.Size = new System.Drawing.Size(449, 400);
this.shaderOptionsListView.TabIndex = 30;
this.shaderOptionsListView.UseCompatibleStateImageBehavior = false;
this.shaderOptionsListView.View = System.Windows.Forms.View.Details;
this.shaderOptionsListView.SelectedIndexChanged += new System.EventHandler(this.shaderOptionsListView_SelectedIndexChanged);
this.shaderOptionsListView.DoubleClick += new System.EventHandler(this.shaderOptionsListView_DoubleClick);
//
// ovlColumn1
//
this.ovlColumn1.AspectName = "Name";
this.ovlColumn1.HeaderForeColor = System.Drawing.Color.Empty;
this.ovlColumn1.Text = "Name";
this.ovlColumn1.Width = 170;
//
// ovlColumn2
//
this.ovlColumn2.AspectName = "Value";
this.ovlColumn2.Text = "Value";
this.ovlColumn2.Width = 385;
//
// ShaderOptionsEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.chkFilterDefaults);
this.Controls.Add(this.shaderOptionsListView);
this.Controls.Add(this.btnScrolDown);
this.Controls.Add(this.btnScrollUp);
@ -146,6 +161,7 @@
this.Size = new System.Drawing.Size(496, 435);
((System.ComponentModel.ISupportInitialize)(this.shaderOptionsListView)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -159,5 +175,6 @@
private Toolbox.Library.Forms.STListView shaderOptionsListView;
private BrightIdeasSoftware.OLVColumn ovlColumn1;
private BrightIdeasSoftware.OLVColumn ovlColumn2;
private Toolbox.Library.Forms.STCheckBox chkFilterDefaults;
}
}

View File

@ -14,6 +14,8 @@ namespace FirstPlugin.Forms
{
public partial class ShaderOptionsEditor : UserControl
{
private bool FilterDefaults => chkFilterDefaults.Checked;
public ShaderOptionsEditor()
{
InitializeComponent();
@ -47,7 +49,12 @@ namespace FirstPlugin.Forms
shaderOptionsListView.ForeColor = FormThemes.BaseTheme.FormForeColor;
foreach (var option in material.shaderassign.options)
{
if (FilterDefaults && option.Value == "<Default Value>")
continue;
options.Add(new Options() { Name = option.Key, Value = option.Value });
}
shaderOptionsListView.SetObjects(options);
options.Clear();
@ -140,5 +147,10 @@ namespace FirstPlugin.Forms
}
}
}
private void chkFilterDefaults_CheckedChanged(object sender, EventArgs e)
{
InitializeShaderOptionList(material);
}
}
}

View File

@ -41,6 +41,7 @@
this.stLabel5 = new Toolbox.Library.Forms.STLabel();
this.stLabel4 = new Toolbox.Library.Forms.STLabel();
this.stLabel3 = new Toolbox.Library.Forms.STLabel();
this.textBox1 = new System.Windows.Forms.TextBox();
this.stFlowLayoutPanel1.SuspendLayout();
this.stDropDownPanel1.SuspendLayout();
this.stDropDownPanel2.SuspendLayout();
@ -51,7 +52,10 @@
this.stFlowLayoutPanel1.AutoScroll = true;
this.stFlowLayoutPanel1.Controls.Add(this.stDropDownPanel1);
this.stFlowLayoutPanel1.Controls.Add(this.stDropDownPanel2);
this.stFlowLayoutPanel1.Controls.Add(this.textBox1);
this.stFlowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.stFlowLayoutPanel1.FixedHeight = false;
this.stFlowLayoutPanel1.FixedWidth = true;
this.stFlowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.stFlowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.stFlowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
@ -75,8 +79,8 @@
this.stDropDownPanel1.PanelName = "Skeleton Info";
this.stDropDownPanel1.PanelValueName = "";
this.stDropDownPanel1.SetIcon = null;
this.stDropDownPanel1.SetIconAlphaColor = System.Drawing.Color.Empty;
this.stDropDownPanel1.SetIconColor = System.Drawing.Color.Empty;
this.stDropDownPanel1.SetIconAlphaColor = System.Drawing.Color.White;
this.stDropDownPanel1.SetIconColor = System.Drawing.Color.White;
this.stDropDownPanel1.Size = new System.Drawing.Size(434, 108);
this.stDropDownPanel1.TabIndex = 0;
//
@ -86,6 +90,7 @@
this.scalingModeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid;
this.scalingModeCB.ButtonColor = System.Drawing.Color.Empty;
this.scalingModeCB.FormattingEnabled = true;
this.scalingModeCB.IsReadOnly = false;
this.scalingModeCB.Location = new System.Drawing.Point(114, 64);
this.scalingModeCB.Name = "scalingModeCB";
this.scalingModeCB.Size = new System.Drawing.Size(172, 21);
@ -107,6 +112,7 @@
this.rotationModeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid;
this.rotationModeCB.ButtonColor = System.Drawing.Color.Empty;
this.rotationModeCB.FormattingEnabled = true;
this.rotationModeCB.IsReadOnly = false;
this.rotationModeCB.Location = new System.Drawing.Point(114, 37);
this.rotationModeCB.Name = "rotationModeCB";
this.rotationModeCB.Size = new System.Drawing.Size(172, 21);
@ -139,8 +145,8 @@
this.stDropDownPanel2.PanelName = "Matricies";
this.stDropDownPanel2.PanelValueName = "";
this.stDropDownPanel2.SetIcon = null;
this.stDropDownPanel2.SetIconAlphaColor = System.Drawing.Color.Empty;
this.stDropDownPanel2.SetIconColor = System.Drawing.Color.Empty;
this.stDropDownPanel2.SetIconAlphaColor = System.Drawing.Color.White;
this.stDropDownPanel2.SetIconColor = System.Drawing.Color.White;
this.stDropDownPanel2.Size = new System.Drawing.Size(434, 182);
this.stDropDownPanel2.TabIndex = 5;
//
@ -200,6 +206,19 @@
this.stLabel3.TabIndex = 5;
this.stLabel3.Text = "Smooth Matrix Indices";
//
// textBox1
//
this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.textBox1.Location = new System.Drawing.Point(3, 293);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(428, 332);
this.textBox1.TabIndex = 13;
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
//
// FSKLEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -209,6 +228,7 @@
this.Name = "FSKLEditor";
this.Size = new System.Drawing.Size(434, 628);
this.stFlowLayoutPanel1.ResumeLayout(false);
this.stFlowLayoutPanel1.PerformLayout();
this.stDropDownPanel1.ResumeLayout(false);
this.stDropDownPanel1.PerformLayout();
this.stDropDownPanel2.ResumeLayout(false);
@ -232,5 +252,6 @@
private Toolbox.Library.Forms.STLabel stLabel5;
private Toolbox.Library.Forms.STLabel stLabel4;
private Toolbox.Library.Forms.STLabel stLabel3;
private System.Windows.Forms.TextBox textBox1;
}
}

View File

@ -23,6 +23,9 @@ namespace FirstPlugin.Forms
BackColor = FormThemes.BaseTheme.FormBackColor;
ForeColor = FormThemes.BaseTheme.FormForeColor;
textBox1.BackColor = FormThemes.BaseTheme.ListViewBackColor;
textBox1.ForeColor = FormThemes.BaseTheme.FormForeColor;
}
public FSKL activeSkeleton;
@ -61,6 +64,12 @@ namespace FirstPlugin.Forms
scalingModeCB.SelectedItem = fskl.node.Skeleton.FlagsScaling;
}
if (fskl.node.Skeleton != null && fskl.node.Skeleton.userIndices != null)
{
var indices = string.Join(",", fskl.node.Skeleton.userIndices);
this.textBox1.Text = indices;
}
IsLoaded = true;
}
@ -129,5 +138,23 @@ namespace FirstPlugin.Forms
}
LibraryGUI.UpdateViewport();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (activeSkeleton.node.Skeleton != null)
{
List<ushort> indices = new List<ushort>();
foreach (var line in textBox1.Text.Split(','))
{
if (string.IsNullOrEmpty(line))
continue;
if (ushort.TryParse(line, out ushort id))
indices.Add(id);
}
activeSkeleton.node.Skeleton.userIndices = indices.ToArray();
}
}
}
}

View File

@ -22,6 +22,8 @@ namespace FirstPlugin
{
}
public bool CombineMipLevel = true;
public int Alignment = 512;
public bool GammaFix = false;
public string TexName;
public AccessFlags AccessFlags = AccessFlags.Texture;
@ -279,17 +281,20 @@ namespace FirstPlugin
for (int i = 0; i < arrayFaces.Count; i++)
{
List<byte[]> mipmaps = SwizzleSurfaceMipMaps(tex, arrayFaces[i], tex.MipCount);
List<byte[]> mipmaps = SwizzleSurfaceMipMaps(tex, arrayFaces[i], tex.MipCount, settings.Alignment);
tex.TextureData.Add(mipmaps);
//Combine mip map data
byte[] combinedMips = Utils.CombineByteArray(mipmaps.ToArray());
tex.TextureData[i][0] = combinedMips;
if (settings.Alignment != 1)
{
byte[] combinedMips = Utils.CombineByteArray(mipmaps.ToArray());
tex.TextureData[i][0] = combinedMips;
}
}
return tex;
}
public static List<byte[]> SwizzleSurfaceMipMaps(Texture tex, byte[] data, uint MipCount)
public static List<byte[]> SwizzleSurfaceMipMaps(Texture tex, byte[] data, uint MipCount, int alignment = 512)
{
var TexFormat = TextureData.ConvertFormat(tex.Format);
@ -319,7 +324,7 @@ namespace FirstPlugin
{
blockHeight = TegraX1Swizzle.GetBlockHeight(DIV_ROUND_UP(tex.Height, blkHeight));
tex.BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
tex.Alignment = 512;
tex.Alignment = alignment;
tex.ReadTextureLayout = 1;
linesPerBlockHeight = blockHeight * 8;
@ -346,6 +351,9 @@ namespace FirstPlugin
byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, (uint)tex.Alignment) - SurfaceSize)];
if (tex.Alignment == 1)
AlignedData = new byte[0];
SurfaceSize += (uint)AlignedData.Length;
// Console.WriteLine("SurfaceSize Aligned " + AlignedData);
@ -372,8 +380,10 @@ namespace FirstPlugin
SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);
}
byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, depth_, blkWidth, blkHeight, blkDepth, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), data_);
byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, depth_, blkWidth, blkHeight, blkDepth, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), data_, size);
mipmaps.Add(AlignedData.Concat(SwizzledData).ToArray());
Console.WriteLine("SwizzledData " + SwizzledData.Length);
}
tex.ImageSize = SurfaceSize;

View File

@ -462,7 +462,9 @@ namespace FirstPlugin
Formats.Add(typeof(NKN));
Formats.Add(typeof(MetroidDreadLibrary.BSMAT));
Formats.Add(typeof(TRANM));
Formats.Add(typeof(GFA));
Formats.Add(typeof(TXTG));
//Formats.Add(typeof(XLINK_FILE));
// Formats.Add(typeof(MPBIN));
@ -478,7 +480,6 @@ namespace FirstPlugin
if (Runtime.DEVELOPER_DEBUG_MODE)
{
Formats.Add(typeof(BFSAR));
Formats.Add(typeof(GFA));
}

View File

@ -299,46 +299,56 @@ namespace Toolbox.Library.Animations
return false;
}
int LastFound = 0;
float LastFrame;
public float GetValue(float frame)
private float GetWrapFrame(float frame)
{
if (Keys.Count == 0)
return 0;
var lastFrame = Keys.Last().Frame;
if (frame < 0 || lastFrame < 0)
return frame;
float startFrame = Keys.First().Frame;
return frame;
}
public virtual float GetValue(float frame, float startFrame = 0)
{
if (Keys.Count == 0) return 0;
if (Keys.Count == 1) return Keys[0].Value;
KeyFrame LK = Keys.First();
KeyFrame RK = Keys.Last();
float Frame = GetWrapFrame(frame - startFrame);
foreach (KeyFrame keyFrame in Keys)
{
if (keyFrame.Frame <= frame) LK = keyFrame;
if (keyFrame.Frame >= frame && keyFrame.Frame < RK.Frame) RK = keyFrame;
if (keyFrame.Frame <= Frame) LK = keyFrame;
if (keyFrame.Frame >= Frame && keyFrame.Frame < RK.Frame) RK = keyFrame;
}
if (LK == RK)
return LK.Value;
if (LK.Frame != RK.Frame)
return GetInterpolatedValue(Frame, LK, RK);
}
private float GetInterpolatedValue(float Frame, KeyFrame LK, KeyFrame RK)
{
float FrameDiff = Frame - LK.Frame;
float Weight = FrameDiff / (RK.Frame - LK.Frame);
switch (InterpolationType)
{
// float FrameDiff = frame - LK.Frame;
// float Weight = 1.0f / (RK.Frame - LK.Frame);
// float Weight = FrameDiff / (RK.Frame - LK.Frame);
case InterpolationType.CONSTANT: return LK.Value;
case InterpolationType.STEP: return LK.Value;
case InterpolationType.LINEAR: return InterpolationHelper.Lerp(LK.Value, RK.Value, Weight);
case InterpolationType.HERMITE:
float length = RK.Frame - LK.Frame;
float FrameDiff = frame - LK.Frame;
float Weight = FrameDiff / (RK.Frame - LK.Frame);
Console.WriteLine($"frame diff {FrameDiff} frame {frame} LK {LK.Frame} RK {RK} ratio {Weight}");
switch (InterpolationType)
{
case InterpolationType.CONSTANT: return LK.Value;
case InterpolationType.STEP: return LK.Value;
case InterpolationType.LINEAR: return InterpolationHelper.Lerp(LK.Value, RK.Value, Weight);
case InterpolationType.HERMITE:
float val = Hermite(frame, LK.Frame, RK.Frame, LK.In, LK.Out != -1 ? LK.Out : RK.In, LK.Value, RK.Value);
return val;
}
return InterpolationHelper.HermiteInterpolate(Frame,
LK.Frame,
RK.Frame,
LK.Value,
RK.Value,
LK.Out * length,
RK.In * length);
}
return LK.Value;
}
@ -508,7 +518,7 @@ namespace Toolbox.Library.Animations
float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.EulerRotation.X;
float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.EulerRotation.Y;
float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.EulerRotation.Z;
b.rot = EulerToQuat(z, y, x);
b.rot = STMath.FromEulerAngles(new Vector3(x, y, z));
}
}
}
@ -558,16 +568,37 @@ namespace Toolbox.Library.Animations
// return (((cf0 * t + cf1) * t + cf2) * t + cf3);
}
public static float Hermite(float frame, float frame1, float frame2, float outSlope, float inSlope, float val1, float val2)
public static float HermiteInterpolate(float frame, float frame1, float frame2,
float inSlope, float outSlope, float p0, float p1)
{
if (frame == frame1) return val1;
if (frame == frame2) return val2;
if (frame == frame1) return p0;
if (frame == frame2) return p1;
float distance = frame - frame1;
float invDuration = 1f / (frame2 - frame1);
float t = distance * invDuration;
float t1 = t - 1f;
return (val1 + ((((val1 - val2) * ((2f * t) - 3f)) * t) * t)) + ((distance * t1) * ((t1 * outSlope) + (t * inSlope)));
float t = (frame - frame1) / (frame2 - frame1);
return GetPointHermite(p0, p1, outSlope, inSlope, t);
}
private static float GetPointHermite(float p0, float p1, float s0, float s1, float t)
{
float cf0 = (p0 * 2) + (p1 * -2) + (s0 * 1) + (s1 * 1);
float cf1 = (p0 * -3) + (p1 * 3) + (s0 * -2) + (s1 * -1);
float cf2 = (p0 * 0) + (p1 * 0) + (s0 * 1) + (s1 * 0);
float cf3 = (p0 * 1) + (p1 * 0) + (s0 * 0) + (s1 * 0);
return GetPointCubic(cf0, cf1, cf2, cf3, t);
}
private static float GetPointBezier(float p0, float p1, float p2, float p3, float t)
{
float cf0 = (p0 * -1) + (p1 * 3) + (p2 * -3) + (p3 * 1);
float cf1 = (p0 * 3) + (p1 * -6) + (p2 * 3) + (p3 * 0);
float cf2 = (p0 * -3) + (p1 * 3) + (p2 * 0) + (p3 * 0);
float cf3 = (p0 * 1) + (p1 * 0) + (p2 * 0) + (p3 * 0);
return GetPointCubic(cf0, cf1, cf2, cf3, t);
}
private static float GetPointCubic(float cf0, float cf1, float cf2, float cf3, float t)
{
return (((cf0 * t + cf1) * t + cf2) * t + cf3);
}
public static float Lerp(float av, float bv, float v0, float v1, float t)

View File

@ -23,27 +23,40 @@ namespace Toolbox.Library.Animations
return Result;
}
public static float BezierInterpolate(float frame, float frame1, float frame2,
float inSlope, float outSlope, float p0, float p1)
public static float BezierInterpolate(float frame, float FrameL, float frameR,
float inSlope, float outSlope, float p0, float p1)
{
if (frame == frame1) return p0;
if (frame == frame2) return p1;
if (frame == FrameL) return p0;
if (frame == frameR) return p1;
float t = (frame - frame1) / (frame2 - frame1);
return GetPointBezier(p0, p1, outSlope, inSlope, t);
float t = (frame - FrameL) / (frameR - FrameL);
return GetPointBezier(p0, p1, inSlope, outSlope, t);
}
public static float CubicHermiteInterpolate(float frame, float FrameL, float frameR,
float cf0, float cf1, float cf2, float cf3)
{
float t = (frame - FrameL) / (frameR - FrameL);
return GetPointCubic(cf3, cf2, cf1, cf0, t);
}
private static float GetPointCubic(float cf0, float cf1, float cf2, float cf3, float t)
{
return (((cf0 * t + cf1) * t + cf2) * t + cf3);
}
public static float HermiteInterpolate(float frame, float frame1, float frame2,
float inSlope, float outSlope, float p0, float p1)
float p0, float p1, float s0, float s1)
{
if (frame == frame1) return p0;
if (frame == frame2) return p1;
float t = (frame - frame1) / (frame2 - frame1);
return GetPointHermite(p0, p1, outSlope, inSlope, t);
return GetPointHermite(p0, p1, s0, s1, t);
}
private static float GetPointHermite(float p0, float p1, float s0, float s1, float t) {
private static float GetPointHermite(float p0, float p1, float s0, float s1, float t)
{
float cf0 = (p0 * 2) + (p1 * -2) + (s0 * 1) + (s1 * 1);
float cf1 = (p0 * -3) + (p1 * 3) + (s0 * -2) + (s1 * -1);
float cf2 = (p0 * 0) + (p1 * 0) + (s0 * 1) + (s1 * 0);
@ -51,7 +64,8 @@ namespace Toolbox.Library.Animations
return GetPointCubic(cf0, cf1, cf2, cf3, t);
}
private static float GetPointBezier(float p0, float p1, float p2, float p3, float t) {
private static float GetPointBezier(float p0, float p1, float p2, float p3, float t)
{
float cf0 = (p0 * -1) + (p1 * 3) + (p2 * -3) + (p3 * 1);
float cf1 = (p0 * 3) + (p1 * -6) + (p2 * 3) + (p3 * 0);
float cf2 = (p0 * -3) + (p1 * 3) + (p2 * 0) + (p3 * 0);
@ -59,11 +73,8 @@ namespace Toolbox.Library.Animations
return GetPointCubic(cf0, cf1, cf2, cf3, t);
}
private static float GetPointCubic(float cf0, float cf1, float cf2, float cf3, float t) {
return (((cf0 * t + cf1) * t + cf2) * t + cf3);
}
public static float[] CalculateCubicCoef(float frameA, float frameB, float valueA, float valueB, float inSlope, float outSlope) {
public static float[] CalculateCubicCoef(float frameA, float frameB, float valueA, float valueB, float inSlope, float outSlope)
{
return CalculateCubicCoef(frameB - frameA, valueA, valueB, inSlope, outSlope);
}

View File

@ -70,9 +70,9 @@ namespace Toolbox.Library
return decompressor.Unwrap(b, MaxDecompressedSize);
}
}
public static byte[] SCompress(byte[] b)
public static byte[] SCompress(byte[] b, int level = 5)
{
using (var compressor = new ZstdNet.Compressor())
using (var compressor = new ZstdNet.Compressor(new ZstdNet.CompressionOptions(level)))
{
return compressor.Wrap(b);
}

View File

@ -69,7 +69,7 @@ namespace Toolbox.Library.Animations
}
}
return Animation.Hermite (frame+1, f1.input, f2.input, weighted ? f1.t1 : 0, weighted ? f2.t1 : 0, f1.output, f2.output);
return Animation.HermiteInterpolate (frame+1, f1.input, f2.input, weighted ? f1.t1 : 0, weighted ? f2.t1 : 0, f1.output, f2.output);
}
}

View File

@ -9,6 +9,9 @@ namespace Toolbox.Library
{
public static class STMath
{
public const float Deg2Rad = (float)System.Math.PI / 180.0f;
public const float Rad2Deg = 180.0f / (float)System.Math.PI;
private const long SizeOfKb = 1024;
private const long SizeOfMb = SizeOfKb * 1024;
private const long SizeOfGb = SizeOfMb * 1024;
@ -40,11 +43,13 @@ namespace Toolbox.Library
//From https://github.com/Ploaj/SSBHLib/blob/e37b0d83cd088090f7802be19b1d05ec998f2b6a/CrossMod/Tools/CrossMath.cs#L42
//Seems to give good results
public static Vector3 ToEulerAngles(double X, double Y, double Z, double W) {
public static Vector3 ToEulerAngles(double X, double Y, double Z, double W)
{
return ToEulerAngles(new Quaternion((float)X, (float)Y, (float)Z, (float)W));
}
public static Vector3 ToEulerAngles(float X, float Y, float Z, float W) {
public static Vector3 ToEulerAngles(float X, float Y, float Z, float W)
{
return ToEulerAngles(new Quaternion(X, Y, Z, W));
}
@ -80,6 +85,70 @@ namespace Toolbox.Library
return q;
}
public static Matrix4 RotationFromTo(Vector3 start, Vector3 end)
{
var axis = Vector3.Cross(start, end).Normalized();
var angle = (float)Math.Acos(Vector3.Dot(start, end));
return Matrix4.CreateFromAxisAngle(axis, angle);
}
public static Quaternion QuatRotationFromTo(Vector3 start, Vector3 end)
{
var axis = Vector3.Cross(start, end).Normalized();
var angle = (float)Math.Acos(Vector3.Dot(start, end));
return Quaternion.FromAxisAngle(axis, angle);
}
public static Vector3 GetEulerAngle(Matrix4 m)
{
float pitch, yaw, roll; // 3 angles
yaw = Rad2Deg * (float)Math.Asin(GetValue(m, 8));
if (GetValue(m, 10) < 0)
{
if (yaw >= 0) yaw = 180.0f - yaw;
else yaw = -180.0f - yaw;
}
// find roll (around z-axis) and pitch (around x-axis)
// if forward vector is (1,0,0) or (-1,0,0), then m[0]=m[4]=m[9]=m[10]=0
if (m.M11 > -double.Epsilon && m.M11 < double.Epsilon)
{
roll = 0; //@@ assume roll=0
pitch = Rad2Deg * (float)Math.Atan2(GetValue(m, 1), GetValue(m, 5));
}
else
{
roll = Rad2Deg * (float)Math.Atan2(-GetValue(m, 4), GetValue(m, 0));
pitch = Rad2Deg * (float)Math.Atan2(-GetValue(m, 9), GetValue(m, 10));
}
return new Vector3(pitch, yaw, roll) * Deg2Rad;
}
static float GetValue(Matrix4 mat, int index)
{
switch (index)
{
case 0: return mat.M11;
case 1: return mat.M12;
case 2: return mat.M13;
case 3: return mat.M14;
case 4: return mat.M21;
case 5: return mat.M22;
case 6: return mat.M23;
case 7: return mat.M24;
case 8: return mat.M31;
case 9: return mat.M32;
case 10: return mat.M33;
case 11: return mat.M34;
case 12: return mat.M41;
case 13: return mat.M42;
case 14: return mat.M43;
case 15: return mat.M44;
default:
throw new Exception("Invalid index for 4x4 matrix!");
}
}
public static float Clamp(float v, float min, float max)
{
if (v < min) return min;

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace Toolbox.Library
{
@ -104,6 +105,37 @@ namespace Toolbox.Library
return GetImageData(texture, ImageData, ArrayLevel, MipLevel, DepthLevel, BlockHeightLog2, target, LinearTileMode);
}
public static byte[] GetDirectImageData(STGenericTexture texture, byte[] ImageData, int mipLevel, int target = 1, bool LinearTileMode = false)
{
uint blkWidth = STGenericTexture.GetBlockWidth(texture.Format);
uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
uint blkDepth = STGenericTexture.GetBlockDepth(texture.Format);
var blockHeightMip0 = GetBlockHeight(DIV_ROUND_UP(texture.Height, blkHeight));
uint bpp = STGenericTexture.GetBytesPerPixel(texture.Format);
uint TileMode = LinearTileMode ? 1u : 0u;
uint width = Math.Max(1, texture.Width >> mipLevel);
uint height = Math.Max(1, texture.Height >> mipLevel);
uint depth = Math.Max(1, texture.Depth >> mipLevel);
uint heightInBlocks = DIV_ROUND_UP(height, blkHeight);
// tegra_swizzle only allows block heights supported by the TRM (1,2,4,8,16,32).
var mipBlockHeightLog2 = (int)Math.Log(GetMipBlockHeight(heightInBlocks, blockHeightMip0), 2);
try
{
byte[] result = deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, mipBlockHeightLog2, ImageData);
return result;
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {texture.Text}!");
Console.WriteLine(e);
return new byte[0];
}
}
public static byte[] GetImageData(STGenericTexture texture, byte[] ImageData, int ArrayLevel, int MipLevel, int DepthLevel, uint BlockHeightLog2, int target = 1, bool LinearTileMode = false)
{
uint bpp = STGenericTexture.GetBytesPerPixel(texture.Format);
@ -179,7 +211,7 @@ namespace Toolbox.Library
}
private static unsafe byte[] SwizzleDeswizzleBlockLinear(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth,
uint bpp, int blockHeightLog2, byte[] data, bool deswizzle)
uint bpp, int blockHeightLog2, byte[] data, bool deswizzle, uint size, uint alignment = 512)
{
// This function expects the surface dimensions in blocks rather than pixels for block compressed formats.
// This ensures the bytes per pixel parameter is used correctly.
@ -245,17 +277,17 @@ namespace Toolbox.Library
public static byte[] deswizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data)
{
if (tileMode == 1)
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, true);
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, true, 0);
else
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, true);
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, true, 0);
}
public static byte[] swizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data)
public static byte[] swizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data, uint size)
{
if (tileMode == 1)
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, false);
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, false, size);
else
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, false);
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, false, size);
}
@ -283,7 +315,7 @@ namespace Toolbox.Library
return x + 1;
}
private static byte[] SwizzlePitchLinear(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, int blockHeightLog2, byte[] data, bool deswizzle)
private static byte[] SwizzlePitchLinear(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, int blockHeightLog2, byte[] data, bool deswizzle, uint size)
{
// TODO: Investigate doing this more efficiently in Rust.
width = DIV_ROUND_UP(width, blkWidth);

View File

@ -439,6 +439,7 @@
<Compile Include="IO\Colors\STColor.cs" />
<Compile Include="IO\Colors\STColor8.cs" />
<Compile Include="IO\SubStream.cs" />
<Compile Include="Maths\STMath.cs" />
<Compile Include="OpenGL\GLShaderGeneric.cs" />
<Compile Include="OpenGL\IPickableObject.cs" />
<Compile Include="OpenGL\OpenGL2DEnums.cs" />
@ -872,7 +873,6 @@
<Compile Include="IO\Extensions\StreamReaderExtensions.cs" />
<Compile Include="IO\Extensions\StringExtension.cs" />
<Compile Include="IO\STStream.cs" />
<Compile Include="Maths\Math.cs" />
<Compile Include="Plugin\GenericPluginLoader.cs" />
<Compile Include="Forms\Animation\AnimationPanel.cs">
<SubType>UserControl</SubType>
@ -965,6 +965,7 @@
<Compile Include="Util\ImageUtilty.cs" />
<Compile Include="Util\OpenGLUtils.cs" />
<Compile Include="Util\Util.cs" />
<Compile Include="Util\WebUtil.cs" />
<Compile Include="XML\XmlDoc.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
namespace Toolbox.Library
{
public class WebUtil
{
public static void OpenDonation() {
OpenURLEncoded("aHR0cHM6Ly9rby1maS5jb20vc2ltcGx5a3hn");
}
public static void OpenURLEncoded(string encodedString)
{
byte[] data = Convert.FromBase64String(encodedString);
OpenURL(Encoding.UTF8.GetString(data));
}
public static void OpenURL(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); // Works ok on windows
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
Process.Start("xdg-open", url); // Works ok on linux
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
Process.Start("open", url); // Not tested
}
}
}
}

View File

@ -2013,7 +2013,7 @@
</member>
<member name="M:Syroot.NintenTools.NSW.Bfres.Core.ResFileLoader.ReadOffsets(System.Int32)">
<summary>
Reads BFRES offsets which is the absolute addresses.
Reads BFRES offsets which is the absolute addresses.+
</summary>
<param name="count">The number of offsets to read.</param>
<returns>The absolute addresses of the offsets.</returns>
@ -2275,7 +2275,7 @@
<param name="str">The name to save.</param>
<param name="encoding">The <see cref="T:System.Text.Encoding"/> in which the name will be stored.</param>
</member>
<member name="M:Syroot.NintenTools.NSW.Bfres.Core.ResFileSaver.SaveStrings(System.Collections.Generic.IEnumerable{System.String},System.Text.Encoding)">
<member name="M:Syroot.NintenTools.NSW.Bfres.Core.ResFileSaver.SaveStrings(System.Collections.Generic.IEnumerable{System.String},System.Boolean,System.Text.Encoding)">
<summary>
Reserves space for offsets to the <paramref name="strings"/> written later in the string pool with the
specified <paramref name="encoding"/>
@ -3160,6 +3160,11 @@
Gets or sets the <see cref="T:Syroot.NintenTools.NSW.Bfres.Material"/> instance applied on the <see cref="P:Syroot.NintenTools.NSW.Bfres.Model.Shapes"/> to color their surface.
</summary>
</member>
<member name="F:Syroot.NintenTools.NSW.Bfres.Model.ShaderAssigns">
<summary>
</summary>
</member>
<member name="P:Syroot.NintenTools.NSW.Bfres.Model.UserDataDict">
<summary>
Gets or sets customly attached <see cref="P:Syroot.NintenTools.NSW.Bfres.Model.UserData"/> names.
@ -3713,7 +3718,7 @@
rigidbodies (no skinning), 1 equal rigid skinning and 2 or more smooth skinning.
</summary>
</member>
<member name="P:Syroot.NintenTools.NSW.Bfres.VertexBuffer.VertexCount">
<member name="F:Syroot.NintenTools.NSW.Bfres.VertexBuffer.VertexCount">
<summary>
Gets the number of vertices stored by the <see cref="P:Syroot.NintenTools.NSW.Bfres.VertexBuffer.Buffers"/>. It is calculated from the size of the first
<see cref="!:Buffer"/> in bytes divided by the <see cref="P:Syroot.NintenTools.NSW.Bfres.VertexBuffer.StrideArray"/>.
@ -4850,6 +4855,16 @@
Gets or sets <see cref="T:Syroot.NintenTools.NSW.Bfres.AnimCurve"/> instances animating properties of objects stored in this section.
</summary>
</member>
<member name="P:Syroot.NintenTools.NSW.Bfres.BoneAnim.UserDataDict">
<summary>
Gets or sets customly attached <see cref="P:Syroot.NintenTools.NSW.Bfres.BoneAnim.UserData"/> names.
</summary>
</member>
<member name="P:Syroot.NintenTools.NSW.Bfres.BoneAnim.UserData">
<summary>
Gets or sets customly attached <see cref="P:Syroot.NintenTools.NSW.Bfres.BoneAnim.UserData"/> instances.
</summary>
</member>
<member name="P:Syroot.NintenTools.NSW.Bfres.BoneAnim.BaseData">
<summary>
Gets or sets initial transformation values. Only stores specific transformations according to
@ -5173,6 +5188,12 @@
Euler XYZ, 3 components.
</summary>
</member>
<member name="T:Syroot.NintenTools.NSW.Bfres.StringCache">
<summary>
A cache of strings that are saved through raw IDs in place of the pointer field of a name offset.
This is used and required for TOTK models.
</summary>
</member>
<member name="T:Syroot.NintenTools.NSW.Bfres.VisibilityAnim">
<summary>
Represents an FVIS subfile in a <see cref="T:Syroot.NintenTools.NSW.Bfres.ResFile"/>, storing visibility animations of <see cref="T:Syroot.NintenTools.NSW.Bfres.Bone"/> or

File diff suppressed because it is too large Load Diff