mirror of
https://github.com/ficed/Braver.git
synced 2024-11-23 05:10:08 +00:00
Add CrossSlash command line exporter program
This commit is contained in:
parent
f7c4ae4aed
commit
65275487d4
@ -34,7 +34,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Braver.FFNxCompatibility",
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IrosArchive", "IrosArchive\IrosArchive.csproj", "{803429DC-A6B4-43C2-9F73-D6EA51EA6B99}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Braver.EquipMenuMod", "PluginImplementations\Braver.EquipMenuMod\Braver.EquipMenuMod.csproj", "{A6C5FE20-7D00-4FD9-AE27-65176B098FC7}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Braver.EquipMenuMod", "PluginImplementations\Braver.EquipMenuMod\Braver.EquipMenuMod.csproj", "{A6C5FE20-7D00-4FD9-AE27-65176B098FC7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrossSlash", "CrossSlash\CrossSlash.csproj", "{9A97BA9B-CC8B-4A13-BBB7-5249A6234FD6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -98,6 +100,10 @@ Global
|
||||
{A6C5FE20-7D00-4FD9-AE27-65176B098FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6C5FE20-7D00-4FD9-AE27-65176B098FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6C5FE20-7D00-4FD9-AE27-65176B098FC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A97BA9B-CC8B-4A13-BBB7-5249A6234FD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A97BA9B-CC8B-4A13-BBB7-5249A6234FD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A97BA9B-CC8B-4A13-BBB7-5249A6234FD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A97BA9B-CC8B-4A13-BBB7-5249A6234FD6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
35
CrossSlash/CrossSlash.csproj
Normal file
35
CrossSlash/CrossSlash.csproj
Normal file
@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Terminal.Gui" Version="1.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ficedula.FF7.Exporters\Ficedula.FF7.Exporters.csproj" />
|
||||
<ProjectReference Include="..\Ficedula.FF7\Ficedula.FF7.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
146
CrossSlash/ExportGuiWindow.cs
Normal file
146
CrossSlash/ExportGuiWindow.cs
Normal file
@ -0,0 +1,146 @@
|
||||
// This program and the accompanying materials are made available under the terms of the
|
||||
// Eclipse Public License v2.0 which accompanies this distribution, and is available at
|
||||
// https://www.eclipse.org/legal/epl-v20.html
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace CrossSlash {
|
||||
public class ExportGuiWindow : Window {
|
||||
|
||||
private Label _lblLGP, _lblGLB;
|
||||
private ListView _lvHRCs;
|
||||
private TextView _txtAnims;
|
||||
private List<string> _hrcFiles;
|
||||
|
||||
private string _lgpFile, _glbFile;
|
||||
|
||||
public ExportGuiWindow() {
|
||||
Title = "CrossSlash Exporter (Ctrl-Q to Quit)";
|
||||
|
||||
var btnLGP = new Button {
|
||||
Text = "Select char LGP file",
|
||||
Width = Dim.Percent(25),
|
||||
};
|
||||
btnLGP.Clicked += BtnLGP_Clicked;
|
||||
|
||||
_lblLGP = new Label {
|
||||
Text = "(No LGP selected)",
|
||||
X = Pos.Right(btnLGP) + 1,
|
||||
};
|
||||
|
||||
Label lblHRC = new Label {
|
||||
Y = Pos.Bottom(btnLGP) + 1,
|
||||
Width = Dim.Percent(25),
|
||||
Text = "HRC/Model",
|
||||
};
|
||||
|
||||
_lvHRCs = new ListView {
|
||||
Y = lblHRC.Y,
|
||||
X = Pos.Right(lblHRC),
|
||||
Width = Dim.Fill(1),
|
||||
Height = 8,
|
||||
};
|
||||
|
||||
Label lblAnims = new Label {
|
||||
Width = Dim.Percent(25),
|
||||
Y = Pos.Bottom(_lvHRCs) + 1,
|
||||
Text = "Animations:"
|
||||
};
|
||||
|
||||
_txtAnims = new TextView {
|
||||
X = Pos.Right(lblAnims) + 1,
|
||||
Y = lblAnims.Y,
|
||||
Width = Dim.Fill(),
|
||||
Height = 8,
|
||||
};
|
||||
|
||||
var btnGLB = new Button {
|
||||
Text = "Save GLB As",
|
||||
Width = Dim.Percent(25),
|
||||
Y = Pos.Bottom(_txtAnims) + 1,
|
||||
};
|
||||
btnGLB.Clicked += BtnGLB_Clicked;
|
||||
|
||||
_lblGLB = new Label {
|
||||
X = Pos.Right(btnGLB) + 1,
|
||||
Y = btnGLB.Y,
|
||||
Text = "(No file selected)",
|
||||
};
|
||||
|
||||
var btnExport = new Button {
|
||||
Y = Pos.Bottom(btnGLB) + 1,
|
||||
Width = Dim.Fill(1),
|
||||
Text = "Export"
|
||||
};
|
||||
btnExport.Clicked += BtnExport_Clicked;
|
||||
|
||||
Add(btnLGP, _lblLGP, lblHRC, _lvHRCs, lblAnims, _txtAnims, btnGLB, _lblGLB, btnExport);
|
||||
}
|
||||
|
||||
private void BtnExport_Clicked() {
|
||||
try {
|
||||
var anims = _txtAnims.Text
|
||||
.ToString()
|
||||
.Split('\r', '\n')
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s));
|
||||
|
||||
if (!File.Exists(_lgpFile))
|
||||
throw new Exception("No LGP file selected");
|
||||
if (string.IsNullOrEmpty(_glbFile))
|
||||
throw new Exception("No GLB save as filename selected");
|
||||
if (_lvHRCs.SelectedItem < 0)
|
||||
throw new Exception("No HRC file selected");
|
||||
if (!anims.Any())
|
||||
throw new Exception("No animations specified");
|
||||
|
||||
using (var lgp = new Ficedula.FF7.LGPFile(_lgpFile)) {
|
||||
var exporter = new Ficedula.FF7.Exporters.FieldModel(lgp);
|
||||
var model = exporter.BuildScene(_hrcFiles[_lvHRCs.SelectedItem], anims);
|
||||
model.SaveGLB(_glbFile);
|
||||
}
|
||||
MessageBox.Query("Success", "Export Succeeded", "OK");
|
||||
} catch (Exception ex) {
|
||||
MessageBox.ErrorQuery("Error", ex.Message, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnGLB_Clicked() {
|
||||
var d = new SaveDialog(
|
||||
"Save As", "Save output model to which file",
|
||||
new List<string> { ".glb" }
|
||||
);
|
||||
Application.Run(d);
|
||||
if (!d.Canceled && d.FileName != null) {
|
||||
_lblGLB.Text = _glbFile = (string)d.FilePath;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnLGP_Clicked() {
|
||||
var d = new OpenDialog(
|
||||
"Open LGP", "Choose the char.lgp file to read models from",
|
||||
new List<string> { ".lgp" }
|
||||
);
|
||||
Application.Run(d);
|
||||
if (!d.Canceled && d.FilePaths.Any()) {
|
||||
try {
|
||||
using (var lgp = new Ficedula.FF7.LGPFile(d.FilePaths[0])) {
|
||||
_hrcFiles = lgp.Filenames
|
||||
.Where(s => Path.GetExtension(s).Equals(".hrc", StringComparison.InvariantCultureIgnoreCase))
|
||||
.ToList();
|
||||
_lvHRCs.SetSource(_hrcFiles);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
MessageBox.ErrorQuery("Error", ex.Message, "OK");
|
||||
}
|
||||
_lblLGP.Text = _lgpFile = d.FilePaths[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
CrossSlash/Program.cs
Normal file
34
CrossSlash/Program.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// This program and the accompanying materials are made available under the terms of the
|
||||
// Eclipse Public License v2.0 which accompanies this distribution, and is available at
|
||||
// https://www.eclipse.org/legal/epl-v20.html
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
|
||||
using CrossSlash;
|
||||
using Terminal.Gui;
|
||||
|
||||
Console.WriteLine("CrossSlash");
|
||||
|
||||
switch (args.Length) {
|
||||
case 0:
|
||||
Application.Run<ExportGuiWindow>();
|
||||
Application.Shutdown();
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
Console.WriteLine("USAGE: CrossSlash [OutputGLBFile] [LGPFile] [HRCFile] [Anim] [Anim] [Anim]...");
|
||||
Console.WriteLine(@"e.g. CrossSlash C:\temp\tifa.glb C:\games\FF7\data\field\char.lgp AAGB.HRC ABCD.a ABCE.a");
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"Opening LGP {args[1]}...");
|
||||
using (var lgp = new Ficedula.FF7.LGPFile(args[1])) {
|
||||
var exporter = new Ficedula.FF7.Exporters.FieldModel(lgp);
|
||||
Console.WriteLine($"Exporting model {args[2]}...");
|
||||
var model = exporter.BuildScene(args[2], args.Skip(3));
|
||||
Console.WriteLine($"Saving output to {args[0]}...");
|
||||
model.SaveGLB(args[0]);
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
break;
|
||||
}
|
18
CrossSlash/Properties/PublishProfiles/FolderProfile.pubxml
Normal file
18
CrossSlash/Properties/PublishProfiles/FolderProfile.pubxml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\net7.0-windows\publish\win-x64\</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishReadyToRun>false</PublishReadyToRun>
|
||||
</PropertyGroup>
|
||||
</Project>
|
63
CrossSlash/Properties/Resources.Designer.cs
generated
Normal file
63
CrossSlash/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace CrossSlash.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CrossSlash.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
CrossSlash/Properties/Resources.resx
Normal file
101
CrossSlash/Properties/Resources.resx
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
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">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</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.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:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<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" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</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>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
7
CrossSlash/Properties/launchSettings.json
Normal file
7
CrossSlash/Properties/launchSettings.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"profiles": {
|
||||
"CrossSlash": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user