Make the limit of 32 options for a multi-select group explicit and handle it better.

This commit is contained in:
Ottermandias 2022-05-13 15:01:50 +02:00
parent 976f7840cd
commit a86a73bbf5
5 changed files with 73 additions and 37 deletions

View file

@ -120,6 +120,7 @@ public partial class TexToolsImporter
{
groupName = $"{baseName} ({i++})";
}
return groupName;
}
@ -160,46 +161,58 @@ public partial class TexToolsImporter
{
foreach( var group in page.ModGroups.Where( group => group.GroupName.Length > 0 && group.OptionList.Length > 0 ) )
{
var allOptions = group.OptionList.Where( option => option.Name.Length > 0 && option.ModsJsons.Length > 0 ).ToList();
var (numGroups, maxOptions) = group.SelectionType == SelectType.Single
? ( 1, allOptions.Count )
: ( 1 + allOptions.Count / IModGroup.MaxMultiOptions, IModGroup.MaxMultiOptions );
_currentGroupName = GetGroupName( group.GroupName, groupNames );
options.Clear();
var description = new StringBuilder();
var groupFolder = Mod.NewSubFolderName( _currentModDirectory, _currentGroupName )
?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName, $"Group {groupPriority + 1}" ) );
var optionIdx = 1;
foreach( var option in group.OptionList.Where( option => option.Name.Length > 0 && option.ModsJsons.Length > 0 ) )
var optionIdx = 0;
for( var groupId = 0; groupId < numGroups; ++groupId )
{
_token.ThrowIfCancellationRequested();
_currentOptionName = option.Name;
var optionFolder = Mod.NewSubFolderName( groupFolder, option.Name )
?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {optionIdx}" ) );
ExtractSimpleModList( optionFolder, option.ModsJsons );
options.Add( Mod.CreateSubMod( _currentModDirectory, optionFolder, option ) );
description.Append( option.Description );
if( !string.IsNullOrEmpty( option.Description ) )
var name = numGroups == 1 ? _currentGroupName : $"{_currentGroupName}, Part {groupId + 1}";
options.Clear();
var description = new StringBuilder();
var groupFolder = Mod.NewSubFolderName( _currentModDirectory, name )
?? new DirectoryInfo( Path.Combine( _currentModDirectory.FullName,
numGroups == 1 ? $"Group {groupPriority + 1}" : $"Group {groupPriority + 1}, Part {groupId + 1}" ) );
for( var i = 0; i + optionIdx < allOptions.Count && i < maxOptions; ++i )
{
description.Append( '\n' );
var option = allOptions[ i + optionIdx ];
_token.ThrowIfCancellationRequested();
_currentOptionName = option.Name;
var optionFolder = Mod.NewSubFolderName( groupFolder, option.Name )
?? new DirectoryInfo( Path.Combine( groupFolder.FullName, $"Option {i + optionIdx + 1}" ) );
ExtractSimpleModList( optionFolder, option.ModsJsons );
options.Add( Mod.CreateSubMod( _currentModDirectory, optionFolder, option ) );
description.Append( option.Description );
if( !string.IsNullOrEmpty( option.Description ) )
{
description.Append( '\n' );
}
++_currentOptionIdx;
}
++optionIdx;
++_currentOptionIdx;
}
optionIdx += maxOptions;
// Handle empty options for single select groups without creating a folder for them.
// We only want one of those at most, and it should usually be the first option.
if( group.SelectionType == SelectType.Single )
{
var empty = group.OptionList.FirstOrDefault( o => o.Name.Length > 0 && o.ModsJsons.Length == 0 );
if( empty != null )
// Handle empty options for single select groups without creating a folder for them.
// We only want one of those at most, and it should usually be the first option.
if( group.SelectionType == SelectType.Single )
{
_currentOptionName = empty.Name;
options.Insert( 0, Mod.CreateEmptySubMod( empty.Name ) );
var empty = group.OptionList.FirstOrDefault( o => o.Name.Length > 0 && o.ModsJsons.Length == 0 );
if( empty != null )
{
_currentOptionName = empty.Name;
options.Insert( 0, Mod.CreateEmptySubMod( empty.Name ) );
}
}
}
Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, _currentGroupName, groupPriority, groupPriority, description.ToString(), options );
++groupPriority;
Mod.CreateOptionGroup( _currentModDirectory, group.SelectionType, name, groupPriority, groupPriority,
description.ToString(), options );
++groupPriority;
}
}
}

View file

@ -15,6 +15,8 @@ public enum SelectType
public interface IModGroup : IEnumerable< ISubMod >
{
public const int MaxMultiOptions = 32;
public string Name { get; }
public string Description { get; }
public SelectType Type { get; }

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Filesystem;
@ -57,6 +58,11 @@ public partial class Mod
{
foreach( var child in options.Children() )
{
if( ret.PrioritizedOptions.Count == IModGroup.MaxMultiOptions )
{
PluginLog.Warning($"Multi Group {ret.Name} has more than {IModGroup.MaxMultiOptions} options, ignoring excessive options." );
break;
}
var subMod = new SubMod();
subMod.Load( basePath, child, out var priority );
ret.PrioritizedOptions.Add( ( subMod, priority ) );

View file

@ -101,7 +101,7 @@ public class ModSettings
=> group.Type switch
{
SelectType.Single => ( uint )Math.Min( value, group.Count - 1 ),
SelectType.Multi => ( uint )( value & ( ( 1 << group.Count ) - 1 ) ),
SelectType.Multi => ( uint )( value & ( ( 1ul << group.Count ) - 1 ) ),
_ => value,
};

View file

@ -518,8 +518,13 @@ public partial class ConfigWindow
}
ImGui.TableNextColumn();
var canAddGroup = mod.Groups[ groupIdx ].Type != SelectType.Multi || mod.Groups[ groupIdx ].Count < IModGroup.MaxMultiOptions;
var validName = _newOptionName.Length > 0 && _newOptionNameIdx == groupIdx;
var tt = canAddGroup
? validName ? "Add a new option to this group." : "Please enter a name for the new option."
: $"Can not add more than {IModGroup.MaxMultiOptions} options to a multi group.";
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Plus.ToIconString(), iconButtonSize,
"Add a new option to this group.", _newOptionName.Length == 0 || _newOptionNameIdx != groupIdx, true ) )
tt, !( canAddGroup && validName ), true ) )
{
Penumbra.ModManager.AddOption( mod, groupIdx, _newOptionName );
_newOptionName = string.Empty;
@ -598,12 +603,22 @@ public partial class ConfigWindow
return;
}
foreach( var type in new[] { SelectType.Single, SelectType.Multi } )
if( ImGui.Selectable( GroupTypeName( SelectType.Single ), group.Type == SelectType.Single ) )
{
if( ImGui.Selectable( GroupTypeName( type ), @group.Type == type ) )
{
Penumbra.ModManager.ChangeModGroupType( _mod, groupIdx, type );
}
Penumbra.ModManager.ChangeModGroupType( _mod, groupIdx, SelectType.Single );
}
var canSwitchToMulti = group.Count <= IModGroup.MaxMultiOptions;
using var style = ImRaii.PushStyle( ImGuiStyleVar.Alpha, 0.5f, !canSwitchToMulti );
if( ImGui.Selectable( GroupTypeName( SelectType.Multi ), group.Type == SelectType.Multi ) && canSwitchToMulti )
{
Penumbra.ModManager.ChangeModGroupType( _mod, groupIdx, SelectType.Multi );
}
style.Pop();
if( !canSwitchToMulti )
{
ImGuiUtil.HoverTooltip( $"Can not convert group to multi group since it has more than {IModGroup.MaxMultiOptions} options." );
}
}