Merge branch 'master' into Textures

This commit is contained in:
Ottermandias 2022-09-22 18:52:54 +02:00
commit 4b7315d364
18 changed files with 184 additions and 87 deletions

@ -1 +1 @@
Subproject commit 98064e790042c90c82a58fbfa79201bd69800758 Subproject commit c84ff1b1c313c5f4ae28645a2e3fcb4d214f240a

View file

@ -39,6 +39,8 @@ public partial class Configuration : IPluginConfiguration
public bool PreferNamedCollectionsOverOwners { get; set; } = true; public bool PreferNamedCollectionsOverOwners { get; set; } = true;
public bool UseDefaultCollectionForRetainers { get; set; } = false; public bool UseDefaultCollectionForRetainers { get; set; } = false;
public bool HideRedrawBar { get; set; } = false;
#if DEBUG #if DEBUG
public bool DebugMode { get; set; } = true; public bool DebugMode { get; set; } = true;
#else #else

View file

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Newtonsoft.Json; using Newtonsoft.Json;
using OtterGui;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Util; using Penumbra.Util;
using SharpCompress.Archives.Zip; using SharpCompress.Archives.Zip;
@ -166,16 +167,17 @@ public partial class TexToolsImporter
: ( 1 + allOptions.Count / IModGroup.MaxMultiOptions, IModGroup.MaxMultiOptions ); : ( 1 + allOptions.Count / IModGroup.MaxMultiOptions, IModGroup.MaxMultiOptions );
_currentGroupName = GetGroupName( group.GroupName, groupNames ); _currentGroupName = GetGroupName( group.GroupName, groupNames );
var optionIdx = 0; var optionIdx = 0;
for( var groupId = 0; groupId < numGroups; ++groupId ) for( var groupId = 0; groupId < numGroups; ++groupId )
{ {
var name = numGroups == 1 ? _currentGroupName : $"{_currentGroupName}, Part {groupId + 1}"; var name = numGroups == 1 ? _currentGroupName : $"{_currentGroupName}, Part {groupId + 1}";
options.Clear(); options.Clear();
var description = new StringBuilder(); var description = new StringBuilder();
var groupFolder = Mod.NewSubFolderName( _currentModDirectory, name ) var groupFolder = Mod.NewSubFolderName( _currentModDirectory, name )
?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName, ?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName,
numGroups == 1 ? $"Group {groupPriority + 1}" : $"Group {groupPriority + 1}, Part {groupId + 1}" ) ); numGroups == 1 ? $"Group {groupPriority + 1}" : $"Group {groupPriority + 1}, Part {groupId + 1}" ) );
uint? defaultSettings = group.SelectionType == SelectType.Multi ? 0u : null;
for( var i = 0; i + optionIdx < allOptions.Count && i < maxOptions; ++i ) for( var i = 0; i + optionIdx < allOptions.Count && i < maxOptions; ++i )
{ {
var option = allOptions[ i + optionIdx ]; var option = allOptions[ i + optionIdx ];
@ -191,6 +193,13 @@ public partial class TexToolsImporter
description.Append( '\n' ); description.Append( '\n' );
} }
if( option.IsChecked )
{
defaultSettings = group.SelectionType == SelectType.Multi
? ( defaultSettings!.Value | ( 1u << i ) )
: ( uint )i;
}
++_currentOptionIdx; ++_currentOptionIdx;
} }
@ -205,11 +214,12 @@ public partial class TexToolsImporter
{ {
_currentOptionName = empty.Name; _currentOptionName = empty.Name;
options.Insert( 0, Mod.CreateEmptySubMod( empty.Name ) ); options.Insert( 0, Mod.CreateEmptySubMod( empty.Name ) );
defaultSettings = defaultSettings == null ? 0 : defaultSettings.Value + 1;
} }
} }
Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority, Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority,
description.ToString(), options ); defaultSettings ?? 0, description.ToString(), options );
++groupPriority; ++groupPriority;
} }
} }

View file

@ -37,14 +37,7 @@ public partial class Mod
} }
Penumbra.ModManager.OptionSetFiles( _mod, _subMod.GroupIdx, _subMod.OptionIdx, dict ); Penumbra.ModManager.OptionSetFiles( _mod, _subMod.GroupIdx, _subMod.OptionIdx, dict );
if( num > 0 ) UpdateFiles();
{
RevertFiles();
}
else
{
FileChanges = false;
}
return num; return num;
} }

View file

@ -98,7 +98,7 @@ public partial class Mod
{ {
void HandleSubMod( ISubMod mod, int groupIdx, int optionIdx ) void HandleSubMod( ISubMod mod, int groupIdx, int optionIdx )
{ {
var newDict = mod.Files.Where( kvp => CheckAgainstMissing( kvp.Value, kvp.Key ) ) var newDict = mod.Files.Where( kvp => CheckAgainstMissing( kvp.Value, kvp.Key, mod == _subMod ) )
.ToDictionary( kvp => kvp.Key, kvp => kvp.Value ); .ToDictionary( kvp => kvp.Key, kvp => kvp.Value );
if( newDict.Count != mod.Files.Count ) if( newDict.Count != mod.Files.Count )
{ {
@ -110,13 +110,18 @@ public partial class Mod
_missingFiles.Clear(); _missingFiles.Clear();
} }
private bool CheckAgainstMissing( FullPath file, Utf8GamePath key ) private bool CheckAgainstMissing( FullPath file, Utf8GamePath key, bool removeUsed )
{ {
if( !_missingFiles.Contains( file ) ) if( !_missingFiles.Contains( file ) )
{ {
return true; return true;
} }
if( removeUsed )
{
_usedPaths.Remove( key );
}
Penumbra.Log.Debug( $"[RemoveMissingPaths] Removing {key} -> {file} from {_mod.Name}." ); Penumbra.Log.Debug( $"[RemoveMissingPaths] Removing {key} -> {file} from {_mod.Name}." );
return false; return false;
} }

View file

@ -28,6 +28,18 @@ public sealed partial class Mod
ModOptionChanged.Invoke( ModOptionChangeType.GroupTypeChanged, mod, groupIdx, -1, -1 ); ModOptionChanged.Invoke( ModOptionChangeType.GroupTypeChanged, mod, groupIdx, -1, -1 );
} }
public void ChangeModGroupDefaultOption( Mod mod, int groupIdx, uint defaultOption )
{
var group = mod._groups[groupIdx];
if( group.DefaultSettings == defaultOption )
{
return;
}
group.DefaultSettings = defaultOption;
ModOptionChanged.Invoke( ModOptionChangeType.DefaultOptionChanged, mod, groupIdx, -1, -1 );
}
public void RenameModGroup( Mod mod, int groupIdx, string newName ) public void RenameModGroup( Mod mod, int groupIdx, string newName )
{ {
var group = mod._groups[ groupIdx ]; var group = mod._groups[ groupIdx ];

View file

@ -17,6 +17,7 @@ public enum ModOptionChangeType
OptionMetaChanged, OptionMetaChanged,
DisplayChange, DisplayChange,
PrepareChange, PrepareChange,
DefaultOptionChanged,
} }
public static class ModOptionChangeTypeExtension public static class ModOptionChangeTypeExtension
@ -30,21 +31,22 @@ public static class ModOptionChangeTypeExtension
{ {
( requiresSaving, requiresReloading, wasPrepared ) = type switch ( requiresSaving, requiresReloading, wasPrepared ) = type switch
{ {
ModOptionChangeType.GroupRenamed => ( true, false, false ), ModOptionChangeType.GroupRenamed => ( true, false, false ),
ModOptionChangeType.GroupAdded => ( true, false, false ), ModOptionChangeType.GroupAdded => ( true, false, false ),
ModOptionChangeType.GroupDeleted => ( true, true, false ), ModOptionChangeType.GroupDeleted => ( true, true, false ),
ModOptionChangeType.GroupMoved => ( true, false, false ), ModOptionChangeType.GroupMoved => ( true, false, false ),
ModOptionChangeType.GroupTypeChanged => ( true, true, true ), ModOptionChangeType.GroupTypeChanged => ( true, true, true ),
ModOptionChangeType.PriorityChanged => ( true, true, true ), ModOptionChangeType.PriorityChanged => ( true, true, true ),
ModOptionChangeType.OptionAdded => ( true, true, true ), ModOptionChangeType.OptionAdded => ( true, true, true ),
ModOptionChangeType.OptionDeleted => ( true, true, false ), ModOptionChangeType.OptionDeleted => ( true, true, false ),
ModOptionChangeType.OptionMoved => ( true, false, false ), ModOptionChangeType.OptionMoved => ( true, false, false ),
ModOptionChangeType.OptionFilesChanged => ( false, true, false ), ModOptionChangeType.OptionFilesChanged => ( false, true, false ),
ModOptionChangeType.OptionFilesAdded => ( false, true, true ), ModOptionChangeType.OptionFilesAdded => ( false, true, true ),
ModOptionChangeType.OptionSwapsChanged => ( false, true, false ), ModOptionChangeType.OptionSwapsChanged => ( false, true, false ),
ModOptionChangeType.OptionMetaChanged => ( false, true, false ), ModOptionChangeType.OptionMetaChanged => ( false, true, false ),
ModOptionChangeType.DisplayChange => ( false, false, false ), ModOptionChangeType.DisplayChange => ( false, false, false ),
_ => ( false, false, false ), ModOptionChangeType.DefaultOptionChanged => ( true, false, false ),
_ => ( false, false, false ),
}; };
} }
} }

View file

@ -63,7 +63,7 @@ public partial class Mod
// Create a file for an option group from given data. // Create a file for an option group from given data.
internal static void CreateOptionGroup( DirectoryInfo baseFolder, SelectType type, string name, internal static void CreateOptionGroup( DirectoryInfo baseFolder, SelectType type, string name,
int priority, int index, string desc, IEnumerable< ISubMod > subMods ) int priority, int index, uint defaultSettings, string desc, IEnumerable< ISubMod > subMods )
{ {
switch( type ) switch( type )
{ {
@ -71,9 +71,10 @@ public partial class Mod
{ {
var group = new MultiModGroup() var group = new MultiModGroup()
{ {
Name = name, Name = name,
Description = desc, Description = desc,
Priority = priority, Priority = priority,
DefaultSettings = defaultSettings,
}; };
group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) ); group.PrioritizedOptions.AddRange( subMods.OfType< SubMod >().Select( ( s, idx ) => ( s, idx ) ) );
IModGroup.Save( group, baseFolder, index ); IModGroup.Save( group, baseFolder, index );
@ -83,9 +84,10 @@ public partial class Mod
{ {
var group = new SingleModGroup() var group = new SingleModGroup()
{ {
Name = name, Name = name,
Description = desc, Description = desc,
Priority = priority, Priority = priority,
DefaultSettings = defaultSettings,
}; };
group.OptionData.AddRange( subMods.OfType< SubMod >() ); group.OptionData.AddRange( subMods.OfType< SubMod >() );
IModGroup.Save( group, baseFolder, index ); IModGroup.Save( group, baseFolder, index );

View file

@ -20,6 +20,7 @@ public interface IModGroup : IEnumerable< ISubMod >
public string Description { get; } public string Description { get; }
public SelectType Type { get; } public SelectType Type { get; }
public int Priority { get; } public int Priority { get; }
public uint DefaultSettings { get; set; }
public int OptionPriority( Index optionIdx ); public int OptionPriority( Index optionIdx );
@ -60,7 +61,8 @@ public interface IModGroup : IEnumerable< ISubMod >
public static void SaveDelayed( IModGroup group, DirectoryInfo basePath, int groupIdx ) public static void SaveDelayed( IModGroup group, DirectoryInfo basePath, int groupIdx )
{ {
Penumbra.Framework.RegisterDelayed( $"{nameof( SaveModGroup )}_{basePath.Name}_{group.Name}", () => SaveModGroup( group, basePath, groupIdx ) ); Penumbra.Framework.RegisterDelayed( $"{nameof( SaveModGroup )}_{basePath.Name}_{group.Name}",
() => SaveModGroup( group, basePath, groupIdx ) );
} }
public static void Save( IModGroup group, DirectoryInfo basePath, int groupIdx ) public static void Save( IModGroup group, DirectoryInfo basePath, int groupIdx )
@ -82,6 +84,8 @@ public interface IModGroup : IEnumerable< ISubMod >
j.WriteValue( group.Priority ); j.WriteValue( group.Priority );
j.WritePropertyName( nameof( Type ) ); j.WritePropertyName( nameof( Type ) );
j.WriteValue( group.Type.ToString() ); j.WriteValue( group.Type.ToString() );
j.WritePropertyName( nameof( group.DefaultSettings ) );
j.WriteValue( group.DefaultSettings );
j.WritePropertyName( "Options" ); j.WritePropertyName( "Options" );
j.WriteStartArray(); j.WriteStartArray();
for( var idx = 0; idx < group.Count; ++idx ) for( var idx = 0; idx < group.Count; ++idx )
@ -96,5 +100,5 @@ public interface IModGroup : IEnumerable< ISubMod >
public IModGroup Convert( SelectType type ); public IModGroup Convert( SelectType type );
public bool MoveOption( int optionIdxFrom, int optionIdxTo ); public bool MoveOption( int optionIdxFrom, int optionIdxTo );
public void UpdatePositions(int from = 0); public void UpdatePositions( int from = 0 );
} }

View file

@ -2,6 +2,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui; using OtterGui;
@ -20,6 +21,7 @@ public partial class Mod
public string Name { get; set; } = "Group"; public string Name { get; set; } = "Group";
public string Description { get; set; } = "A non-exclusive group of settings."; public string Description { get; set; } = "A non-exclusive group of settings.";
public int Priority { get; set; } public int Priority { get; set; }
public uint DefaultSettings { get; set; }
public int OptionPriority( Index idx ) public int OptionPriority( Index idx )
=> PrioritizedOptions[ idx ].Priority; => PrioritizedOptions[ idx ].Priority;
@ -44,9 +46,10 @@ public partial class Mod
var options = json[ "Options" ]; var options = json[ "Options" ];
var ret = new MultiModGroup() var ret = new MultiModGroup()
{ {
Name = json[ nameof( Name ) ]?.ToObject< string >() ?? string.Empty, Name = json[ nameof( Name ) ]?.ToObject< string >() ?? string.Empty,
Description = json[ nameof( Description ) ]?.ToObject< string >() ?? string.Empty, Description = json[ nameof( Description ) ]?.ToObject< string >() ?? string.Empty,
Priority = json[ nameof( Priority ) ]?.ToObject< int >() ?? 0, Priority = json[ nameof( Priority ) ]?.ToObject< int >() ?? 0,
DefaultSettings = json[ nameof( DefaultSettings ) ]?.ToObject< uint >() ?? 0,
}; };
if( ret.Name.Length == 0 ) if( ret.Name.Length == 0 )
{ {
@ -71,6 +74,8 @@ public partial class Mod
} }
} }
ret.DefaultSettings = (uint) (ret.DefaultSettings & ( ( 1ul << ret.Count ) - 1 ));
return ret; return ret;
} }
@ -82,9 +87,10 @@ public partial class Mod
case SelectType.Single: case SelectType.Single:
var multi = new SingleModGroup() var multi = new SingleModGroup()
{ {
Name = Name, Name = Name,
Description = Description, Description = Description,
Priority = Priority, Priority = Priority,
DefaultSettings = ( uint )Math.Max( Math.Min( Count - 1, BitOperations.TrailingZeroCount( DefaultSettings) ), 0 ),
}; };
multi.OptionData.AddRange( PrioritizedOptions.Select( p => p.Mod ) ); multi.OptionData.AddRange( PrioritizedOptions.Select( p => p.Mod ) );
return multi; return multi;
@ -99,6 +105,7 @@ public partial class Mod
return false; return false;
} }
DefaultSettings = Functions.MoveBit( DefaultSettings, optionIdxFrom, optionIdxTo );
UpdatePositions( Math.Min( optionIdxFrom, optionIdxTo ) ); UpdatePositions( Math.Min( optionIdxFrom, optionIdxTo ) );
return true; return true;
} }

View file

@ -20,6 +20,7 @@ public partial class Mod
public string Name { get; set; } = "Option"; public string Name { get; set; } = "Option";
public string Description { get; set; } = "A mutually exclusive group of settings."; public string Description { get; set; } = "A mutually exclusive group of settings.";
public int Priority { get; set; } public int Priority { get; set; }
public uint DefaultSettings { get; set; }
public readonly List< SubMod > OptionData = new(); public readonly List< SubMod > OptionData = new();
@ -44,9 +45,10 @@ public partial class Mod
var options = json[ "Options" ]; var options = json[ "Options" ];
var ret = new SingleModGroup var ret = new SingleModGroup
{ {
Name = json[ nameof( Name ) ]?.ToObject< string >() ?? string.Empty, Name = json[ nameof( Name ) ]?.ToObject< string >() ?? string.Empty,
Description = json[ nameof( Description ) ]?.ToObject< string >() ?? string.Empty, Description = json[ nameof( Description ) ]?.ToObject< string >() ?? string.Empty,
Priority = json[ nameof( Priority ) ]?.ToObject< int >() ?? 0, Priority = json[ nameof( Priority ) ]?.ToObject< int >() ?? 0,
DefaultSettings = json[ nameof( DefaultSettings ) ]?.ToObject< uint >() ?? 0u,
}; };
if( ret.Name.Length == 0 ) if( ret.Name.Length == 0 )
{ {
@ -64,6 +66,9 @@ public partial class Mod
} }
} }
if( ( int )ret.DefaultSettings >= ret.Count )
ret.DefaultSettings = 0;
return ret; return ret;
} }
@ -75,9 +80,10 @@ public partial class Mod
case SelectType.Multi: case SelectType.Multi:
var multi = new MultiModGroup() var multi = new MultiModGroup()
{ {
Name = Name, Name = Name,
Description = Description, Description = Description,
Priority = Priority, Priority = Priority,
DefaultSettings = 1u << ( int )DefaultSettings,
}; };
multi.PrioritizedOptions.AddRange( OptionData.Select( ( o, i ) => ( o, i ) ) ); multi.PrioritizedOptions.AddRange( OptionData.Select( ( o, i ) => ( o, i ) ) );
return multi; return multi;
@ -92,6 +98,23 @@ public partial class Mod
return false; return false;
} }
// Update default settings with the move.
if( DefaultSettings == optionIdxFrom )
{
DefaultSettings = ( uint )optionIdxTo;
}
else if( optionIdxFrom < optionIdxTo )
{
if( DefaultSettings > optionIdxFrom && DefaultSettings <= optionIdxTo )
{
--DefaultSettings;
}
}
else if( DefaultSettings < optionIdxFrom && DefaultSettings >= optionIdxTo )
{
++DefaultSettings;
}
UpdatePositions( Math.Min( optionIdxFrom, optionIdxTo ) ); UpdatePositions( Math.Min( optionIdxFrom, optionIdxTo ) );
return true; return true;
} }

View file

@ -30,7 +30,7 @@ public class ModSettings
{ {
Enabled = false, Enabled = false,
Priority = 0, Priority = 0,
Settings = Enumerable.Repeat( 0u, mod.Groups.Count ).ToList(), Settings = mod.Groups.Select( g => g.DefaultSettings ).ToList(),
}; };
// Automatically react to changes in a mods available options. // Automatically react to changes in a mods available options.
@ -41,7 +41,7 @@ public class ModSettings
case ModOptionChangeType.GroupRenamed: return true; case ModOptionChangeType.GroupRenamed: return true;
case ModOptionChangeType.GroupAdded: case ModOptionChangeType.GroupAdded:
// Add new empty setting for new mod. // Add new empty setting for new mod.
Settings.Insert( groupIdx, 0 ); Settings.Insert( groupIdx, mod.Groups[groupIdx].DefaultSettings );
return true; return true;
case ModOptionChangeType.GroupDeleted: case ModOptionChangeType.GroupDeleted:
// Remove setting for deleted mod. // Remove setting for deleted mod.
@ -70,8 +70,8 @@ public class ModSettings
var config = Settings[ groupIdx ]; var config = Settings[ groupIdx ];
Settings[ groupIdx ] = group.Type switch Settings[ groupIdx ] = group.Type switch
{ {
SelectType.Single => config >= optionIdx ? (config > 1 ? config - 1 : 0) : config, SelectType.Single => config >= optionIdx ? config > 1 ? config - 1 : 0 : config,
SelectType.Multi => RemoveBit( config, optionIdx ), SelectType.Multi => Functions.RemoveBit( config, optionIdx ),
_ => config, _ => config,
}; };
return config != Settings[ groupIdx ]; return config != Settings[ groupIdx ];
@ -88,7 +88,7 @@ public class ModSettings
Settings[ groupIdx ] = group.Type switch Settings[ groupIdx ] = group.Type switch
{ {
SelectType.Single => config == optionIdx ? ( uint )movedToIdx : config, SelectType.Single => config == optionIdx ? ( uint )movedToIdx : config,
SelectType.Multi => MoveBit( config, optionIdx, movedToIdx ), SelectType.Multi => Functions.MoveBit( config, optionIdx, movedToIdx ),
_ => config, _ => config,
}; };
return config != Settings[ groupIdx ]; return config != Settings[ groupIdx ];
@ -114,27 +114,6 @@ public class ModSettings
Settings[ groupIdx ] = FixSetting( group, newValue ); Settings[ groupIdx ] = FixSetting( group, newValue );
} }
// Remove a single bit, moving all further bits one down.
private static uint RemoveBit( uint config, int bit )
{
var lowMask = ( 1u << bit ) - 1u;
var highMask = ~( ( 1u << ( bit + 1 ) ) - 1u );
var low = config & lowMask;
var high = ( config & highMask ) >> 1;
return low | high;
}
// Move a bit in an uint from its position to another, shifting other bits accordingly.
private static uint MoveBit( uint config, int bit1, int bit2 )
{
var enabled = ( config & ( 1 << bit1 ) ) != 0 ? 1u << bit2 : 0u;
config = RemoveBit( config, bit1 );
var lowMask = ( 1u << bit2 ) - 1u;
var low = config & lowMask;
var high = ( config & ~lowMask ) << 1;
return low | enabled | high;
}
// Add defaulted settings up to the required count. // Add defaulted settings up to the required count.
private bool AddMissingSettings( int totalCount ) private bool AddMissingSettings( int totalCount )
{ {

View file

@ -8,6 +8,7 @@ using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.ByteString; using Penumbra.GameData.ByteString;
using Penumbra.GameData.Util;
using Penumbra.Mods; using Penumbra.Mods;
namespace Penumbra.UI.Classes; namespace Penumbra.UI.Classes;
@ -230,7 +231,7 @@ public partial class ModEditWindow
using var id = ImRaii.PushId( j ); using var id = ImRaii.PushId( j );
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var tmp = _fileIdx == i && _pathIdx == j ? _gamePathEdit : gamePath.ToString(); var tmp = _fileIdx == i && _pathIdx == j ? _gamePathEdit : gamePath.ToString();
var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight();
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.InputText( string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength ) ) if( ImGui.InputText( string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength ) )
{ {
@ -251,11 +252,20 @@ public partial class ModEditWindow
_fileIdx = -1; _fileIdx = -1;
_pathIdx = -1; _pathIdx = -1;
} }
else if( _fileIdx == i && _pathIdx == j && ( !Utf8GamePath.FromString( _gamePathEdit, out var path, false )
|| !path.IsEmpty && !path.Equals( gamePath ) && !_editor!.CanAddGamePath( path )) )
{
ImGui.SameLine();
ImGui.SetCursorPosX( pos );
using var font = ImRaii.PushFont( UiBuilder.IconFont );
ImGuiUtil.TextColored( 0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString() );
}
} }
private void PrintNewGamePath( int i, Mod.Editor.FileRegistry registry, ISubMod subMod ) private void PrintNewGamePath( int i, Mod.Editor.FileRegistry registry, ISubMod subMod )
{ {
var tmp = _fileIdx == i && _pathIdx == -1 ? _gamePathEdit : string.Empty; var tmp = _fileIdx == i && _pathIdx == -1 ? _gamePathEdit : string.Empty;
var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight();
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
if( ImGui.InputTextWithHint( "##new", "Add New Path...", ref tmp, Utf8GamePath.MaxGamePathLength ) ) if( ImGui.InputTextWithHint( "##new", "Add New Path...", ref tmp, Utf8GamePath.MaxGamePathLength ) )
{ {
@ -274,6 +284,14 @@ public partial class ModEditWindow
_fileIdx = -1; _fileIdx = -1;
_pathIdx = -1; _pathIdx = -1;
} }
else if( _fileIdx == i && _pathIdx == -1 && (!Utf8GamePath.FromString( _gamePathEdit, out var path, false )
|| !path.IsEmpty && !_editor!.CanAddGamePath( path )) )
{
ImGui.SameLine();
ImGui.SetCursorPosX( pos );
using var font = ImRaii.PushFont( UiBuilder.IconFont );
ImGuiUtil.TextColored( 0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString() );
}
} }
private void DrawButtonHeader() private void DrawButtonHeader()

View file

@ -33,11 +33,15 @@ public partial class ConfigWindow
"Migration should have set your currently assigned Base Collection to the Interface Collection, please verify that.", 1 ) "Migration should have set your currently assigned Base Collection to the Interface Collection, please verify that.", 1 )
.RegisterEntry( "New API / IPC for the Interface Collection added.", 1 ) .RegisterEntry( "New API / IPC for the Interface Collection added.", 1 )
.RegisterHighlight( "API / IPC consumers should verify whether they need to change resolving to the new collection.", 1 ) .RegisterHighlight( "API / IPC consumers should verify whether they need to change resolving to the new collection.", 1 )
.RegisterEntry( "Files that the game loads super early should now be replaceable correctly via base or interface collection." )
.RegisterEntry( "The 1.0 neck tattoo file should now be replaceable, even in character collections. You can also replace the transparent texture used instead. (This was ugly.)" )
.RegisterEntry( .RegisterEntry(
"Added buttons for redrawing self or all as well as a tooltip to describe redraw options and a tutorial step for it." ) "Added buttons for redrawing self or all as well as a tooltip to describe redraw options and a tutorial step for it." )
.RegisterEntry( "Collection Selectors now display None at the top if available." ) .RegisterEntry( "Collection Selectors now display None at the top if available." )
.RegisterEntry( "Adding mods via API/IPC will now cause them to incorporate and then delete TexTools .meta and .rgsp files automatically." )
.RegisterEntry( "Fixed an issue with Actor 201 using Your Character collections in cutscenes." ) .RegisterEntry( "Fixed an issue with Actor 201 using Your Character collections in cutscenes." )
.RegisterEntry( "Fixed issues with and improved mod option editing." ) .RegisterEntry( "Fixed issues with and improved mod option editing." )
.RegisterEntry( "Fixed some issues with and improved file redirection editing - you are now informed if you can not add a game path (because it is invalid or already in use)." )
.RegisterEntry( "Backend optimizations." ) .RegisterEntry( "Backend optimizations." )
.RegisterEntry( "Changed metadata change system again.", 1 ) .RegisterEntry( "Changed metadata change system again.", 1 )
.RegisterEntry( "Improved logging efficiency.", 1 ); .RegisterEntry( "Improved logging efficiency.", 1 );

View file

@ -97,7 +97,7 @@ public partial class ConfigWindow
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
} }
private void DrawUpdateBibo( Vector2 buttonSize) private void DrawUpdateBibo( Vector2 buttonSize )
{ {
if( ImGui.Button( "Update Bibo Material", buttonSize ) ) if( ImGui.Button( "Update Bibo Material", buttonSize ) )
{ {
@ -108,7 +108,8 @@ public partial class ConfigWindow
_window.ModEditPopup.UpdateModels(); _window.ModEditPopup.UpdateModels();
} }
ImGuiUtil.HoverTooltip( "For every model in this mod, change all material names that end in a _b or _c suffix to a _bibo or _bibopube suffix respectively.\n" ImGuiUtil.HoverTooltip(
"For every model in this mod, change all material names that end in a _b or _c suffix to a _bibo or _bibopube suffix respectively.\n"
+ "Does nothing if the mod does not contain any such models or no model contains such materials.\n" + "Does nothing if the mod does not contain any such models or no model contains such materials.\n"
+ "Use this for outdated mods made for old Bibo bodies.\n" + "Use this for outdated mods made for old Bibo bodies.\n"
+ "Go to Advanced Editing for more fine-tuned control over material assignment." ); + "Go to Advanced Editing for more fine-tuned control over material assignment." );
@ -459,15 +460,16 @@ public partial class ConfigWindow
public static void Draw( ModPanel panel, int groupIdx ) public static void Draw( ModPanel panel, int groupIdx )
{ {
using var table = ImRaii.Table( string.Empty, 4, ImGuiTableFlags.SizingFixedFit ); using var table = ImRaii.Table( string.Empty, 5, ImGuiTableFlags.SizingFixedFit );
if( !table ) if( !table )
{ {
return; return;
} }
ImGui.TableSetupColumn( "idx", ImGuiTableColumnFlags.WidthFixed, 60 * ImGuiHelpers.GlobalScale ); ImGui.TableSetupColumn( "idx", ImGuiTableColumnFlags.WidthFixed, 60 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "default", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight() );
ImGui.TableSetupColumn( "name", ImGuiTableColumnFlags.WidthFixed, ImGui.TableSetupColumn( "name", ImGuiTableColumnFlags.WidthFixed,
panel._window._inputTextWidth.X - 62 * ImGuiHelpers.GlobalScale ); panel._window._inputTextWidth.X - 68 * ImGuiHelpers.GlobalScale - ImGui.GetFrameHeight() );
ImGui.TableSetupColumn( "delete", ImGuiTableColumnFlags.WidthFixed, panel._window._iconButtonSize.X ); ImGui.TableSetupColumn( "delete", ImGuiTableColumnFlags.WidthFixed, panel._window._iconButtonSize.X );
ImGui.TableSetupColumn( "priority", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale ); ImGui.TableSetupColumn( "priority", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale );
@ -491,6 +493,31 @@ public partial class ConfigWindow
Source( group, groupIdx, optionIdx ); Source( group, groupIdx, optionIdx );
Target( panel, group, groupIdx, optionIdx ); Target( panel, group, groupIdx, optionIdx );
ImGui.TableNextColumn();
if( group.Type == SelectType.Single )
{
if( ImGui.RadioButton( "##default", group.DefaultSettings == optionIdx ) )
{
Penumbra.ModManager.ChangeModGroupDefaultOption( panel._mod, groupIdx, ( uint )optionIdx );
}
ImGuiUtil.HoverTooltip( $"Set {option.Name} as the default choice for this group." );
}
else
{
var isDefaultOption = ( ( group.DefaultSettings >> optionIdx ) & 1 ) != 0;
if( ImGui.Checkbox( "##default", ref isDefaultOption ) )
{
Penumbra.ModManager.ChangeModGroupDefaultOption( panel._mod, groupIdx, isDefaultOption
? group.DefaultSettings | ( 1u << optionIdx )
: group.DefaultSettings & ~( 1u << optionIdx ) );
}
ImGuiUtil.HoverTooltip( $"{( isDefaultOption ? "Disable" : "Enable" )} {option.Name} per default in this group." );
}
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if( Input.Text( "##Name", groupIdx, optionIdx, option.Name, out var newOptionName, 256, -1 ) ) if( Input.Text( "##Name", groupIdx, optionIdx, option.Name, out var newOptionName, 256, -1 ) )
{ {
@ -527,6 +554,7 @@ public partial class ConfigWindow
ImGui.Selectable( $"Option #{group.Count + 1}" ); ImGui.Selectable( $"Option #{group.Count + 1}" );
Target( panel, group, groupIdx, group.Count ); Target( panel, group, groupIdx, group.Count );
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.TableNextColumn();
ImGui.SetNextItemWidth( -1 ); ImGui.SetNextItemWidth( -1 );
var tmp = _newOptionNameIdx == groupIdx ? _newOptionName : string.Empty; var tmp = _newOptionNameIdx == groupIdx ? _newOptionName : string.Empty;
if( ImGui.InputTextWithHint( "##newOption", "Add new option...", ref tmp, 256 ) ) if( ImGui.InputTextWithHint( "##newOption", "Add new option...", ref tmp, 256 ) )
@ -575,7 +603,7 @@ public partial class ConfigWindow
return; return;
} }
if( _dragDropGroupIdx >= 0 && _dragDropOptionIdx >= 0 ) if( _dragDropGroupIdx >= 0 && _dragDropOptionIdx >= 0 )
{ {
if( _dragDropGroupIdx == groupIdx ) if( _dragDropGroupIdx == groupIdx )
{ {
@ -589,7 +617,7 @@ public partial class ConfigWindow
var sourceOption = _dragDropOptionIdx; var sourceOption = _dragDropOptionIdx;
var sourceGroup = panel._mod.Groups[ sourceGroupIdx ]; var sourceGroup = panel._mod.Groups[ sourceGroupIdx ];
var currentCount = group.Count; var currentCount = group.Count;
var option = sourceGroup[sourceOption]; var option = sourceGroup[ sourceOption ];
var priority = sourceGroup.OptionPriority( _dragDropGroupIdx ); var priority = sourceGroup.OptionPriority( _dragDropGroupIdx );
panel._delayedActions.Enqueue( () => panel._delayedActions.Enqueue( () =>
{ {

View file

@ -160,7 +160,7 @@ public partial class ConfigWindow
} }
using var id = ImRaii.PushId( groupIdx ); using var id = ImRaii.PushId( groupIdx );
var selectedOption = _emptySetting ? 0 : ( int )_settings.Settings[ groupIdx ]; var selectedOption = _emptySetting ? (int) group.DefaultSettings : ( int )_settings.Settings[ groupIdx ];
ImGui.SetNextItemWidth( _window._inputTextWidth.X * 3 / 4 ); ImGui.SetNextItemWidth( _window._inputTextWidth.X * 3 / 4 );
using var combo = ImRaii.Combo( string.Empty, group[ selectedOption ].Name ); using var combo = ImRaii.Combo( string.Empty, group[ selectedOption ].Name );
if( combo ) if( combo )
@ -199,7 +199,7 @@ public partial class ConfigWindow
} }
using var id = ImRaii.PushId( groupIdx ); using var id = ImRaii.PushId( groupIdx );
var flags = _emptySetting ? 0u : _settings.Settings[ groupIdx ]; var flags = _emptySetting ? group.DefaultSettings : _settings.Settings[ groupIdx ];
Widget.BeginFramedGroup( group.Name, group.Description ); Widget.BeginFramedGroup( group.Name, group.Description );
for( var idx2 = 0; idx2 < group.Count; ++idx2 ) for( var idx2 = 0; idx2 < group.Count; ++idx2 )
{ {

View file

@ -37,8 +37,8 @@ public partial class ConfigWindow
using var style = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero ); using var style = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, Vector2.Zero );
using( var child = ImRaii.Child( "##ModsTabMod", new Vector2( -1, -ImGui.GetFrameHeight() ), true, using( var child = ImRaii.Child( "##ModsTabMod", new Vector2( -1, Penumbra.Config.HideRedrawBar ? 0 : -ImGui.GetFrameHeight() ),
ImGuiWindowFlags.HorizontalScrollbar ) ) true, ImGuiWindowFlags.HorizontalScrollbar ) )
{ {
style.Pop(); style.Pop();
if( child ) if( child )
@ -68,6 +68,11 @@ public partial class ConfigWindow
private void DrawRedrawLine() private void DrawRedrawLine()
{ {
if( Penumbra.Config.HideRedrawBar )
{
return;
}
var frameHeight = new Vector2( 0, ImGui.GetFrameHeight() ); var frameHeight = new Vector2( 0, ImGui.GetFrameHeight() );
var frameColor = ImGui.GetColorU32( ImGuiCol.FrameBg ); var frameColor = ImGui.GetColorU32( ImGuiCol.FrameBg );
using( var _ = ImRaii.Group() ) using( var _ = ImRaii.Group() )

View file

@ -59,6 +59,9 @@ public partial class ConfigWindow
Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = !v; Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = !v;
} ); } );
ImGui.Dummy( _window._defaultSpace ); ImGui.Dummy( _window._defaultSpace );
Checkbox( "Hide Redraw Bar in Mod Panel", "Hides the lower redraw buttons in the mod panel in your Mods tab.",
Penumbra.Config.HideRedrawBar, v => Penumbra.Config.HideRedrawBar = v );
ImGui.Dummy( _window._defaultSpace );
Checkbox( $"Use {AssignedCollections} in Character Window", Checkbox( $"Use {AssignedCollections} in Character Window",
"Use the character collection for your characters name or the Your Character collection in your main character window, if it is set.", "Use the character collection for your characters name or the Your Character collection in your main character window, if it is set.",
Penumbra.Config.UseCharacterCollectionInMainWindow, v => Penumbra.Config.UseCharacterCollectionInMainWindow = v ); Penumbra.Config.UseCharacterCollectionInMainWindow, v => Penumbra.Config.UseCharacterCollectionInMainWindow = v );