mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Allow changing skin materials in .mdls in edit mode.
This commit is contained in:
parent
076be3925c
commit
75823d413e
3 changed files with 118 additions and 6 deletions
|
|
@ -39,8 +39,8 @@ namespace Penumbra.Importer
|
|||
private const string Ext = @"\.meta";
|
||||
|
||||
// These are the valid regexes for .meta files that we are able to support at the moment.
|
||||
private static readonly Regex HousingMeta = new( $"bgcommon/hou/{Pt}/general/{Pi}/{Pir}{Ext}" );
|
||||
private static readonly Regex CharaMeta = new( $"chara/{Pt}/{Pp}{Pi}(/obj/{St}/{Sp}{Si})?/{File}{Slot}{Ext}" );
|
||||
private static readonly Regex HousingMeta = new($"bgcommon/hou/{Pt}/general/{Pi}/{Pir}{Ext}");
|
||||
private static readonly Regex CharaMeta = new($"chara/{Pt}/{Pp}{Pi}(/obj/{St}/{Sp}{Si})?/{File}{Slot}{Ext}");
|
||||
|
||||
public readonly ObjectType PrimaryType;
|
||||
public readonly BodySlot SecondaryType;
|
||||
|
|
@ -129,7 +129,7 @@ namespace Penumbra.Importer
|
|||
}
|
||||
|
||||
if( match.Groups[ "SecondaryType" ].Success
|
||||
&& Names.StringToBodySlot.TryGetValue( match.Groups[ "SecondaryType" ].Value, out SecondaryType ) )
|
||||
&& Names.StringToBodySlot.TryGetValue( match.Groups[ "SecondaryType" ].Value, out SecondaryType ) )
|
||||
{
|
||||
SecondaryId = ushort.Parse( match.Groups[ "SecondaryId" ].Value );
|
||||
}
|
||||
|
|
@ -234,8 +234,8 @@ namespace Penumbra.Importer
|
|||
var id = reader.ReadUInt16();
|
||||
var value = reader.ReadUInt16();
|
||||
if( !gr.IsValid()
|
||||
|| info.PrimaryType == ObjectType.Character && info.SecondaryType != BodySlot.Face && info.SecondaryType != BodySlot.Hair
|
||||
|| info.PrimaryType == ObjectType.Equipment && info.EquipSlot != EquipSlot.Head && info.EquipSlot != EquipSlot.Body )
|
||||
|| info.PrimaryType == ObjectType.Character && info.SecondaryType != BodySlot.Face && info.SecondaryType != BodySlot.Hair
|
||||
|| info.PrimaryType == ObjectType.Equipment && info.EquipSlot != EquipSlot.Head && info.EquipSlot != EquipSlot.Body )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -323,7 +323,7 @@ namespace Penumbra.Importer
|
|||
Version = version;
|
||||
}
|
||||
|
||||
public static TexToolsMeta Invalid = new( string.Empty, 0 );
|
||||
public static TexToolsMeta Invalid = new(string.Empty, 0);
|
||||
|
||||
public static TexToolsMeta FromRgspFile( string filePath, byte[] data )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -499,6 +499,42 @@ namespace Penumbra.UI
|
|||
+ "Experimental - Use at own risk!" );
|
||||
}
|
||||
|
||||
private void DrawMaterialChangeButtons()
|
||||
{
|
||||
if( ImGui.Button( "Skin Material B to D" ) )
|
||||
{
|
||||
ModelChanger.ChangeMtrlBToD( Mod!.Data );
|
||||
}
|
||||
ImGuiCustom.HoverTooltip( "Change the skin material all models in this mod reference from B to D.\n"
|
||||
+ "This is usually to convert Bibo+ models to T&F3 skins.\n"
|
||||
+ "This overwrites .mdl files, use at your own risk!" );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Skin Material D to B" ) )
|
||||
{
|
||||
ModelChanger.ChangeMtrlDToB( Mod!.Data );
|
||||
}
|
||||
ImGuiCustom.HoverTooltip( "Change the skin material all models in this mod reference from D to B.\n"
|
||||
+ "This is usually to convert T&F3 models to Bibo+ skins.\n"
|
||||
+ "This overwrites .mdl files, use at your own risk!" );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Skin Material A to E" ) )
|
||||
{
|
||||
ModelChanger.ChangeMtrlAToE( Mod!.Data );
|
||||
}
|
||||
ImGuiCustom.HoverTooltip( "Change the material all models in this mod reference from A to E.\n"
|
||||
+ "This overwrites .mdl files, use at your own risk!" );
|
||||
|
||||
ImGui.SameLine();
|
||||
if( ImGui.Button( "Skin Material E to A" ) )
|
||||
{
|
||||
ModelChanger.ChangeMtrlEToA( Mod!.Data );
|
||||
}
|
||||
ImGuiCustom.HoverTooltip( "Change the material all models in this mod reference from E to A.\n"
|
||||
+ "This overwrites .mdl files, use at your own risk!" );
|
||||
}
|
||||
|
||||
private void DrawEditLine()
|
||||
{
|
||||
DrawOpenModFolderButton();
|
||||
|
|
@ -519,6 +555,8 @@ namespace Penumbra.UI
|
|||
ImGui.SameLine();
|
||||
DrawSplitButton();
|
||||
|
||||
DrawMaterialChangeButtons();
|
||||
|
||||
DrawSortOrder( Mod!.Data, _modManager, _selector );
|
||||
}
|
||||
|
||||
|
|
|
|||
74
Penumbra/Util/ModelChanger.cs
Normal file
74
Penumbra/Util/ModelChanger.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Dalamud.Logging;
|
||||
using Penumbra.Mod;
|
||||
|
||||
namespace Penumbra.Util;
|
||||
|
||||
public static class ModelChanger
|
||||
{
|
||||
private const string SkinMaterialString = "/mt_c0201b0001_d.mtrl";
|
||||
private static readonly byte[] SkinMaterial = Encoding.UTF8.GetBytes( SkinMaterialString );
|
||||
|
||||
public static int ChangeMtrl( FullPath file, byte from, byte to )
|
||||
{
|
||||
if( !file.Exists )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllBytes( file.FullName );
|
||||
var replaced = 0;
|
||||
|
||||
var length = text.Length - SkinMaterial.Length;
|
||||
SkinMaterial[ 15 ] = from;
|
||||
for( var i = 0; i < length; ++i )
|
||||
{
|
||||
if( SkinMaterial.Where( ( t, j ) => text[ i + j ] != t ).Any() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
text[ i + 15 ] = to;
|
||||
i += SkinMaterial.Length;
|
||||
++replaced;
|
||||
}
|
||||
|
||||
if( replaced == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
File.WriteAllBytes( file.FullName, text );
|
||||
return replaced;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
PluginLog.Error( $"Could not write .mdl data for file {file.FullName}, replacing {( char )from} with {( char )to}:\n{e}" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ChangeModMaterials( ModData mod, byte from, byte to )
|
||||
{
|
||||
return mod.Resources.ModFiles
|
||||
.Where( f => f.Extension.Equals( ".mdl", StringComparison.InvariantCultureIgnoreCase ) )
|
||||
.All( file => ChangeMtrl( file, from, to ) >= 0 );
|
||||
}
|
||||
|
||||
public static bool ChangeMtrlBToD( ModData mod )
|
||||
=> ChangeModMaterials( mod, ( byte )'b', ( byte )'d' );
|
||||
|
||||
public static bool ChangeMtrlDToB( ModData mod )
|
||||
=> ChangeModMaterials( mod, ( byte )'d', ( byte )'b' );
|
||||
|
||||
public static bool ChangeMtrlEToA( ModData mod )
|
||||
=> ChangeModMaterials( mod, ( byte )'e', ( byte )'a' );
|
||||
|
||||
public static bool ChangeMtrlAToE( ModData mod )
|
||||
=> ChangeModMaterials( mod, ( byte )'a', ( byte )'e' );
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue