Fix some stuff.

This commit is contained in:
Ottermandias 2022-08-23 17:49:14 +02:00
parent cfeb20a18e
commit 674dc03f46
11 changed files with 130 additions and 75 deletions

View file

@ -135,7 +135,7 @@ public partial class ModCollection
var settings = _settings[ idx ];
if( settings != null )
{
_unusedSettings.Add( mod.ModPath.Name, new ModSettings.SavedSettings( settings, mod ) );
_unusedSettings[mod.ModPath.Name] = new ModSettings.SavedSettings( settings, mod );
}
_settings.RemoveAt( idx );

View file

@ -46,7 +46,9 @@ public class DdsFile
ParseType.R8G8B8A8 => Header.Height * Header.Width * 4,
ParseType.B8G8R8A8 => Header.Height * Header.Width * 4,
_ => throw new ArgumentOutOfRangeException( nameof( ParseType ), ParseType, null ),
ParseType.A16B16G16R16F => Header.Height * Header.Width * 8,
_ => throw new ArgumentOutOfRangeException( nameof( ParseType ), ParseType, null ),
};
if( Header.MipMapCount < level )
@ -89,25 +91,26 @@ public class DdsFile
return ParseType switch
{
ParseType.Unsupported => Array.Empty< byte >(),
ParseType.DXT1 => ImageParsing.DecodeDxt1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.DXT3 => ImageParsing.DecodeDxt3( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.DXT5 => ImageParsing.DecodeDxt5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.BC4 => ImageParsing.DecodeBc4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.BC5 => ImageParsing.DecodeBc5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.Greyscale => ImageParsing.DecodeUncompressedGreyscale( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R4G4B4A4 => ImageParsing.DecodeUncompressedR4G4B4A4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B4G4R4A4 => ImageParsing.DecodeUncompressedB4G4R4A4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G5B5 => ImageParsing.DecodeUncompressedR5G5B5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G5R5 => ImageParsing.DecodeUncompressedB5G5R5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G6B5 => ImageParsing.DecodeUncompressedR5G6B5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G6R5 => ImageParsing.DecodeUncompressedB5G6R5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G5B5A1 => ImageParsing.DecodeUncompressedR5G5B5A1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G5R5A1 => ImageParsing.DecodeUncompressedB5G5R5A1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R8G8B8 => ImageParsing.DecodeUncompressedR8G8B8( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B8G8R8 => ImageParsing.DecodeUncompressedB8G8R8( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R8G8B8A8 => _data.Length == Header.Width * Header.Height * 4 ? _data : _data[ ..( Header.Width * Header.Height * 4 ) ],
ParseType.B8G8R8A8 => ImageParsing.DecodeUncompressedB8G8R8A8( MipMap( 0 ), Header.Height, Header.Width ),
_ => throw new ArgumentOutOfRangeException(),
ParseType.DXT1 => ImageParsing.DecodeDxt1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.DXT3 => ImageParsing.DecodeDxt3( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.DXT5 => ImageParsing.DecodeDxt5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.BC4 => ImageParsing.DecodeBc4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.BC5 => ImageParsing.DecodeBc5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.Greyscale => ImageParsing.DecodeUncompressedGreyscale( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R4G4B4A4 => ImageParsing.DecodeUncompressedR4G4B4A4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B4G4R4A4 => ImageParsing.DecodeUncompressedB4G4R4A4( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G5B5 => ImageParsing.DecodeUncompressedR5G5B5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G5R5 => ImageParsing.DecodeUncompressedB5G5R5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G6B5 => ImageParsing.DecodeUncompressedR5G6B5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G6R5 => ImageParsing.DecodeUncompressedB5G6R5( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R5G5B5A1 => ImageParsing.DecodeUncompressedR5G5B5A1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B5G5R5A1 => ImageParsing.DecodeUncompressedB5G5R5A1( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R8G8B8 => ImageParsing.DecodeUncompressedR8G8B8( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.B8G8R8 => ImageParsing.DecodeUncompressedB8G8R8( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.R8G8B8A8 => _data.Length == Header.Width * Header.Height * 4 ? _data : _data[ ..( Header.Width * Header.Height * 4 ) ],
ParseType.B8G8R8A8 => ImageParsing.DecodeUncompressedB8G8R8A8( MipMap( 0 ), Header.Height, Header.Width ),
ParseType.A16B16G16R16F => ImageParsing.DecodeUncompressedA16B16G16R16F( MipMap( 0 ), Header.Height, Header.Width ),
_ => throw new ArgumentOutOfRangeException(),
};
}
@ -126,6 +129,12 @@ public class DdsFile
var dxt10 = header.PixelFormat.FourCC == PixelFormat.FourCCType.DX10 ? ( DXT10Header? )br.ReadStructure< DXT10Header >() : null;
var type = header.PixelFormat.ToParseType( dxt10 );
if( type == ParseType.Unsupported )
{
PluginLog.Error( "DDS format unsupported." );
return false;
}
file = new DdsFile( type, header, br.ReadBytes( ( int )( br.BaseStream.Length - br.BaseStream.Position ) ), dxt10 );
return true;
}

View file

@ -577,4 +577,25 @@ public static partial class ImageParsing
return ret;
}
public static unsafe byte[] DecodeUncompressedA16B16G16R16F( ReadOnlySpan< byte > data, int height, int width )
{
Verify( data, height, width, 1, 8 );
var ret = new byte[data.Length / 2];
fixed( byte* r = ret, d = data )
{
var ptr = r;
var input = ( Half* )d;
var end = (Half*) (d + data.Length);
while( input != end )
{
*ptr++ = ( byte )( byte.MaxValue * (float) *input++ );
*ptr++ = ( byte )( byte.MaxValue * (float) *input++ );
*ptr++ = ( byte )( byte.MaxValue * (float) *input++ );
*ptr++ = ( byte )( byte.MaxValue * (float) *input++ );
}
}
return ret;
}
}

View file

@ -26,6 +26,8 @@ public enum ParseType
B8G8R8,
R8G8B8A8,
B8G8R8A8,
A16B16G16R16F,
}
[StructLayout( LayoutKind.Sequential )]
@ -54,23 +56,23 @@ public struct PixelFormat
public enum FourCCType : uint
{
NoCompression = 0,
DXT1 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '1' << 24 ),
DXT2 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '2' << 24 ),
DXT3 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '3' << 24 ),
DXT4 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '4' << 24 ),
DXT5 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '5' << 24 ),
DX10 = 'D' | ( 'X' << 8 ) | ( '1' << 16 ) | ( '0' << 24 ),
ATI1 = 'A' | ( 'T' << 8 ) | ( 'I' << 16 ) | ( '1' << 24 ),
BC4U = 'B' | ( 'C' << 8 ) | ( '4' << 16 ) | ( 'U' << 24 ),
BC45 = 'B' | ( 'C' << 8 ) | ( '4' << 16 ) | ( '5' << 24 ),
ATI2 = 'A' | ( 'T' << 8 ) | ( 'I' << 16 ) | ( '2' << 24 ),
BC5U = 'B' | ( 'C' << 8 ) | ( '5' << 16 ) | ( 'U' << 24 ),
BC55 = 'B' | ( 'C' << 8 ) | ( '5' << 16 ) | ( '5' << 24 ),
NoCompression = 0,
DXT1 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '1' << 24 ),
DXT2 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '2' << 24 ),
DXT3 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '3' << 24 ),
DXT4 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '4' << 24 ),
DXT5 = 'D' | ( 'X' << 8 ) | ( 'T' << 16 ) | ( '5' << 24 ),
DX10 = 'D' | ( 'X' << 8 ) | ( '1' << 16 ) | ( '0' << 24 ),
ATI1 = 'A' | ( 'T' << 8 ) | ( 'I' << 16 ) | ( '1' << 24 ),
BC4U = 'B' | ( 'C' << 8 ) | ( '4' << 16 ) | ( 'U' << 24 ),
BC45 = 'B' | ( 'C' << 8 ) | ( '4' << 16 ) | ( '5' << 24 ),
ATI2 = 'A' | ( 'T' << 8 ) | ( 'I' << 16 ) | ( '2' << 24 ),
BC5U = 'B' | ( 'C' << 8 ) | ( '5' << 16 ) | ( 'U' << 24 ),
BC55 = 'B' | ( 'C' << 8 ) | ( '5' << 16 ) | ( '5' << 24 ),
D3D_A16B16G16R16 = 113,
}
public void Write( BinaryWriter bw )
{
bw.Write( Size );
@ -87,20 +89,21 @@ public struct PixelFormat
{
return FourCC switch
{
FourCCType.NoCompression => HandleUncompressed(),
FourCCType.DXT1 => ParseType.DXT1,
FourCCType.DXT2 => ParseType.Unsupported,
FourCCType.DXT3 => ParseType.DXT3,
FourCCType.DXT4 => ParseType.Unsupported,
FourCCType.DXT5 => ParseType.DXT5,
FourCCType.DX10 => dxt10?.ToParseType() ?? ParseType.Unsupported,
FourCCType.ATI1 => ParseType.BC4,
FourCCType.BC4U => ParseType.BC4,
FourCCType.BC45 => ParseType.BC4,
FourCCType.ATI2 => ParseType.BC5,
FourCCType.BC5U => ParseType.BC5,
FourCCType.BC55 => ParseType.BC5,
_ => ParseType.Unsupported,
FourCCType.NoCompression => HandleUncompressed(),
FourCCType.DXT1 => ParseType.DXT1,
FourCCType.DXT2 => ParseType.Unsupported,
FourCCType.DXT3 => ParseType.DXT3,
FourCCType.DXT4 => ParseType.Unsupported,
FourCCType.DXT5 => ParseType.DXT5,
FourCCType.DX10 => dxt10?.ToParseType() ?? ParseType.Unsupported,
FourCCType.ATI1 => ParseType.BC4,
FourCCType.BC4U => ParseType.BC4,
FourCCType.BC45 => ParseType.BC4,
FourCCType.ATI2 => ParseType.BC5,
FourCCType.BC5U => ParseType.BC5,
FourCCType.BC55 => ParseType.BC5,
FourCCType.D3D_A16B16G16R16 => ParseType.A16B16G16R16F,
_ => ParseType.Unsupported,
};
}

View file

@ -8,7 +8,7 @@ namespace Penumbra.Interop;
public unsafe class CharacterUtility : IDisposable
{
// A static pointer to the CharacterUtility address.
[Signature( "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? 00 48 8D 8E ?? ?? 00 00 E8 ?? ?? ?? 00 33 D2", ScanType = ScanType.StaticAddress )]
[Signature( "48 8B 05 ?? ?? ?? ?? 83 B9", ScanType = ScanType.StaticAddress )]
private readonly Structs.CharacterUtility** _characterUtilityAddress = null;
// Only required for migration anymore.

View file

@ -173,7 +173,7 @@ public unsafe partial class PathResolver
// so we always keep track of the current GameObject to be able to link it to the DrawObject.
private delegate void EnableDrawDelegate( IntPtr gameObject, IntPtr b, IntPtr c, IntPtr d );
[Signature( "E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9 74 ?? 33 D2 E8 ?? ?? ?? ?? 84 C0", DetourName = nameof( EnableDrawDetour ) )]
[Signature( "E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9 74 33 45 33 C0", DetourName = nameof( EnableDrawDetour ) )]
private readonly Hook< EnableDrawDelegate > _enableDrawHook = null!;
private void EnableDrawDetour( IntPtr gameObject, IntPtr b, IntPtr c, IntPtr d )

View file

@ -1,10 +1,12 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Component.GUI;
using Lumina.Excel.GeneratedSheets;
using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
@ -15,6 +17,9 @@ namespace Penumbra.Interop.Resolver;
public unsafe partial class PathResolver
{
[Signature( "0F B7 0D ?? ?? ?? ?? C7 85", ScanType = ScanType.StaticAddress )]
private static ushort* _inspectTitleId = null!;
// Obtain the name of the current player, if one exists.
private static string? GetPlayerName()
=> Dalamud.Objects[ 0 ]?.Name.ToString();
@ -34,17 +39,14 @@ public unsafe partial class PathResolver
}
var ui = ( AtkUnitBase* )addon;
if( ui->UldManager.NodeListCount < 60 )
if( ui->UldManager.NodeListCount <= 60 )
{
return null;
}
var text = ( AtkTextNode* )ui->UldManager.NodeList[ 59 ];
if( text == null || !text->AtkResNode.IsVisible )
{
text = ( AtkTextNode* )ui->UldManager.NodeList[ 60 ];
}
var nodeId = Dalamud.GameData.GetExcelSheet< Title >()?.GetRow( *_inspectTitleId )?.IsPrefix == true ? 59 : 60;
var text = ( AtkTextNode* )ui->UldManager.NodeList[ nodeId ];
return text != null ? text->NodeText.ToString() : null;
}

View file

@ -242,7 +242,14 @@ public partial class ModEditWindow
if( data != null )
{
wrap = Dalamud.PluginInterface.UiBuilder.LoadImageRaw( data, width, height, 4 );
try
{
wrap = Dalamud.PluginInterface.UiBuilder.LoadImageRaw( data, width, height, 4 );
}
catch( Exception e )
{
PluginLog.Error( $"Could not load raw image:\n{e}" );
}
}
UpdateCenter();
@ -356,7 +363,10 @@ public partial class ModEditWindow
if( wrap != null )
{
ImGui.TextUnformatted( $"Image Dimensions: {wrap.Width} x {wrap.Height}" );
size = size with { Y = wrap.Height * size.X / wrap.Width };
size = size.X < wrap.Width
? size with { Y = wrap.Height * size.X / wrap.Width }
: new Vector2( wrap.Width, wrap.Height );
ImGui.Image( wrap.ImGuiHandle, size );
}
else if( path.Length > 0 )
@ -425,8 +435,10 @@ public partial class ModEditWindow
return;
}
var leftRightWidth = new Vector2( ( ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - ImGui.GetStyle().FramePadding.X * 4 ) / 3, -1 );
var imageSize = new Vector2( leftRightWidth.X - ImGui.GetStyle().FramePadding.X * 2 );
var leftRightWidth =
new Vector2(
( ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - ImGui.GetStyle().FramePadding.X * 4 ) / 3, -1 );
var imageSize = new Vector2( leftRightWidth.X - ImGui.GetStyle().FramePadding.X * 2 );
using( var child = ImRaii.Child( "ImageLeft", leftRightWidth, true ) )
{
if( child )

View file

@ -200,9 +200,9 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
private void AddImportModButton( Vector2 size )
{
var button = ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size,
"Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true );
"Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true );
ConfigWindow.OpenTutorial( ConfigWindow.BasicTutorialSteps.ModImport );
if (!button)
if( !button )
{
return;
}
@ -212,15 +212,16 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
: Penumbra.Config.ModDirectory.Length > 0 ? Penumbra.Config.ModDirectory : null;
_hasSetFolder = true;
_fileManager.OpenFileDialog( "Import Mod Pack", "Mod Packs{.ttmp,.ttmp2,.zip,.7z,.rar},TexTools Mod Packs{.ttmp,.ttmp2},Archives{.zip,.7z,.rar}", ( s, f ) =>
{
if( s )
_fileManager.OpenFileDialog( "Import Mod Pack",
"Mod Packs{.ttmp,.ttmp2,.zip,.7z,.rar},TexTools Mod Packs{.ttmp,.ttmp2},Archives{.zip,.7z,.rar}", ( s, f ) =>
{
_import = new TexToolsImporter( Penumbra.ModManager.BasePath, f.Count, f.Select( file => new FileInfo( file ) ),
AddNewMod );
ImGui.OpenPopup( "Import Status" );
}
}, 0, modPath );
if( s )
{
_import = new TexToolsImporter( Penumbra.ModManager.BasePath, f.Count, f.Select( file => new FileInfo( file ) ),
AddNewMod );
ImGui.OpenPopup( "Import Status" );
}
}, 0, modPath );
}
// Draw the progress information for import.
@ -312,13 +313,20 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
{
ImGui.OpenPopup( "ExtendedHelp" );
}
ConfigWindow.OpenTutorial( ConfigWindow.BasicTutorialSteps.AdvancedHelp );
}
// Helpers.
private static void SetDescendants( ModFileSystem.Folder folder, bool enabled, bool inherit = false )
{
var mods = folder.GetAllDescendants( ISortMode< Mod >.Lexicographical ).OfType< ModFileSystem.Leaf >().Select( l => l.Value );
var mods = folder.GetAllDescendants( ISortMode< Mod >.Lexicographical ).OfType< ModFileSystem.Leaf >().Select( l =>
{
// Any mod handled here should not stay new.
Penumbra.ModManager.NewMods.Remove( l.Value );
return l.Value;
} );
if( inherit )
{
Penumbra.CollectionManager.Current.SetMultipleModInheritances( mods, enabled );

View file

@ -126,8 +126,8 @@ public partial class ConfigWindow
_currentPriority = null;
}
ImGuiUtil.LabeledHelpMarker( "Priority", "Mods with higher priority take precedence before Mods with lower priority.\n"
+ "That means, if Mod A should overwrite changes from Mod B, Mod A should have higher priority than Mod B." );
ImGuiUtil.LabeledHelpMarker( "Priority", "Mods with a higher number here take precedence before Mods with a lower number.\n"
+ "That means, if Mod A should overwrite changes from Mod B, Mod A should have a higher priority number than Mod B." );
}
// Draw a button to remove the current settings and inherit them instead

View file

@ -88,7 +88,7 @@ public partial class ConfigWindow
return;
}
ImGui.TextWrapped( _mod.Description );
ImGuiUtil.TextWrapped( _mod.Description );
}
// A simple clipped list of changed items.