e4722ed1af
General - Always allow multiple instances of the tool by default. (UseSingleInstance in config.XML) - Yaz0 now uses a new library using c code. This improves compression times and is comparable to wzst's yaz0 compressor. Thanks to AboodXD for helping port the code. - Add flat buffer templates for gfbmdl and gfbanm. - Redid UV editor. Now using new 2D engine with some improvements. Should work better with mutliple file formats than just bfres. - Auto compress bfres with .sbfres extension. BFLYT: -Add animation reference list to panes if they have any animations. - Note the animation editor in it is not functional yet. GFBMDL - Progress on model importing. Currently crashes on many tests so saving is currently disabled till i figure out why. - Add new texture map display with UV coordinates shown. Displays how transforms are handled. - Add option to export materials and models entirely as .json files. DAE - improve bone/joint check.
346 lines
14 KiB
C#
346 lines
14 KiB
C#
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;
|
|
using Toolbox.Library.Forms;
|
|
using Toolbox.Library;
|
|
using FirstPlugin.GFMDLStructs;
|
|
|
|
namespace FirstPlugin.Forms
|
|
{
|
|
public partial class GFLXModelImporter : STForm
|
|
{
|
|
public bool ImportNewBones => !chkUseOriginalBones.Checked;
|
|
|
|
private List<STGenericObject> Meshes;
|
|
private List<GFLXMesh> OriginalMeshes;
|
|
|
|
public GfbmdlImportSettings Settings = new GfbmdlImportSettings();
|
|
|
|
private bool Loaded = false;
|
|
|
|
public int RotationY => (int)rotateModel90YUD.Value;
|
|
|
|
public GFLXModelImporter()
|
|
{
|
|
InitializeComponent();
|
|
|
|
presetCB.Items.Add("Optimal");
|
|
presetCB.SelectedIndex = 0;
|
|
|
|
stPanel1.BackColor = FormThemes.BaseTheme.TextEditorBackColor;
|
|
stPanel2.BackColor = FormThemes.BaseTheme.TextEditorBackColor;
|
|
|
|
CanResize = false;
|
|
}
|
|
|
|
public void LoadMeshes(List<STGenericObject> meshes, List<STGenericMaterial> importedMats,
|
|
List<GFLXMaterialData> originalMaterials, List<GFLXMesh> originalMeshes)
|
|
{
|
|
Loaded = false;
|
|
|
|
Meshes = meshes;
|
|
OriginalMeshes = originalMeshes;
|
|
|
|
foreach (var mat in originalMaterials)
|
|
{
|
|
materiialPresetCB.Items.Add(mat.Text);
|
|
}
|
|
|
|
materiialPresetCB.SelectedIndex = 0;
|
|
|
|
listViewCustom1.Items.Clear();
|
|
for (int i = 0; i < meshes.Count; i++)
|
|
{
|
|
string material = originalMaterials[0].Text;
|
|
|
|
//Check if a material name matches one in the preset list
|
|
//Then auto match the preset
|
|
if (meshes[i].MaterialIndex < importedMats.Count &&
|
|
meshes[i].MaterialIndex > 0)
|
|
{
|
|
string importedMat = importedMats[meshes[i].MaterialIndex].Text;
|
|
if (materiialPresetCB.Items.Contains(importedMat))
|
|
material = importedMat;
|
|
}
|
|
|
|
Settings.MeshSettings.Add(new GfbmdlImportSettings.MeshSetting()
|
|
{
|
|
HasColor1 = meshes[i].HasVertColors,
|
|
HasColor2 = meshes[i].HasVertColors,
|
|
HasTexCoord1 = meshes[i].HasUv0,
|
|
HasTexCoord2 = meshes[i].HasUv1,
|
|
HasTexCoord3 = meshes[i].HasUv2,
|
|
HasNormals = meshes[i].HasNrm,
|
|
HasBoneIndices = meshes[i].HasIndices,
|
|
HasWeights = meshes[i].HasWeights,
|
|
HasBitangents = meshes[i].HasUv0,
|
|
Material = material,
|
|
});
|
|
listViewCustom1.Items.Add($"{meshes[i].ObjectName}");
|
|
}
|
|
|
|
SetDefaultFormats();
|
|
|
|
Loaded = true;
|
|
}
|
|
|
|
private void SetDefaultFormats()
|
|
{
|
|
positionFormatCB.LoadEnum(typeof(BufferFormat));
|
|
positionFormatCB.SelectedItem = BufferFormat.Float;
|
|
|
|
normalFormatCB.LoadEnum(typeof(BufferFormat));
|
|
normalFormatCB.SelectedItem = BufferFormat.HalfFloat;
|
|
|
|
bitangentFormatCB.LoadEnum(typeof(BufferFormat));
|
|
bitangentFormatCB.SelectedItem = BufferFormat.HalfFloat;
|
|
|
|
uv0FormatCB.LoadEnum(typeof(BufferFormat));
|
|
uv0FormatCB.SelectedItem = BufferFormat.Float;
|
|
|
|
uv1FormatCB.LoadEnum(typeof(BufferFormat));
|
|
uv1FormatCB.SelectedItem = BufferFormat.Float;
|
|
|
|
color0FormatCB.LoadEnum(typeof(BufferFormat));
|
|
color0FormatCB.SelectedItem = BufferFormat.Byte;
|
|
|
|
color1FormatCB.LoadEnum(typeof(BufferFormat));
|
|
color1FormatCB.SelectedItem = BufferFormat.Byte;
|
|
|
|
boneFormatCB.LoadEnum(typeof(BufferFormat));
|
|
boneFormatCB.SelectedItem = BufferFormat.Byte;
|
|
|
|
weightFormatCB.LoadEnum(typeof(BufferFormat));
|
|
weightFormatCB.SelectedItem = BufferFormat.BytesAsFloat;
|
|
|
|
tangentFormatCB.LoadEnum(typeof(BufferFormat));
|
|
tangentFormatCB.SelectedItem = BufferFormat.HalfFloat;
|
|
}
|
|
|
|
private void TryMatchOriginal()
|
|
{
|
|
if (OriginalMeshes == null || OriginalMeshes?.Count == 0)
|
|
return;
|
|
|
|
Loaded = false;
|
|
foreach (var mesh in Meshes)
|
|
{
|
|
var matchedMesh = (GFLXMesh)OriginalMeshes.FirstOrDefault(x => x.Text == mesh.ObjectName);
|
|
if (matchedMesh != null)
|
|
{
|
|
int index = Meshes.IndexOf(mesh);
|
|
var setting = Settings.MeshSettings[index];
|
|
|
|
foreach (var attribute in matchedMesh.MeshData.Attributes)
|
|
{
|
|
switch ((VertexType)attribute.VertexType)
|
|
{
|
|
case VertexType.Position:
|
|
setting.PositionFormat = (BufferFormat)attribute.BufferFormat;
|
|
break;
|
|
case VertexType.Normal:
|
|
setting.NormalFormat = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasNormals = true;
|
|
break;
|
|
case VertexType.Color1:
|
|
setting.Color1Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasColor1 = true;
|
|
break;
|
|
case VertexType.Color2:
|
|
setting.Color2Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasColor2 = true;
|
|
break;
|
|
case VertexType.UV1:
|
|
setting.TexCoord1Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasTexCoord1 = true;
|
|
break;
|
|
case VertexType.UV2:
|
|
setting.TexCoord2Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasTexCoord2 = true;
|
|
break;
|
|
case VertexType.UV3:
|
|
setting.TexCoord3Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasTexCoord3 = true;
|
|
break;
|
|
case VertexType.UV4:
|
|
setting.TexCoord4Format = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasTexCoord4 = true;
|
|
break;
|
|
case VertexType.BoneWeight:
|
|
setting.BoneWeightFormat = (BufferFormat)attribute.BufferFormat;
|
|
if (mesh.vertices.FirstOrDefault().boneWeights.Count == 0)
|
|
{
|
|
//Fill weights with 1s
|
|
for (int v = 0; v < mesh.vertices.Count; v++)
|
|
{
|
|
for (int j = 0; j < 1; j++)
|
|
mesh.vertices[v].boneWeights.Add(1);
|
|
}
|
|
}
|
|
setting.HasWeights = true;
|
|
break;
|
|
case VertexType.BoneID:
|
|
setting.BoneIndexFormat = (BufferFormat)attribute.BufferFormat;
|
|
if (mesh.vertices.FirstOrDefault().boneNames.Count == 0)
|
|
{
|
|
//Fill indices with 1s
|
|
for (int v = 0; v < mesh.vertices.Count; v++)
|
|
{
|
|
for (int j = 0; j < 1; j++)
|
|
mesh.vertices[v].boneIds.Add(1);
|
|
}
|
|
}
|
|
setting.HasBoneIndices = true;
|
|
break;
|
|
case VertexType.Tangents:
|
|
setting.TangentsFormat = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasTangents = true;
|
|
break;
|
|
case VertexType.Binormal:
|
|
setting.BitangentnFormat = (BufferFormat)attribute.BufferFormat;
|
|
setting.HasBitangents = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Loaded = true;
|
|
}
|
|
|
|
private void listViewCustom1_SelectedIndexChanged(object sender, EventArgs e) {
|
|
if (!Loaded) return;
|
|
|
|
if (listViewCustom1.SelectedIndices.Count > 0)
|
|
{
|
|
Loaded = false;
|
|
|
|
int index = listViewCustom1.SelectedIndices[0];
|
|
var mesh = Meshes[index];
|
|
|
|
var settings = Settings.MeshSettings[index];
|
|
materiialPresetCB.SelectedItem = settings.Material;
|
|
|
|
UpdateSelectedMesh(settings);
|
|
|
|
Loaded = true;
|
|
}
|
|
}
|
|
|
|
private void ApplySettings(object sender, EventArgs e)
|
|
{
|
|
if (!Loaded) return;
|
|
|
|
var indices = listViewCustom1.SelectedIndices;
|
|
for (int i = 0; i < indices?.Count; i++)
|
|
{
|
|
int index = indices[i];
|
|
var mesh = Meshes[index];
|
|
var settings = Settings.MeshSettings[index];
|
|
|
|
settings.Material = materiialPresetCB.GetSelectedText();
|
|
settings.HasNormals = chkUseNormals.Checked;
|
|
settings.HasBitangents = chkBitangents.Checked;
|
|
settings.HasTexCoord1 = chkHasUv1.Checked;
|
|
settings.HasTexCoord2 = chkHasUv2.Checked;
|
|
settings.HasColor1 = chkUseColor1.Checked;
|
|
settings.HasColor2 = chkUseColor2.Checked;
|
|
settings.HasBoneIndices = chkUseBoneIndex.Checked;
|
|
settings.HasWeights = chkUseBoneWeights.Checked;
|
|
settings.HasTangents = chkTangents.Checked;
|
|
|
|
settings.PositionFormat = (BufferFormat)positionFormatCB.SelectedItem;
|
|
settings.NormalFormat = (BufferFormat)normalFormatCB.SelectedItem;
|
|
settings.BitangentnFormat = (BufferFormat)bitangentFormatCB.SelectedItem;
|
|
settings.TexCoord1Format = (BufferFormat)uv0FormatCB.SelectedItem;
|
|
settings.TexCoord2Format = (BufferFormat)uv1FormatCB.SelectedItem;
|
|
settings.Color1Format = (BufferFormat)color0FormatCB.SelectedItem;
|
|
settings.Color2Format = (BufferFormat)color1FormatCB.SelectedItem;
|
|
settings.BoneIndexFormat = (BufferFormat)boneFormatCB.SelectedItem;
|
|
settings.BoneWeightFormat = (BufferFormat)weightFormatCB.SelectedItem;
|
|
settings.TangentsFormat = (BufferFormat)tangentFormatCB.SelectedItem;
|
|
}
|
|
}
|
|
|
|
private void UpdateSelectedMesh(GfbmdlImportSettings.MeshSetting settings) {
|
|
chkUseNormals.Checked = settings.HasNormals;
|
|
chkBitangents.Checked = settings.HasBitangents;
|
|
chkHasUv1.Checked = settings.HasTexCoord1;
|
|
chkHasUv2.Checked = settings.HasTexCoord2;
|
|
chkUseColor1.Checked = settings.HasColor1;
|
|
chkUseColor2.Checked = settings.HasColor2;
|
|
chkUseBoneIndex.Checked = settings.HasBoneIndices;
|
|
chkUseBoneWeights.Checked = settings.HasWeights;
|
|
chkTangents.Checked = settings.HasTangents;
|
|
|
|
positionFormatCB.SelectedItem = settings.PositionFormat;
|
|
normalFormatCB.SelectedItem = settings.NormalFormat;
|
|
bitangentFormatCB.SelectedItem = settings.BitangentnFormat;
|
|
uv0FormatCB.SelectedItem = settings.TexCoord1Format;
|
|
uv1FormatCB.SelectedItem = settings.TexCoord2Format;
|
|
color0FormatCB.SelectedItem = settings.Color1Format;
|
|
color1FormatCB.SelectedItem = settings.Color2Format;
|
|
boneFormatCB.SelectedItem = settings.BoneIndexFormat;
|
|
weightFormatCB.SelectedItem = settings.BoneWeightFormat;
|
|
tangentFormatCB.SelectedItem = settings.TangentsFormat;
|
|
}
|
|
|
|
private void stButton1_Click(object sender, EventArgs e) {
|
|
if (!Loaded) return;
|
|
|
|
if (listViewCustom1.SelectedIndices.Count == 0) return;
|
|
|
|
OpenFileDialog ofd = new OpenFileDialog();
|
|
ofd.Filter = "Supported Formats|*.json;";
|
|
ofd.DefaultExt = "json";
|
|
if (ofd.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try {
|
|
Newtonsoft.Json.JsonConvert.DeserializeObject<Material>(
|
|
System.IO.File.ReadAllText(ofd.FileName));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
STErrorDialog.Show("Failed to load material!", "GFBMDL Importer", ex.ToString());
|
|
return;
|
|
}
|
|
|
|
string name = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName);
|
|
materiialPresetCB.Items.Add(name);
|
|
|
|
var indices = listViewCustom1.SelectedIndices;
|
|
for (int i = 0; i < indices?.Count; i++)
|
|
{
|
|
var settings = Settings.MeshSettings[indices[i]];
|
|
settings.MaterialFile = ofd.FileName;
|
|
settings.Material = name;
|
|
}
|
|
|
|
materiialPresetCB.SelectedItem = name;
|
|
}
|
|
}
|
|
|
|
private void chkMatchAttributes_CheckedChanged(object sender, EventArgs e) {
|
|
if (chkMatchAttributes.Checked)
|
|
{
|
|
TryMatchOriginal();
|
|
if (listViewCustom1.SelectedIndices.Count > 0)
|
|
{
|
|
int index = listViewCustom1.SelectedIndices[0];
|
|
UpdateSelectedMesh(Settings.MeshSettings[index]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void numericUpDownFloat1_ValueChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|