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

Chr0 animation importing, dae exporting and tons more improvements!

Chr0 can be imported/replaced.
More fixes to importing sections including some errors and proper filtering.
Dae epxorting now has a progress bar and an option to idsable texture exporting.
Bfska can now be swapped between platforms. More sections will handle this method soon!.
Fixed spaces on files from "Export All".
Display multiple texture maps in bcres materials
This commit is contained in:
KillzXGaming 2019-05-24 15:15:35 -04:00
parent 1498c83c44
commit 2a92afa122
42 changed files with 1340 additions and 114 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,552 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using ResU = Syroot.NintenTools.Bfres;
using System.Windows;
using Syroot.Maths;
using BrawlLib.SSBB.ResourceNodes;
namespace BrawlboxHelper
{
public class FSHUConverter
{
public static ResU.ShaderParamAnim Clr02Fshu(string FileName)
{
CLR0Node clr0 = NodeFactory.FromFile(null, FileName) as CLR0Node;
ResU.ShaderParamAnim fshu = new ResU.ShaderParamAnim();
fshu.FrameCount = clr0.FrameCount;
fshu.Name = clr0.Name;
fshu.Path = clr0.OriginalPath;
fshu.UserData = new ResU.ResDict<Syroot.NintenTools.Bfres.UserData>();
//Set flags
if (clr0.Loop)
fshu.Flags |= ResU.ShaderParamAnimFlags.Looping;
//Set mat anims and then calculate data after
foreach (var entry in clr0.Children)
fshu.ShaderParamMatAnims.Add(Clr0Entry2ShaderMatAnim(clr0, (CLR0MaterialNode)entry));
fshu.BakedSize = CalculateBakeSize(fshu);
fshu.BindIndices = SetIndices(fshu);
return fshu;
}
public static ResU.ShaderParamMatAnim Clr0Entry2ShaderMatAnim(CLR0Node clr0, CLR0MaterialNode clrMaterial)
{
ResU.ShaderParamMatAnim matAnim = new ResU.ShaderParamMatAnim();
matAnim.Name = clrMaterial.Name;
foreach (var entry in clrMaterial.Children)
{
ushort curveIndex = 0;
ushort constantIndex = 0;
CLR0MaterialEntryNode ParamEntry = (CLR0MaterialEntryNode)entry;
//Add constants for RGBA if constant
if (ParamEntry.Constant)
{
//Red
matAnim.Constants.Add(new ResU.AnimConstant()
{
AnimDataOffset = 0,
Value = (float)ParamEntry.Colors[0].R / 255f,
});
//Green
matAnim.Constants.Add(new ResU.AnimConstant()
{
AnimDataOffset = 4,
Value = (float)ParamEntry.Colors[0].G / 255f,
});
//Blue
matAnim.Constants.Add(new ResU.AnimConstant()
{
AnimDataOffset = 8,
Value = (float)ParamEntry.Colors[0].B / 255f,
});
//Alpha
matAnim.Constants.Add(new ResU.AnimConstant()
{
AnimDataOffset = 12,
Value = (float)ParamEntry.Colors[0].A / 255f,
});
}
var RedCurve = GenerateCurve(0, clr0, ParamEntry);
var GreenCurve = GenerateCurve(4, clr0, ParamEntry);
var BlueCurve = GenerateCurve(8, clr0, ParamEntry);
var AlphaCurve = GenerateCurve(12, clr0, ParamEntry);
if (RedCurve != null)
matAnim.Curves.Add(RedCurve);
if (GreenCurve != null)
matAnim.Curves.Add(GreenCurve);
if (BlueCurve != null)
matAnim.Curves.Add(BlueCurve);
if (AlphaCurve != null)
matAnim.Curves.Add(AlphaCurve);
matAnim.ParamAnimInfos.Add(new ResU.ParamAnimInfo()
{
Name = entry.Name,
BeginCurve = matAnim.Curves.Count > 0 ? curveIndex : ushort.MaxValue,
FloatCurveCount = (ushort)matAnim.Curves.Count,
SubBindIndex = ushort.MaxValue,
ConstantCount = (ushort)matAnim.Constants.Count,
BeginConstant = matAnim.Constants.Count > 0 ? constantIndex : ushort.MaxValue,
});
constantIndex += (ushort)matAnim.Constants.Count;
curveIndex += (ushort)matAnim.Curves.Count;
}
return matAnim;
}
private static ResU.AnimCurve GenerateCurve(uint AnimOffset, CLR0Node anim, CLR0MaterialEntryNode entry)
{
ResU.AnimCurve curve = new ResU.AnimCurve();
curve.AnimDataOffset = AnimOffset;
curve.StartFrame = 0;
curve.Offset = 0;
curve.Scale = 1;
curve.FrameType = ResU.AnimCurveFrameType.Single;
curve.KeyType = ResU.AnimCurveKeyType.Single;
curve.CurveType = ResU.AnimCurveType.Linear;
List<float> Frames = new List<float>();
List<float> Keys = new List<float>();
for (int c = 0; c < entry.Colors.Count; c++)
{
Frames.Add(c);
//Max of 4 values. Cubic using 4, linear using 2, and step using 1
float[] KeyValues = new float[4];
switch (AnimOffset)
{
case 0: //Red
Keys.Add((float)entry.Colors[c].R / 255f);
break;
case 4: //Green
Keys.Add((float)entry.Colors[c].G / 255f);
break;
case 8: //Blue
Keys.Add((float)entry.Colors[c].B / 255f);
break;
case 12: //Alpha
Keys.Add((float)entry.Colors[c].A / 255f);
break;
default:
throw new Exception("Invalid animation offset set!");
}
}
//Max value in frames is our end frame
curve.EndFrame = Frames.Max();
curve.Frames = Frames.ToArray();
//If a curve only has one frame we don't need to interpolate or add keys to a curve as it's constant
if (curve.Frames.Length <= 1)
return null;
switch (curve.CurveType)
{
case ResU.AnimCurveType.Cubic:
curve.Keys = new float[Keys.Count, 4];
for (int frame = 0; frame < Keys.Count; frame++)
{
float Delta = 0;
if (frame < Keys.Count - 1)
Delta = Keys[frame + 1] - Keys[frame];
float value = Keys[frame];
float Slope = 0;
float Slope2 = 0;
curve.Keys[frame, 0] = value;
curve.Keys[frame, 1] = Slope;
curve.Keys[frame, 2] = Slope2;
curve.Keys[frame, 3] = Delta;
}
break;
case ResU.AnimCurveType.StepInt:
//Step requires no interpolation
curve.Keys = new float[Keys.Count, 1];
for (int frame = 0; frame < Keys.Count; frame++)
{
curve.Keys[frame, 0] = 0;
}
break;
case ResU.AnimCurveType.Linear:
curve.Keys = new float[Keys.Count, 2];
for (int frame = 0; frame < Keys.Count; frame++)
{
//Delta for second value used in linear curves
float time = curve.Frames[frame];
float Delta = 0;
if (frame < Keys.Count - 1)
Delta = Keys[frame + 1] - Keys[frame];
curve.Keys[frame, 0] = Keys[frame];
curve.Keys[frame, 1] = Delta;
}
break;
}
return curve;
}
private static ushort[] SetIndices(ResU.ShaderParamAnim fshu)
{
List<ushort> indces = new List<ushort>();
foreach (var matAnim in fshu.ShaderParamMatAnims)
indces.Add(65535);
return indces.ToArray();
}
private static uint CalculateBakeSize(ResU.ShaderParamAnim fshu)
{
return 0;
}
}
public class FSKAConverter
{
static float Deg2Rad = (float)(Math.PI / 180f);
public static SkeletalAnim Chr02Fska(string FileName)
{
CHR0Node chr0 = CHR0Node.FromFile(FileName);
SkeletalAnim fska = new SkeletalAnim();
fska.FrameCount = chr0.FrameCount;
fska.Name = chr0.Name;
fska.Path = chr0.OriginalPath;
fska.UserDatas = new List<Syroot.NintenTools.NSW.Bfres.UserData>();
fska.UserDataDict = new ResDict();
//Set flags
if (chr0.Loop)
fska.FlagsAnimSettings |= SkeletalAnimFlags.Looping;
fska.FlagsRotate = SkeletalAnimFlagsRotate.EulerXYZ;
fska.FlagsScale = SkeletalAnimFlagsScale.Maya;
//Set bone anims and then calculate data after
foreach (var entry in chr0.Children)
fska.BoneAnims.Add(Chr0Entry2BoneAnim((CHR0EntryNode)entry));
fska.BakedSize = CalculateBakeSize(fska);
fska.BindIndices = SetIndices(fska);
return fska;
}
private static BoneAnim Chr0Entry2BoneAnim(CHR0EntryNode entry)
{
BoneAnim boneAnim = new BoneAnim();
boneAnim.Name = entry.Name;
if (entry.UseModelTranslate)
boneAnim.FlagsBase |= BoneAnimFlagsBase.Translate;
if (entry.UseModelRotate)
boneAnim.FlagsBase |= BoneAnimFlagsBase.Rotate;
if (entry.UseModelScale)
boneAnim.FlagsBase |= BoneAnimFlagsBase.Scale;
var FirstFrame = entry.GetAnimFrame(0);
float xRadian = FirstFrame.Rotation._x * Deg2Rad;
float yRadian = FirstFrame.Rotation._y * Deg2Rad;
float zRadian = FirstFrame.Rotation._z * Deg2Rad;
var baseData = new BoneAnimData();
baseData.Translate = new Vector3F(FirstFrame.Translation._x, FirstFrame.Translation._y, FirstFrame.Translation._z);
baseData.Rotate = new Vector4F(xRadian, yRadian, zRadian, 1);
baseData.Scale = new Vector3F(FirstFrame.Scale._x, FirstFrame.Scale._y, FirstFrame.Scale._z);
baseData.Flags = 0;
boneAnim.BaseData = baseData;
boneAnim.FlagsBase |= BoneAnimFlagsBase.Translate;
boneAnim.FlagsBase |= BoneAnimFlagsBase.Scale;
boneAnim.FlagsBase |= BoneAnimFlagsBase.Rotate;
if (baseData.Rotate == new Vector4F(0, 0, 0, 1))
boneAnim.FlagsTransform |= BoneAnimFlagsTransform.RotateZero;
if (baseData.Translate == new Vector3F(0, 0, 0))
boneAnim.FlagsTransform |= BoneAnimFlagsTransform.TranslateZero;
if (baseData.Scale == new Vector3F(1, 1, 1))
boneAnim.FlagsTransform |= BoneAnimFlagsTransform.ScaleOne;
if (IsUniform(baseData.Scale))
boneAnim.FlagsTransform |= BoneAnimFlagsTransform.ScaleUniform;
if (!IsRoot(boneAnim))
boneAnim.FlagsTransform |= BoneAnimFlagsTransform.SegmentScaleCompensate;
boneAnim.BeginTranslate = 6;
boneAnim.BeginRotate = 3;
if (FirstFrame.HasKeys)
{
var AnimFrame = entry.GetAnimFrame(0);
if (AnimFrame.hasTx)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateX;
var curve = GenerateCurve(0x10, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasTy)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateY;
var curve = GenerateCurve(0x14, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasTz)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.TranslateZ;
var curve = GenerateCurve(0x18, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasRx)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateX;
var curve = GenerateCurve(0x20, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasRy)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateY;
var curve = GenerateCurve(0x24, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasRz)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.RotateZ;
var curve = GenerateCurve(0x28, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasSx)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleX;
var curve = GenerateCurve(0x4, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasSy)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleY;
var curve = GenerateCurve(0x8, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
if (AnimFrame.hasSz)
{
boneAnim.FlagsCurve |= BoneAnimFlagsCurve.ScaleZ;
var curve = GenerateCurve(0xC, entry);
if (curve != null)
boneAnim.Curves.Add(curve);
}
}
return boneAnim;
}
private static bool IsRoot(BoneAnim boneAnim)
{
if (boneAnim.Name.Contains("root") || boneAnim.Name.Contains("center"))
return true;
return false;
}
private static bool IsUniform(Vector3F value)
{
return value.X == value.Y && value.X == value.Z;
}
private static bool HasKeyFrames(CHR0EntryNode entry)
{
for (int frame = 0; frame < entry.FrameCount; frame++)
{
var AnimFrame = entry.GetAnimFrame(frame);
if (frame > 0)
{
if (AnimFrame.hasTx) return true;
if (AnimFrame.hasTy) return true;
if (AnimFrame.hasTz) return true;
if (AnimFrame.hasRx) return true;
if (AnimFrame.hasRy) return true;
if (AnimFrame.hasRz) return true;
if (AnimFrame.hasSx) return true;
if (AnimFrame.hasSy) return true;
if (AnimFrame.hasSz) return true;
}
}
return false;
}
private static AnimCurve GenerateCurve(uint AnimOffset, CHR0EntryNode entry)
{
AnimCurve curve = new AnimCurve();
curve.AnimDataOffset = AnimOffset;
curve.StartFrame = 0;
curve.Offset = 0;
curve.Scale = 1;
curve.FrameType = AnimCurveFrameType.Single;
curve.KeyType = AnimCurveKeyType.Single;
curve.CurveType = AnimCurveType.Cubic;
List<float> Frames = new List<float>();
List<float[]> Keys = new List<float[]>();
for (int frame = 0; frame < entry.FrameCount; frame++)
{
//Max of 4 values. Cubic using 4, linear using 2, and step using 1
float[] KeyValues = new float[4];
//Set the main values to the curve based on offset for encoding later
var AnimFrame = entry.GetAnimFrame(frame);
if (AnimFrame.hasTx && AnimOffset == 0x10)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Translation._x;
Keys.Add(KeyValues);
}
if (AnimFrame.hasTy && AnimOffset == 0x14)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Translation._y;
Keys.Add(KeyValues);
}
if (AnimFrame.hasTz && AnimOffset == 0x18)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Translation._z;
Keys.Add(KeyValues);
}
if (AnimFrame.hasRx && AnimOffset == 0x20)
{
Frames.Add(frame);
float xRadian = AnimFrame.Rotation._x * Deg2Rad;
KeyValues[0] = xRadian;
Keys.Add(KeyValues);
}
if (AnimFrame.hasRy && AnimOffset == 0x24)
{
Frames.Add(frame);
float yRadian = AnimFrame.Rotation._y * Deg2Rad;
KeyValues[0] = yRadian;
Keys.Add(KeyValues);
}
if (AnimFrame.hasRz && AnimOffset == 0x28)
{
Frames.Add(frame);
float zRadian = AnimFrame.Rotation._z * Deg2Rad;
KeyValues[0] = zRadian;
Keys.Add(KeyValues);
}
if (AnimFrame.hasSx && AnimOffset == 0x04)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Scale._x;
Keys.Add(KeyValues);
}
if (AnimFrame.hasSy && AnimOffset == 0x08)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Scale._y;
Keys.Add(KeyValues);
}
if (AnimFrame.hasSz && AnimOffset == 0x0C)
{
Frames.Add(frame);
KeyValues[0] = AnimFrame.Scale._z;
Keys.Add(KeyValues);
}
}
//Max value in frames is our end frame
curve.EndFrame = Frames.Max();
curve.Frames = Frames.ToArray();
//If a curve only has one frame we don't need to interpolate or add keys to a curve as it's constant
if (curve.Frames.Length <= 1)
return null;
switch (curve.CurveType)
{
case AnimCurveType.Cubic:
curve.Keys = new float[Keys.Count, 4];
for (int frame = 0; frame < Keys.Count; frame++)
{
float Delta = 0;
if (frame < Keys.Count - 1)
Delta = Keys[frame + 1][0] - Keys[frame][0];
float value = Keys[frame][0];
float Slope = Keys[frame][1];
float Slope2 = Keys[frame][2];
curve.Keys[frame, 0] = value;
curve.Keys[frame, 1] = Slope;
curve.Keys[frame, 2] = Slope2;
curve.Keys[frame, 3] = Delta;
}
break;
case AnimCurveType.StepInt:
//Step requires no interpolation
curve.Keys = new float[Keys.Count, 1];
for (int frame = 0; frame < Keys.Count; frame++)
{
curve.Keys[frame, 0] = Keys[frame][0];
}
break;
case AnimCurveType.Linear:
curve.Keys = new float[Keys.Count, 2];
for (int frame = 0; frame < Keys.Count; frame++)
{
//Delta for second value used in linear curves
float time = curve.Frames[frame];
float Delta = 0;
if (frame < Keys.Count - 1)
Delta = Keys[frame + 1][0] - Keys[frame][0];
curve.Keys[frame, 0] = Keys[frame][0];
curve.Keys[frame, 1] = Delta;
}
break;
}
return curve;
}
private static ushort[] SetIndices(SkeletalAnim fska)
{
List<ushort> indces = new List<ushort>();
foreach (var boneAnim in fska.BoneAnims)
indces.Add(65535);
return indces.ToArray();
}
private static uint CalculateBakeSize(SkeletalAnim fska)
{
return 0;
}
}
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FA690685-3370-44D5-B138-F538C8D4C2A3}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BrawlboxHelper</RootNamespace>
<AssemblyName>BrawlboxHelper</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Toolbox\bin\Release\Lib\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="BrawlLib">
<HintPath>..\Toolbox\Lib\BrawlLib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.BinaryData">
<HintPath>..\Toolbox\Lib\Syroot.BinaryData.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.Maths">
<HintPath>..\Toolbox\Lib\Syroot.Maths.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.NintenTools.Bfres">
<HintPath>..\Toolbox\Lib\Syroot.NintenTools.Bfres.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Syroot.NintenTools.NSW.Bfres, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Toolbox\Lib\Syroot.NintenTools.NSW.Bfres.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BrawlboxHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BrawlboxHelper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BrawlboxHelper")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fa690685-3370-44d5-b138-f538c8d4c2a3")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -78,12 +78,14 @@ In the event that the tool cannot compile, check references. All the libraries a
- GDKChan for PICA shaders stuff used with bcres, structs for bcres, and some DDS decode methods
- AboodXD for some foundation stuff with exelix's SARC library, Wii U (GPU7) and Switch (Tegra X1) textures swizzling, reading/converting uncompressed types for DDS, and documentation for GTX, XTX, and BNTX
- MelonSpeedruns for logo.
- BrawlBox team for brawl libaries used for brres parsing.
Resources
- [Treeview Icons by icons8](https://icons8.com/)
- Smash Forge (Currently placeholders)
Libraries
- [Brawl Lib (for brres section conversion)](https://github.com/libertyernie/brawltools)
- [Exelix (Sarc, kcl, and byml libraries)](https://github.com/exelix11/EditorCore/tree/master/FileFormatPlugins)
- [ZstdNet (Compression)](https://github.com/skbkontur/ZstdNet)
- [Be.HexEditor by Bernhard Elbl](https://sourceforge.net/projects/hexbox/)

View File

@ -65,24 +65,32 @@ namespace FirstPlugin
int textureUnit = 1;
if (material.TextureMapInfo1 != null)
Nodes.Add(CreateGenericMatTexture(textureUnit, bcres, material.TextureMapInfo1));
if (material.TextureMapInfo2 != null)
Nodes.Add(CreateGenericMatTexture(textureUnit, bcres, material.TextureMapInfo2));
if (material.TextureMapInfo3 != null)
Nodes.Add(CreateGenericMatTexture(textureUnit, bcres, material.TextureMapInfo3));
}
private BcresTextureMapWrapper CreateGenericMatTexture(int textureUnit, BCRES bcres, TextureMapInfo TextureMapInfo)
{
STGenericMatTexture tex1 = new STGenericMatTexture();
var TexRef = material.TextureMapInfo1.TextureRef;
var Sampler = material.TextureMapInfo1.Sampler;
var TexRef = TextureMapInfo.TextureRef;
var Sampler = TextureMapInfo.Sampler;
tex1.textureUnit = textureUnit++;
tex1.Name = TexRef.Reference.Name;
tex1.Type = STGenericMatTexture.TextureType.Diffuse;
TextureMaps.Add(tex1);
switch (material.TextureMapInfo1.WrapU)
switch (TextureMapInfo.WrapU)
{
case PICATextureWrap.Repeat: tex1.wrapModeS = 0; break;
case PICATextureWrap.Mirror: tex1.wrapModeS = 1; break;
case PICATextureWrap.ClampToEdge: tex1.wrapModeS = 2; break;
case PICATextureWrap.ClampToBorder: tex1.wrapModeS = 2; break;
}
switch (material.TextureMapInfo1.WrapV)
switch (TextureMapInfo.WrapV)
{
case PICATextureWrap.Repeat: tex1.wrapModeT = 0; break;
case PICATextureWrap.Mirror: tex1.wrapModeT = 1; break;
@ -90,25 +98,25 @@ namespace FirstPlugin
case PICATextureWrap.ClampToBorder: tex1.wrapModeT = 2; break;
}
switch (material.TextureMapInfo1.MagFilter)
switch (TextureMapInfo.MagFilter)
{
case PICATextureFilter.Linear: tex1.magFilter = 0; break;
case PICATextureFilter.Nearest: tex1.magFilter = 1; break;
}
switch (material.TextureMapInfo1.MinFilter)
switch (TextureMapInfo.MinFilter)
{
case PICATextureFilter.Linear: tex1.minFilter = 0; break;
case PICATextureFilter.Nearest: tex1.minFilter = 1; break;
}
switch (material.TextureMapInfo1.MipFilter)
switch (TextureMapInfo.MipFilter)
{
case PICATextureFilter.Linear: tex1.mipDetail = 0; break;
case PICATextureFilter.Nearest: tex1.mipDetail = 1; break;
}
switch (material.TextureMapInfo1.WrapV)
switch (TextureMapInfo.WrapV)
{
case PICATextureWrap.Repeat: tex1.wrapModeT = 0; break;
case PICATextureWrap.Mirror: tex1.wrapModeT = 1; break;
@ -117,9 +125,8 @@ namespace FirstPlugin
}
var wrapperTexMap = new BcresTextureMapWrapper(bcres, material.TextureMapInfo1, tex1);
Nodes.Add(wrapperTexMap);
}
var wrapperTexMap = new BcresTextureMapWrapper(bcres, TextureMapInfo, tex1);
return wrapperTexMap;
}
}
}

View File

@ -104,6 +104,9 @@ namespace Bfres.Structs
public void ImportSkeletalAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.FSKA_REPLACE;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -115,10 +118,15 @@ namespace Bfres.Structs
public void ImportShaderParamAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (IsWiiU)
ofd.Filter = FileFilters.FSHU_REPLACE;
else
ofd.Filter = FileFilters.FMAA;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FSHU>(MaterialAnimation.AnimationType.ShaderParam);
@ -132,6 +140,12 @@ namespace Bfres.Structs
public void ImportColorAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (IsWiiU)
ofd.Filter = FileFilters.FSHU_REPLACE;
else
ofd.Filter = FileFilters.FMAA;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -148,6 +162,12 @@ namespace Bfres.Structs
public void ImportTexSrtAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (IsWiiU)
ofd.Filter = FileFilters.FSHU_REPLACE;
else
ofd.Filter = FileFilters.FMAA;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -164,6 +184,12 @@ namespace Bfres.Structs
public void ImportTexPatAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (IsWiiU)
ofd.Filter = FileFilters.FTXP;
else
ofd.Filter = FileFilters.FMAA;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -180,6 +206,9 @@ namespace Bfres.Structs
public void ImportBoneVisAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.FBNV;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -191,6 +220,9 @@ namespace Bfres.Structs
public void ImportMatVisAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.FBNV;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -207,6 +239,9 @@ namespace Bfres.Structs
public void ImportSceneAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.FSCN;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -218,6 +253,9 @@ namespace Bfres.Structs
public void ImportShapeAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.FSHA;
ofd.Multiselect = true;
if (ofd.ShowDialog() != DialogResult.OK)
return;
@ -393,7 +431,7 @@ namespace Bfres.Structs
public BFRESGroupNode GetOrCreateFolder<T>(object CheckAnimEffect = null) where T : STGenericWrapper
{
BFRESGroupNode group = new BFRESGroupNode();
BFRESGroupNode group = new BFRESGroupNode(IsWiiU);
if (typeof(T) == typeof(FSKA)) { group.Type = BRESGroupType.SkeletalAnim; }
if (typeof(T) == typeof(FMAA)) { group.Type = BRESGroupType.MaterialAnim; }

View File

@ -38,18 +38,7 @@ namespace Bfres.Structs
get { return ContextMenuStrip.Items[0].Visible; }
}
public bool IsWiiU
{
get
{
if (Parent is BFRES)
return ((BFRES)Parent).IsWiiU;
else if (Parent.Parent is BFRES)
return ((BFRES)Parent.Parent).IsWiiU;
else
return ((BFRES)Parent.Parent.Parent).IsWiiU;
}
}
public bool IsWiiU;
public override void OnClick(TreeView treeview)
{
@ -62,10 +51,11 @@ namespace Bfres.Structs
}
}
public BFRESGroupNode() : base()
public BFRESGroupNode(bool isWiiU) : base()
{
ImageKey = "folder";
IsWiiU = isWiiU;
LoadContextMenus();
}

View File

@ -55,9 +55,9 @@ namespace Bfres.Structs
InterType = InterpolationType.HERMITE,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Value3 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Value4 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
Slope1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Slope2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
});
break;
case ResU.AnimCurveType.Linear: //2 elements are stored for linear
@ -68,7 +68,7 @@ namespace Bfres.Structs
InterType = InterpolationType.LINEAR,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
break;
case ResU.AnimCurveType.StepInt: //1 element are stored for step
@ -182,9 +182,9 @@ namespace Bfres.Structs
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Value3 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Value4 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
Slope1 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Slope2 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
});
break;
case AnimCurveType.Linear: //2 elements are stored for linear
@ -197,7 +197,7 @@ namespace Bfres.Structs
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Delta = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
break;
case AnimCurveType.StepInt: //1 element are stored for step

View File

@ -465,7 +465,14 @@ namespace Bfres.Structs
break;
default:
AssimpSaver assimp = new AssimpSaver();
ExportModelSettings settings = new ExportModelSettings();
if (settings.ShowDialog() == DialogResult.OK)
{
if (settings.ExportTextures)
assimp.SaveFromModel(this, FileName, GetTextures(), Skeleton, Skeleton.Node_Array.ToList());
else
assimp.SaveFromModel(this, FileName, new List<STGenericTexture>(), Skeleton, Skeleton.Node_Array.ToList());
}
break;
}
}

View File

@ -32,6 +32,9 @@ namespace Bfres.Structs
Materials.Add(mat);
}
public override string ExportFilter => FileFilters.FSHU_EXPORT;
public override string ReplaceFilter => FileFilters.FSHU_REPLACE;
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
@ -66,6 +69,11 @@ namespace Bfres.Structs
ShaderParamAnim.Import(FileName, resFile, ShaderParamAnimType.TextureSRT);
LoadAnim(ShaderParamAnim, AnimationType.TexturePattern);
}
if (ext == ".clr0")
{
ShaderParamAnim = BrawlboxHelper.FSHUConverter.Clr02Fshu(FileName);
LoadAnim(ShaderParamAnim, AnimationType.Color);
}
ShaderParamAnim.Name = Text;
}

View File

@ -186,24 +186,182 @@ namespace Bfres.Structs
string ext = Utils.GetExtension(FileName);
if (ext == ".bfska")
{
bool IsSwitch = BfresUtilies.IsSubSectionSwitch(FileName);
MessageBox.Show(IsSwitch.ToString());
if (resFileU != null)
{
SkeletalAnimU.Import(FileName, resFileU);
//If it's a switch animation try to conver it to wii u
if (IsSwitch)
{
var ska = new SkeletalAnim();
ska.Import(FileName);
SkeletalAnimU = ConvertSwitchToWiiU(ska);
SkeletalAnimU.Name = Text;
LoadAnim(SkeletalAnimU);
}
else
{
SkeletalAnimU.Import(FileName, resFileU);
SkeletalAnimU.Name = Text;
LoadAnim(SkeletalAnimU);
}
}
else
{
if (IsSwitch)
{
SkeletalAnim.Import(FileName);
SkeletalAnim.Name = Text;
LoadAnim(SkeletalAnim);
}
else
{
//Create a new wii u skeletal anim and try to convert it instead
var ska = new ResU.SkeletalAnim();
ska.Import(FileName, new ResU.ResFile());
SkeletalAnim = ConvertWiiUToSwitch(ska);
SkeletalAnim.Name = Text;
LoadAnim(SkeletalAnim);
}
}
}
else if (ext == ".seanim")
{
FromSeanim(FileName);
}
else if (ext == ".chr0")
{
FromChr0(FileName);
}
}
public static SkeletalAnim ConvertWiiUToSwitch(ResU.SkeletalAnim skeletalAnimU)
{
SkeletalAnim ska = new SkeletalAnim();
ska.Name = skeletalAnimU.Name;
ska.Path = skeletalAnimU.Path;
ska.FrameCount = skeletalAnimU.FrameCount;
ska.FlagsScale = SkeletalAnimFlagsScale.None;
if (skeletalAnimU.FlagsScale.HasFlag(ResU.SkeletalAnimFlagsScale.Maya))
ska.FlagsScale = SkeletalAnimFlagsScale.Maya;
if (skeletalAnimU.FlagsScale.HasFlag(ResU.SkeletalAnimFlagsScale.Softimage))
ska.FlagsScale = SkeletalAnimFlagsScale.Softimage;
if (skeletalAnimU.FlagsScale.HasFlag(ResU.SkeletalAnimFlagsScale.Standard))
ska.FlagsScale = SkeletalAnimFlagsScale.Standard;
ska.FrameCount = skeletalAnimU.FrameCount;
ska.BindIndices = skeletalAnimU.BindIndices;
ska.BakedSize = skeletalAnimU.BakedSize;
ska.Loop = skeletalAnimU.Loop;
ska.Baked = skeletalAnimU.Baked;
foreach (var boneAnimU in skeletalAnimU.BoneAnims)
{
var boneAnim = new BoneAnim();
ska.BoneAnims.Add(boneAnim);
boneAnim.Name = boneAnimU.Name;
boneAnim.BeginRotate = boneAnimU.BeginRotate;
boneAnim.BeginTranslate = boneAnimU.BeginTranslate;
boneAnim.BeginBaseTranslate = boneAnimU.BeginBaseTranslate;
var baseData = new BoneAnimData();
baseData.Translate = boneAnimU.BaseData.Translate;
baseData.Scale = boneAnimU.BaseData.Scale;
baseData.Rotate = boneAnimU.BaseData.Rotate;
baseData.Flags = boneAnimU.BaseData.Flags;
boneAnim.BaseData = baseData;
boneAnim.FlagsBase = (BoneAnimFlagsBase)boneAnimU.FlagsBase;
boneAnim.FlagsCurve = (BoneAnimFlagsCurve)boneAnimU.FlagsCurve;
boneAnim.FlagsTransform = (BoneAnimFlagsTransform)boneAnimU.FlagsTransform;
foreach (var curveU in boneAnimU.Curves)
{
AnimCurve curve = new AnimCurve();
curve.AnimDataOffset = curveU.AnimDataOffset;
curve.CurveType = (AnimCurveType)curveU.CurveType;
curve.Delta = curveU.Delta;
curve.EndFrame = curveU.EndFrame;
curve.Frames = curveU.Frames;
curve.Keys = curveU.Keys;
curve.KeyStepBoolData = curveU.KeyStepBoolData;
curve.KeyType = (AnimCurveKeyType)curveU.KeyType;
curve.FrameType = (AnimCurveFrameType)curveU.FrameType;
curve.StartFrame = curveU.StartFrame;
curve.Scale = curveU.Scale;
if (curve.Offset.GetType() == typeof(float))
curve.Offset = (float)curveU.Offset;
if (curve.Offset.GetType() == typeof(uint))
curve.Offset = (uint)curveU.Offset;
if (curve.Offset.GetType() == typeof(int))
curve.Offset = (int)curveU.Offset;
boneAnim.Curves.Add(curve);
}
}
return ska;
}
public static ResU.SkeletalAnim ConvertSwitchToWiiU(SkeletalAnim skeletalAnimNX)
{
ResU.SkeletalAnim ska = new ResU.SkeletalAnim();
ska.Name = skeletalAnimNX.Name;
ska.Path = skeletalAnimNX.Path;
ska.FrameCount = skeletalAnimNX.FrameCount;
ska.FlagsScale = ResU.SkeletalAnimFlagsScale.None;
if (skeletalAnimNX.FlagsScale.HasFlag(SkeletalAnimFlagsScale.Maya))
ska.FlagsScale = ResU.SkeletalAnimFlagsScale.Maya;
if (skeletalAnimNX.FlagsScale.HasFlag(SkeletalAnimFlagsScale.Softimage))
ska.FlagsScale = ResU.SkeletalAnimFlagsScale.Softimage;
if (skeletalAnimNX.FlagsScale.HasFlag(SkeletalAnimFlagsScale.Standard))
ska.FlagsScale = ResU.SkeletalAnimFlagsScale.Standard;
ska.FrameCount = skeletalAnimNX.FrameCount;
ska.BindIndices = skeletalAnimNX.BindIndices;
ska.BakedSize = skeletalAnimNX.BakedSize;
ska.Loop = skeletalAnimNX.Loop;
ska.Baked = skeletalAnimNX.Baked;
foreach (var boneAnimNX in skeletalAnimNX.BoneAnims)
{
var boneAnimU = new ResU.BoneAnim();
ska.BoneAnims.Add(boneAnimU);
boneAnimU.Name = boneAnimNX.Name;
boneAnimU.BeginRotate = boneAnimNX.BeginRotate;
boneAnimU.BeginTranslate = boneAnimNX.BeginTranslate;
boneAnimU.BeginBaseTranslate = boneAnimNX.BeginBaseTranslate;
var baseData = new ResU.BoneAnimData();
baseData.Translate = boneAnimNX.BaseData.Translate;
baseData.Scale = boneAnimNX.BaseData.Scale;
baseData.Rotate = boneAnimNX.BaseData.Rotate;
baseData.Flags = boneAnimNX.BaseData.Flags;
boneAnimU.BaseData = baseData;
boneAnimU.FlagsBase = (ResU.BoneAnimFlagsBase)boneAnimNX.FlagsBase;
boneAnimU.FlagsCurve = (ResU.BoneAnimFlagsCurve)boneAnimNX.FlagsCurve;
boneAnimU.FlagsTransform = (ResU.BoneAnimFlagsTransform)boneAnimNX.FlagsTransform;
foreach (var curveNX in boneAnimU.Curves)
{
ResU.AnimCurve curve = new ResU.AnimCurve();
curve.AnimDataOffset = curveNX.AnimDataOffset;
curve.CurveType = curveNX.CurveType;
curve.Delta = curveNX.Delta;
curve.EndFrame = curveNX.EndFrame;
curve.Frames = curveNX.Frames;
curve.Keys = curveNX.Keys;
curve.KeyStepBoolData = curveNX.KeyStepBoolData;
curve.KeyType = curveNX.KeyType;
curve.FrameType = curveNX.FrameType;
curve.StartFrame = curveNX.StartFrame;
curve.Scale = curveNX.Scale;
curve.Offset = curveNX.Offset;
boneAnimU.Curves.Add(curve);
}
}
return ska;
}
public FSKA(ResU.SkeletalAnim ska) { LoadAnim(ska); }
public FSKA(SkeletalAnim ska) { LoadAnim(ska); }
@ -363,6 +521,23 @@ namespace Bfres.Structs
Initialize();
}
public void FromChr0(string FileName)
{
if (SkeletalAnimU != null)
{
var SkeletalAnimNX = BrawlboxHelper.FSKAConverter.Chr02Fska(FileName);
SkeletalAnimU = ConvertSwitchToWiiU(SkeletalAnimNX);
SkeletalAnimU.Name = Text;
LoadAnim(SkeletalAnimU);
}
else
{
SkeletalAnim = BrawlboxHelper.FSKAConverter.Chr02Fska(FileName);
SkeletalAnim.Name = Text;
LoadAnim(SkeletalAnim);
}
}
public void FromSeanim(string FileName)
{
SEAnim anim = SEAnim.Read(FileName);

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
public class BfresUtilies
{
public static bool IsSubSectionSwitch(string FileName)
{
using (var reader = new FileReader(FileName))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
reader.Seek(24, System.IO.SeekOrigin.Begin);
return reader.ReadUInt32() == 1;
}
}
}
}

View File

@ -576,7 +576,9 @@ namespace FirstPlugin
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadProperties(FTEX.FromGx2Surface(surface, Text));
var tex = FTEX.FromGx2Surface(surface, Text);
tex.MipCount = MipCount;
editor.LoadProperties(tex);
editor.LoadImage(this);
}
}

View File

@ -47,9 +47,9 @@ namespace FirstPlugin.Forms
stLabel1.Text = $"key Frame {keyFrame.Frame}";
numericUpDownFloat1.Value = (decimal)keyFrame.Value1;
numericUpDownFloat2.Value = (decimal)keyFrame.Value2;
numericUpDownFloat3.Value = (decimal)keyFrame.Value3;
numericUpDownFloat4.Value = (decimal)keyFrame.Value4;
numericUpDownFloat2.Value = (decimal)keyFrame.Slope1;
numericUpDownFloat3.Value = (decimal)keyFrame.Slope2;
numericUpDownFloat4.Value = (decimal)keyFrame.Delta;
}
else
{

View File

@ -45,7 +45,7 @@ namespace FirstPlugin.NodeWrappers
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = new BFRESGroupNode();
BFRESGroupNode group = new BFRESGroupNode(IsWiiU);
group.Import(ofd.FileNames);
}
@ -55,13 +55,13 @@ namespace FirstPlugin.NodeWrappers
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = new BFRESGroupNode();
BFRESGroupNode group = new BFRESGroupNode(IsWiiU);
group.Import(ofd.FileNames);
}
public void NewModel()
{
BFRESGroupNode group = new BFRESGroupNode();
BFRESGroupNode group = new BFRESGroupNode(IsWiiU);
FMDL anim = new FMDL();
if (IsWiiU)
@ -80,7 +80,7 @@ namespace FirstPlugin.NodeWrappers
public void NewEmbeddedFile()
{
BFRESGroupNode group = new BFRESGroupNode();
BFRESGroupNode group = new BFRESGroupNode(IsWiiU);
ExternalFileData fshu = new ExternalFileData("NewFile", new byte[0]);
group.AddNode(fshu, "NewFile");
SetupAddedNode(group, fshu);

View File

@ -21,9 +21,12 @@ namespace FirstPlugin
public static string BONE = GetFilter(".bfbon");
public static string FMAT = GetFilter(".bfmat");
public static string FSKA = GetFilter(".bfska", ".seanim", ".smd");
public static string FSKA_EXPORT = GetFilter(".bfska", ".seanim", ".smd");
public static string FSKA_REPLACE = GetFilter(".bfska", ".chr0");
public static string FMAA = GetFilter(".bfmaa", ".gif");
public static string FSHU = GetFilter(".bfshu");
public static string FSHU_REPLACE = GetFilter(".bfshu", "clr0");
public static string FSHU_EXPORT = GetFilter(".bfshu");
public static string FCLH = GetFilter(".bfcsh");
public static string FSTH = GetFilter(".bfsth");
@ -45,7 +48,8 @@ namespace FirstPlugin
else if (type == typeof(FMAT)) return FMAT;
else if (type == typeof(FSKL)) return FSKL;
else if (type == typeof(BfresBone)) return BONE;
else if (type == typeof(FSKA)) return FSKA;
else if (type == typeof(FMAA) && IsExporting) return FSKA_EXPORT;
else if (type == typeof(FSKA)) return FSKA_REPLACE;
else if (type == typeof(FMAA)) return FMAA;
else if (type == typeof(FTXP)) return FTXP;
else if (type == typeof(FSHA)) return FSHA;
@ -67,7 +71,11 @@ namespace FirstPlugin
if (animType == VisibiltyAnimType.Material) return FMTV;
else return FBNV;
}
return FSHU;
if (IsExporting)
return FSHU_EXPORT;
else
return FSHU_REPLACE;
}
else if (type == typeof(FVIS))
{

View File

@ -217,6 +217,7 @@
<Compile Include="FileFormats\BCRES\Wrappers\TXOBWrapper.cs" />
<Compile Include="FileFormats\BFRES\BFRESGroupNode.cs" />
<Compile Include="FileFormats\BFRES\BFRESAnimFolder.cs" />
<Compile Include="FileFormats\BFRES\BfresUtilies.cs" />
<Compile Include="FileFormats\BFRES\gfxEnum.cs" />
<Compile Include="FileFormats\BFRES\GLEnumConverter.cs" />
<Compile Include="FileFormats\Bin\KartParts.cs" />
@ -1159,6 +1160,11 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BrawlboxHelper\BrawlboxHelper.csproj">
<Project>{fa690685-3370-44d5-b138-f538c8d4c2a3}</Project>
<Name>BrawlboxHelper</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Switch_Toolbox_Library\Switch_Toolbox_Library.csproj">
<Project>{96820047-2a39-4e5a-bfa4-e84fff5c66cf}</Project>
<Name>Switch_Toolbox_Library</Name>

View File

@ -1 +1 @@
f3116c416a062081738ca7e7aee034e76dab7162
b1cc2c6fe1714d994e4d77917f9fc78ba61787cc

View File

@ -11,6 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Updater\Updater.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolbox", "Toolbox\Toolbox.csproj", "{5E55CA2B-F181-4681-AAFA-A20FEBCF7387}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BrawlboxHelper", "BrawlboxHelper\BrawlboxHelper.csproj", "{FA690685-3370-44D5-B138-F538C8D4C2A3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -52,14 +53,14 @@ Global
{5E55CA2B-F181-4681-AAFA-A20FEBCF7387}.Release|Any CPU.Build.0 = Release|Any CPU
{5E55CA2B-F181-4681-AAFA-A20FEBCF7387}.Release|x64.ActiveCfg = Release|Any CPU
{5E55CA2B-F181-4681-AAFA-A20FEBCF7387}.Release|x64.Build.0 = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|x64.ActiveCfg = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|x64.Build.0 = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|Any CPU.Build.0 = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|x64.ActiveCfg = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|x64.Build.0 = Release|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Debug|x64.ActiveCfg = Debug|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Debug|x64.Build.0 = Debug|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Release|Any CPU.Build.0 = Release|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Release|x64.ActiveCfg = Release|Any CPU
{FA690685-3370-44D5-B138-F538C8D4C2A3}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -453,7 +453,10 @@ namespace Switch_Toolbox.Library.Animations
{
public bool IsKeyed = false;
public float Value1, Value2, Value3, Value4;
public float Value1, Delta;
public float Slope1;
public float Slope2;
public float Value
{
@ -468,7 +471,11 @@ namespace Switch_Toolbox.Library.Animations
}
public String Text;
public float _frame;
public float In = 0, Out = -1;
public float In = 0;
public float Out = -1;
// public float In = 0, Out = -1;
public bool Weighted = false;
public bool Degrees = false; // Use Degrees
public InterpolationType InterType = InterpolationType.LINEAR;

View File

@ -11,17 +11,42 @@ namespace Switch_Toolbox.Library
{
public class AssimpSaver
{
private List<string> ExtractedTextures = new List<string>();
public List<string> BoneNames = new List<string>();
STProgressBar progressBar;
public void SaveFromModel(STGenericModel model, string FileName, List<STGenericTexture> Textures, STSkeleton skeleton = null, List<int> NodeArray = null)
{
ExtractedTextures.Clear();
Scene scene = new Scene();
scene.RootNode = new Node("RootNode");
progressBar = new STProgressBar();
progressBar.Task = "Exorting Skeleton...";
progressBar.Value = 0;
progressBar.StartPosition = FormStartPosition.CenterScreen;
progressBar.Show();
progressBar.Refresh();
SaveSkeleton(skeleton, scene.RootNode);
SaveMaterials(scene, model, FileName, Textures);
progressBar.Task = "Exorting Meshes...";
progressBar.Value = 50;
SaveMeshes(scene, model, skeleton, FileName, NodeArray);
progressBar.Task = "Saving File...";
progressBar.Value = 80;
SaveScene(FileName, scene);
progressBar.Value = 100;
progressBar.Close();
progressBar.Dispose();
}
private void SaveScene(string FileName, Scene scene)
@ -150,16 +175,25 @@ namespace Switch_Toolbox.Library
string TextureExtension = ".png";
string TexturePath = System.IO.Path.GetDirectoryName(FileName);
foreach (var tex in Textures)
for (int i = 0; i < Textures.Count; i++)
{
string path = System.IO.Path.Combine(TexturePath, tex.Text + TextureExtension);
string path = System.IO.Path.Combine(TexturePath, Textures[i].Text + TextureExtension);
var bitmap = tex.GetBitmap();
if (!ExtractedTextures.Contains(path))
{
ExtractedTextures.Add(path);
progressBar.Task = $"Exorting Texture {Textures[i].Text}";
progressBar.Value = ((i * 100) / Textures.Count);
progressBar.Refresh();
var bitmap = Textures[i].GetBitmap();
bitmap.Save(path);
bitmap.Dispose();
GC.Collect();
}
}
foreach (var mat in model.Nodes[1].Nodes)
{

View File

@ -31,7 +31,7 @@ namespace Switch_Toolbox.Library
string SelectedExt = comboBox1.GetSelectedText();
string output = GetSubstringByString("(",")", SelectedExt);
output = output.Replace('*', ' ');
output = output.Remove(0, 1);
output.Replace(" ", string.Empty);
if (output == ".")

View File

@ -0,0 +1,100 @@
namespace Switch_Toolbox.Library.Forms
{
partial class ExportModelSettings
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.exportTexturesChkBox = new Switch_Toolbox.Library.Forms.STCheckBox();
this.stButton1 = new Switch_Toolbox.Library.Forms.STButton();
this.stButton2 = new Switch_Toolbox.Library.Forms.STButton();
this.contentContainer.SuspendLayout();
this.SuspendLayout();
//
// contentContainer
//
this.contentContainer.Controls.Add(this.stButton2);
this.contentContainer.Controls.Add(this.stButton1);
this.contentContainer.Controls.Add(this.exportTexturesChkBox);
this.contentContainer.Size = new System.Drawing.Size(210, 156);
this.contentContainer.Controls.SetChildIndex(this.exportTexturesChkBox, 0);
this.contentContainer.Controls.SetChildIndex(this.stButton1, 0);
this.contentContainer.Controls.SetChildIndex(this.stButton2, 0);
//
// exportTexturesChkBox
//
this.exportTexturesChkBox.AutoSize = true;
this.exportTexturesChkBox.Checked = true;
this.exportTexturesChkBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.exportTexturesChkBox.Location = new System.Drawing.Point(23, 47);
this.exportTexturesChkBox.Name = "exportTexturesChkBox";
this.exportTexturesChkBox.Size = new System.Drawing.Size(100, 17);
this.exportTexturesChkBox.TabIndex = 11;
this.exportTexturesChkBox.Text = "Export Textures";
this.exportTexturesChkBox.UseVisualStyleBackColor = true;
//
// stButton1
//
this.stButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.stButton1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.stButton1.Location = new System.Drawing.Point(126, 124);
this.stButton1.Name = "stButton1";
this.stButton1.Size = new System.Drawing.Size(75, 23);
this.stButton1.TabIndex = 12;
this.stButton1.Text = "Cancel";
this.stButton1.UseVisualStyleBackColor = false;
//
// stButton2
//
this.stButton2.DialogResult = System.Windows.Forms.DialogResult.OK;
this.stButton2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.stButton2.Location = new System.Drawing.Point(45, 124);
this.stButton2.Name = "stButton2";
this.stButton2.Size = new System.Drawing.Size(75, 23);
this.stButton2.TabIndex = 13;
this.stButton2.Text = "Ok";
this.stButton2.UseVisualStyleBackColor = false;
//
// ExportModelSettings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(216, 161);
this.Name = "ExportModelSettings";
this.Text = "Export Settings";
this.contentContainer.ResumeLayout(false);
this.contentContainer.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private STCheckBox exportTexturesChkBox;
private STButton stButton2;
private STButton stButton1;
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Switch_Toolbox.Library.Forms
{
public partial class ExportModelSettings : STForm
{
public bool ExportTextures
{
get
{
return exportTexturesChkBox.Checked;
}
}
public ExportModelSettings()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -186,6 +186,7 @@ namespace Switch_Toolbox.Library.NodeWrappers
if (form.ShowDialog() == DialogResult.OK)
{
string extension = form.GetSelectedExtension();
extension.Replace(" ", string.Empty);
foreach (TreeNode node in Nodes)
{

View File

@ -220,6 +220,12 @@
<Compile Include="Forms\BatchFormatExport.Designer.cs">
<DependentUpon>BatchFormatExport.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Dialogs\ExportModelSettings.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\Dialogs\ExportModelSettings.Designer.cs">
<DependentUpon>ExportModelSettings.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Editors\Animation\BoneAnimTimeline.cs">
<SubType>UserControl</SubType>
</Compile>
@ -690,6 +696,9 @@
<EmbeddedResource Include="Forms\Custom\STTextBox.resx">
<DependentUpon>STTextBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Dialogs\ExportModelSettings.resx">
<DependentUpon>ExportModelSettings.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Dialogs\STOptionsDialog.resx">
<DependentUpon>STOptionsDialog.cs</DependentUpon>
</EmbeddedResource>

BIN
Toolbox/Lib/BrawlLib.dll Normal file

Binary file not shown.

BIN
Toolbox/Lib/BrawlLib.pdb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -310,6 +310,9 @@
<Content Include="Lib\BfshaLibrary.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\BrawlLib.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Lib\ByamlExt.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>