mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Make line endings explicit in editorconfig and share in sub projects, also apply editorconfig everywhere and move some namespaces.
This commit is contained in:
parent
53adb6fa54
commit
2b4a01df06
155 changed files with 1620 additions and 1614 deletions
|
|
@ -1,21 +1,31 @@
|
||||||
|
# Standard properties
|
||||||
[*.proto]
|
charset = utf-8
|
||||||
indent_style=tab
|
end_of_line = lf
|
||||||
indent_size=tab
|
insert_final_newline = true
|
||||||
tab_width=4
|
csharp_indent_labels = one_less_than_current
|
||||||
|
csharp_prefer_simple_using_statement = true:suggestion
|
||||||
[*.{asax,ascx,aspx,axaml,cs,cshtml,css,htm,html,js,jsx,master,paml,razor,skin,ts,tsx,vb,xaml,xamlx,xoml}]
|
csharp_prefer_braces = true:silent
|
||||||
indent_style=space
|
csharp_style_prefer_method_group_conversion = true:silent
|
||||||
indent_size=4
|
csharp_style_expression_bodied_methods = false:silent
|
||||||
tab_width=4
|
csharp_style_expression_bodied_constructors = false:silent
|
||||||
|
csharp_style_expression_bodied_operators = false:silent
|
||||||
[*.{appxmanifest,axml,build,config,csproj,dbml,discomap,dtd,json,jsproj,lsproj,njsproj,nuspec,proj,props,resjson,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}]
|
csharp_style_expression_bodied_properties = true:silent
|
||||||
indent_style=space
|
csharp_style_expression_bodied_indexers = true:silent
|
||||||
indent_size=2
|
csharp_style_expression_bodied_accessors = true:silent
|
||||||
tab_width=2
|
csharp_style_expression_bodied_lambdas = true:silent
|
||||||
|
csharp_style_expression_bodied_local_functions = false:silent
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||||
|
csharp_prefer_simple_default_expression = true:suggestion
|
||||||
|
csharp_style_prefer_local_over_anonymous_function = true:suggestion
|
||||||
|
csharp_style_prefer_index_operator = true:suggestion
|
||||||
|
csharp_style_prefer_range_operator = true:suggestion
|
||||||
|
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_prefer_tuple_swap = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
csharp_style_prefer_top_level_statements = true:silent
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
|
|
||||||
# Microsoft .NET properties
|
# Microsoft .NET properties
|
||||||
csharp_indent_braces=false
|
csharp_indent_braces=false
|
||||||
csharp_indent_switch_labels=true
|
csharp_indent_switch_labels=true
|
||||||
|
|
@ -3567,30 +3577,6 @@ resharper_xaml_x_key_attribute_disallowed_highlighting=error
|
||||||
resharper_xml_doc_comment_syntax_problem_highlighting=warning
|
resharper_xml_doc_comment_syntax_problem_highlighting=warning
|
||||||
resharper_xunit_xunit_test_with_console_output_highlighting=warning
|
resharper_xunit_xunit_test_with_console_output_highlighting=warning
|
||||||
|
|
||||||
# Standard properties
|
|
||||||
end_of_line= crlf
|
|
||||||
csharp_indent_labels = one_less_than_current
|
|
||||||
csharp_prefer_simple_using_statement = true:suggestion
|
|
||||||
csharp_prefer_braces = true:silent
|
|
||||||
csharp_style_prefer_method_group_conversion = true:silent
|
|
||||||
csharp_style_expression_bodied_methods = false:silent
|
|
||||||
csharp_style_expression_bodied_constructors = false:silent
|
|
||||||
csharp_style_expression_bodied_operators = false:silent
|
|
||||||
csharp_style_expression_bodied_properties = true:silent
|
|
||||||
csharp_style_expression_bodied_indexers = true:silent
|
|
||||||
csharp_style_expression_bodied_accessors = true:silent
|
|
||||||
csharp_style_expression_bodied_lambdas = true:silent
|
|
||||||
csharp_style_expression_bodied_local_functions = false:silent
|
|
||||||
csharp_style_throw_expression = true:suggestion
|
|
||||||
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
|
||||||
csharp_prefer_simple_default_expression = true:suggestion
|
|
||||||
csharp_style_prefer_local_over_anonymous_function = true:suggestion
|
|
||||||
csharp_style_prefer_index_operator = true:suggestion
|
|
||||||
csharp_style_prefer_range_operator = true:suggestion
|
|
||||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
|
||||||
csharp_style_prefer_tuple_swap = true:suggestion
|
|
||||||
csharp_style_inlined_variable_declaration = true:suggestion
|
|
||||||
|
|
||||||
[*.{cshtml,htm,html,proto,razor}]
|
[*.{cshtml,htm,html,proto,razor}]
|
||||||
indent_style=tab
|
indent_style=tab
|
||||||
indent_size=tab
|
indent_size=tab
|
||||||
|
|
@ -3601,6 +3587,21 @@ indent_style=space
|
||||||
indent_size=4
|
indent_size=4
|
||||||
tab_width=4
|
tab_width=4
|
||||||
|
|
||||||
|
[ "*.proto" ]
|
||||||
|
indent_style=tab
|
||||||
|
indent_size=tab
|
||||||
|
tab_width=4
|
||||||
|
|
||||||
|
[*.{asax,ascx,aspx,axaml,cs,cshtml,css,htm,html,js,jsx,master,paml,razor,skin,ts,tsx,vb,xaml,xamlx,xoml}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=4
|
||||||
|
tab_width=4
|
||||||
|
|
||||||
|
[*.{appxmanifest,axml,build,config,csproj,dbml,discomap,dtd,json,jsproj,lsproj,njsproj,nuspec,proj,props,resjson,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
tab_width=2
|
||||||
|
|
||||||
[*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,c,c++,cc,cginc,compute,config,cp,cpp,cs,cshtml,csproj,css,cu,cuh,cxx,dbml,discomap,dtd,h,hh,hlsl,hlsli,hlslinc,hpp,htm,html,hxx,inc,inl,ino,ipp,js,json,jsproj,jsx,lsproj,master,mpp,mq4,mq5,mqh,njsproj,nuspec,paml,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,tpp,ts,tsx,usf,ush,vb,vbproj,xaml,xamlx,xml,xoml,xsd}]
|
[*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,c,c++,cc,cginc,compute,config,cp,cpp,cs,cshtml,csproj,css,cu,cuh,cxx,dbml,discomap,dtd,h,hh,hlsl,hlsli,hlslinc,hpp,htm,html,hxx,inc,inl,ino,ipp,js,json,jsproj,jsx,lsproj,master,mpp,mq4,mq5,mqh,njsproj,nuspec,paml,proj,props,proto,razor,resjson,resw,resx,skin,StyleCop,targets,tasks,tpp,ts,tsx,usf,ush,vb,vbproj,xaml,xamlx,xml,xoml,xsd}]
|
||||||
indent_style=space
|
indent_style=space
|
||||||
indent_size= 4
|
indent_size= 4
|
||||||
|
|
@ -3621,3 +3622,4 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||||
dotnet_style_namespace_match_folder = true:suggestion
|
dotnet_style_namespace_match_folder = true:suggestion
|
||||||
|
insert_final_newline = true
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 316f3da4a3ce246afe5b98c1568d73fcd7b6b22d
|
Subproject commit 22846625192884c6e9f5ec4429fb579875b519e9
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0507b1f093f5382e03242e5da991752361b70c6e
|
Subproject commit f004e069824a1588244e06080b32bab170f78077
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0e0c1e1ee116c259abd00e1d5c3450ad40f92a98
|
Subproject commit 620a7edf009b92288257ce7d64fffb8fba44d8b5
|
||||||
|
|
@ -633,7 +633,8 @@ public class PenumbraApi : IDisposable, IPenumbraApi
|
||||||
|
|
||||||
_modManager.AddMod(dir);
|
_modManager.AddMod(dir);
|
||||||
if (_config.UseFileSystemCompression)
|
if (_config.UseFileSystemCompression)
|
||||||
new FileCompactor(Penumbra.Log).StartMassCompact(dir.EnumerateFiles("*.*", SearchOption.AllDirectories), CompressionAlgorithm.Xpress8K);
|
new FileCompactor(Penumbra.Log).StartMassCompact(dir.EnumerateFiles("*.*", SearchOption.AllDirectories),
|
||||||
|
CompressionAlgorithm.Xpress8K);
|
||||||
return PenumbraApiEc.Success;
|
return PenumbraApiEc.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Penumbra.Api.Enums;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
namespace Penumbra.Collections.Cache;
|
namespace Penumbra.Collections.Cache;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.Api;
|
using Penumbra.Api;
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ public struct EqpCache : IDisposable
|
||||||
var def = ExpandedEqpFile.GetDefault(manager, manip.SetId);
|
var def = ExpandedEqpFile.GetDefault(manager, manip.SetId);
|
||||||
manip = new EqpManipulation(def, manip.Slot, manip.SetId);
|
manip = new EqpManipulation(def, manip.Slot, manip.SetId);
|
||||||
return manip.Apply(_eqpFile!);
|
return manip.Apply(_eqpFile!);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ public static class ActiveCollectionMigration
|
||||||
if (!storage.ByName(collectionName, out var collection))
|
if (!storage.ByName(collectionName, out var collection))
|
||||||
{
|
{
|
||||||
Penumbra.Chat.NotificationMessage(
|
Penumbra.Chat.NotificationMessage(
|
||||||
$"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {ModCollection.Empty.Name}.", "Load Failure",
|
$"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {ModCollection.Empty.Name}.",
|
||||||
|
"Load Failure",
|
||||||
NotificationType.Warning);
|
NotificationType.Warning);
|
||||||
dict.Add(player, ModCollection.Empty);
|
dict.Add(player, ModCollection.Empty);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,7 @@ public class ActiveCollections : ISavable, IDisposable
|
||||||
var m = ByType(CollectionTypeExtensions.FromParts(race, Gender.Male, false));
|
var m = ByType(CollectionTypeExtensions.FromParts(race, Gender.Male, false));
|
||||||
if (m != null && m != yourself)
|
if (m != null && m != yourself)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
||||||
var f = ByType(CollectionTypeExtensions.FromParts(race, Gender.Female, false));
|
var f = ByType(CollectionTypeExtensions.FromParts(race, Gender.Female, false));
|
||||||
if (f != null && f != yourself)
|
if (f != null && f != yourself)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
@ -460,14 +461,16 @@ public class ActiveCollections : ISavable, IDisposable
|
||||||
if (male == null)
|
if (male == null)
|
||||||
{
|
{
|
||||||
if (female == null && @base == yourself)
|
if (female == null && @base == yourself)
|
||||||
return $"Assignment is redundant due to overwriting Base{racialString} with an identical collection.\nYou can remove it.";
|
return
|
||||||
|
$"Assignment is redundant due to overwriting Base{racialString} with an identical collection.\nYou can remove it.";
|
||||||
if (female == yourself && @base == yourself)
|
if (female == yourself && @base == yourself)
|
||||||
return
|
return
|
||||||
$"Assignment is redundant due to overwriting Base and Female Players{racialString} with an identical collection.\nYou can remove it.";
|
$"Assignment is redundant due to overwriting Base and Female Players{racialString} with an identical collection.\nYou can remove it.";
|
||||||
}
|
}
|
||||||
else if (male == yourself && female == null && @base == yourself)
|
else if (male == yourself && female == null && @base == yourself)
|
||||||
{
|
{
|
||||||
return $"Assignment is redundant due to overwriting Base and Male Players{racialString} with an identical collection.\nYou can remove it.";
|
return
|
||||||
|
$"Assignment is redundant due to overwriting Base and Male Players{racialString} with an identical collection.\nYou can remove it.";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using OtterGui;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.Collections.Manager;
|
namespace Penumbra.Collections.Manager;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using OtterGui.Filesystem;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.Collections.Manager;
|
namespace Penumbra.Collections.Manager;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Handle generic NPC
|
// Handle generic NPC
|
||||||
var npcIdentifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, ushort.MaxValue,
|
var npcIdentifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty,
|
||||||
|
ushort.MaxValue,
|
||||||
identifier.Kind, identifier.DataId);
|
identifier.Kind, identifier.DataId);
|
||||||
if (npcIdentifier.IsValid && _individuals.TryGetValue(npcIdentifier, out collection))
|
if (npcIdentifier.IsValid && _individuals.TryGetValue(npcIdentifier, out collection))
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -56,7 +57,8 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
|
||||||
if (!_config.UseOwnerNameForCharacterCollection)
|
if (!_config.UseOwnerNameForCharacterCollection)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Player, identifier.PlayerName, identifier.HomeWorld.Id,
|
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Player, identifier.PlayerName,
|
||||||
|
identifier.HomeWorld.Id,
|
||||||
ObjectKind.None, uint.MaxValue);
|
ObjectKind.None, uint.MaxValue);
|
||||||
return CheckWorlds(identifier, out collection);
|
return CheckWorlds(identifier, out collection);
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +144,8 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
|
||||||
if (_individuals.TryGetValue(identifier, out collection))
|
if (_individuals.TryGetValue(identifier, out collection))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, ushort.MaxValue, identifier.Kind,
|
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, ushort.MaxValue,
|
||||||
|
identifier.Kind,
|
||||||
identifier.DataId);
|
identifier.DataId);
|
||||||
if (identifier.IsValid && _individuals.TryGetValue(identifier, out collection))
|
if (identifier.IsValid && _individuals.TryGetValue(identifier, out collection))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ public partial class IndividualCollections
|
||||||
{
|
{
|
||||||
if (_actorService.Valid)
|
if (_actorService.Valid)
|
||||||
return ReadJObjectInternal(obj, storage);
|
return ReadJObjectInternal(obj, storage);
|
||||||
|
|
||||||
void Func()
|
void Func()
|
||||||
{
|
{
|
||||||
if (ReadJObjectInternal(obj, storage))
|
if (ReadJObjectInternal(obj, storage))
|
||||||
|
|
@ -35,6 +36,7 @@ public partial class IndividualCollections
|
||||||
Loaded.Invoke();
|
Loaded.Invoke();
|
||||||
_actorService.FinishedCreation -= Func;
|
_actorService.FinishedCreation -= Func;
|
||||||
}
|
}
|
||||||
|
|
||||||
_actorService.FinishedCreation += Func;
|
_actorService.FinishedCreation += Func;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +87,7 @@ public partial class IndividualCollections
|
||||||
NotificationType.Error);
|
NotificationType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,8 @@ public sealed partial class IndividualCollections
|
||||||
_ => throw new NotImplementedException(),
|
_ => throw new NotImplementedException(),
|
||||||
};
|
};
|
||||||
return table.Where(kvp => kvp.Value == name)
|
return table.Where(kvp => kvp.Value == name)
|
||||||
.Select(kvp => manager.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, identifier.HomeWorld.Id, identifier.Kind,
|
.Select(kvp => manager.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, identifier.HomeWorld.Id,
|
||||||
|
identifier.Kind,
|
||||||
kvp.Key)).ToArray();
|
kvp.Key)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ public partial class ModCollection
|
||||||
// Used for short periods of changed files.
|
// Used for short periods of changed files.
|
||||||
public MetaList.MetaReverter TemporarilySetEqdpFile(CharacterUtility utility, GenderRace genderRace, bool accessory)
|
public MetaList.MetaReverter TemporarilySetEqdpFile(CharacterUtility utility, GenderRace genderRace, bool accessory)
|
||||||
=> _cache?.Meta.TemporarilySetEqdpFile(genderRace, accessory)
|
=> _cache?.Meta.TemporarilySetEqdpFile(genderRace, accessory)
|
||||||
?? utility.TemporarilyResetResource(Interop.Structs.CharacterUtilityData.EqdpIdx(genderRace, accessory));
|
?? utility.TemporarilyResetResource(CharacterUtilityData.EqdpIdx(genderRace, accessory));
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetEqpFile(CharacterUtility utility)
|
public MetaList.MetaReverter TemporarilySetEqpFile(CharacterUtility utility)
|
||||||
=> _cache?.Meta.TemporarilySetEqpFile()
|
=> _cache?.Meta.TemporarilySetEqpFile()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.Collections;
|
namespace Penumbra.Collections;
|
||||||
|
|
@ -142,7 +143,8 @@ public partial class ModCollection
|
||||||
public static ModCollection CreateEmpty(string name, int index, int modCount)
|
public static ModCollection CreateEmpty(string name, int index, int modCount)
|
||||||
{
|
{
|
||||||
Debug.Assert(index >= 0, "Empty collection created with negative index.");
|
Debug.Assert(index >= 0, "Empty collection created with negative index.");
|
||||||
return new ModCollection(name, index, 0, CurrentVersion, Enumerable.Repeat((ModSettings?) null, modCount).ToList(), new List<ModCollection>(),
|
return new ModCollection(name, index, 0, CurrentVersion, Enumerable.Repeat((ModSettings?)null, modCount).ToList(),
|
||||||
|
new List<ModCollection>(),
|
||||||
new Dictionary<string, ModSettings.SavedSettings>());
|
new Dictionary<string, ModSettings.SavedSettings>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Penumbra.Mods;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
|
|
||||||
namespace Penumbra.Collections;
|
namespace Penumbra.Collections;
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@ public class CommandHandler : IDisposable
|
||||||
{
|
{
|
||||||
if (_config.MinimumSize.X == Configuration.Constants.MinimumSizeX && _config.MinimumSize.Y == Configuration.Constants.MinimumSizeY)
|
if (_config.MinimumSize.X == Configuration.Constants.MinimumSizeX && _config.MinimumSize.Y == Configuration.Constants.MinimumSizeY)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_config.MinimumSize.X = Configuration.Constants.MinimumSizeX;
|
_config.MinimumSize.X = Configuration.Constants.MinimumSizeX;
|
||||||
_config.MinimumSize.Y = Configuration.Constants.MinimumSizeY;
|
_config.MinimumSize.Y = Configuration.Constants.MinimumSizeY;
|
||||||
_config.Save();
|
_config.Save();
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ public sealed class CollectionChange : EventWrapper<Action<CollectionType, ModCo
|
||||||
|
|
||||||
/// <seealso cref="UI.ModsTab.ModFileSystemSelector.OnCollectionChange"/>
|
/// <seealso cref="UI.ModsTab.ModFileSystemSelector.OnCollectionChange"/>
|
||||||
ModFileSystemSelector = 0,
|
ModFileSystemSelector = 0,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CollectionChange()
|
public CollectionChange()
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ public sealed class ModDataChanged : EventWrapper<Action<ModDataChangeType, Mod,
|
||||||
/// <seealso cref="Mods.Manager.ModCacheManager.OnModDataChange"/>
|
/// <seealso cref="Mods.Manager.ModCacheManager.OnModDataChange"/>
|
||||||
ModCacheManager = 0,
|
ModCacheManager = 0,
|
||||||
|
|
||||||
/// <seealso cref="Mods.ModFileSystem.OnDataChange"/>
|
/// <seealso cref="Mods.Manager.ModFileSystem.OnDataChange"/>
|
||||||
ModFileSystem = 0,
|
ModFileSystem = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
|
|
||||||
namespace Penumbra.Communication;
|
namespace Penumbra.Communication;
|
||||||
|
|
||||||
|
|
@ -19,7 +20,7 @@ public sealed class ModDiscoveryFinished : EventWrapper<Action, ModDiscoveryFini
|
||||||
/// <seealso cref="Mods.Manager.ModCacheManager.OnModDiscoveryFinished"/>
|
/// <seealso cref="Mods.Manager.ModCacheManager.OnModDiscoveryFinished"/>
|
||||||
ModCacheManager = 0,
|
ModCacheManager = 0,
|
||||||
|
|
||||||
/// <seealso cref="Mods.ModFileSystem.Reload"/>
|
/// <seealso cref="Mods.Manager.ModFileSystem.Reload"/>
|
||||||
ModFileSystem = 0,
|
ModFileSystem = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ public sealed class ModDiscoveryStarted : EventWrapper<Action, ModDiscoveryStart
|
||||||
/// <seealso cref="UI.ModsTab.ModFileSystemSelector.StoreCurrentSelection"/>
|
/// <seealso cref="UI.ModsTab.ModFileSystemSelector.StoreCurrentSelection"/>
|
||||||
ModFileSystemSelector = 200,
|
ModFileSystemSelector = 200,
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModDiscoveryStarted()
|
public ModDiscoveryStarted()
|
||||||
: base(nameof(ModDiscoveryStarted))
|
: base(nameof(ModDiscoveryStarted))
|
||||||
{ }
|
{ }
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public sealed class ModPathChanged : EventWrapper<Action<ModPathChangeType, Mod,
|
||||||
/// <seealso cref="Mods.Manager.ModExportManager.OnModPathChange"/>
|
/// <seealso cref="Mods.Manager.ModExportManager.OnModPathChange"/>
|
||||||
ModExportManager = 0,
|
ModExportManager = 0,
|
||||||
|
|
||||||
/// <seealso cref="Mods.ModFileSystem.OnModPathChange"/>
|
/// <seealso cref="Mods.Manager.ModFileSystem.OnModPathChange"/>
|
||||||
ModFileSystem = 0,
|
ModFileSystem = 0,
|
||||||
|
|
||||||
/// <seealso cref="Mods.Manager.ModManager.OnModPathChange"/>
|
/// <seealso cref="Mods.Manager.ModManager.OnModPathChange"/>
|
||||||
|
|
@ -48,6 +48,7 @@ public sealed class ModPathChanged : EventWrapper<Action<ModPathChangeType, Mod,
|
||||||
/// <seealso cref="Collections.Cache.CollectionCacheManager.OnModChangeRemoval"/>
|
/// <seealso cref="Collections.Cache.CollectionCacheManager.OnModChangeRemoval"/>
|
||||||
CollectionCacheManagerRemoval = 100,
|
CollectionCacheManagerRemoval = 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModPathChanged()
|
public ModPathChanged()
|
||||||
: base(nameof(ModPathChanged))
|
: base(nameof(ModPathChanged))
|
||||||
{ }
|
{ }
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,14 @@ using OtterGui.Classes;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.GameData.Enums;
|
|
||||||
using Penumbra.Import.Structs;
|
using Penumbra.Import.Structs;
|
||||||
using Penumbra.Interop.Services;
|
using Penumbra.Interop.Services;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI;
|
using Penumbra.UI;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
using Penumbra.UI.ResourceWatcher;
|
||||||
using Penumbra.UI.Tabs;
|
using Penumbra.UI.Tabs;
|
||||||
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
global using System;
|
global using System;
|
||||||
global using System.Collections;
|
global using System.Collections;
|
||||||
|
global using System.Collections.Concurrent;
|
||||||
global using System.Collections.Generic;
|
global using System.Collections.Generic;
|
||||||
global using System.Diagnostics;
|
global using System.Diagnostics;
|
||||||
global using System.IO;
|
global using System.IO;
|
||||||
global using System.Linq;
|
global using System.Linq;
|
||||||
global using System.Numerics;
|
global using System.Numerics;
|
||||||
|
global using System.Reflection;
|
||||||
global using System.Runtime.CompilerServices;
|
global using System.Runtime.CompilerServices;
|
||||||
global using System.Runtime.InteropServices;
|
global using System.Runtime.InteropServices;
|
||||||
global using System.Security.Cryptography;
|
global using System.Security.Cryptography;
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,7 @@ public partial class TexToolsImporter
|
||||||
var obj = JObject.Load(j);
|
var obj = JObject.Load(j);
|
||||||
name = obj[nameof(Mod.Name)]?.Value<string>()?.RemoveInvalidPathSymbols() ?? string.Empty;
|
name = obj[nameof(Mod.Name)]?.Value<string>()?.RemoveInvalidPathSymbols() ?? string.Empty;
|
||||||
if (name.Length == 0)
|
if (name.Length == 0)
|
||||||
{
|
|
||||||
throw new Exception("Invalid mod archive: mod meta has no name.");
|
throw new Exception("Invalid mod archive: mod meta has no name.");
|
||||||
}
|
|
||||||
|
|
||||||
using var f = File.OpenWrite(Path.Combine(_currentModDirectory.FullName, reader.Entry.Key));
|
using var f = File.OpenWrite(Path.Combine(_currentModDirectory.FullName, reader.Entry.Key));
|
||||||
s.Seek(0, SeekOrigin.Begin);
|
s.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
@ -122,9 +120,7 @@ public partial class TexToolsImporter
|
||||||
var entry = archive.Entries.FirstOrDefault(e => !e.IsDirectory && Path.GetFileName(e.Key) == "meta.json");
|
var entry = archive.Entries.FirstOrDefault(e => !e.IsDirectory && Path.GetFileName(e.Key) == "meta.json");
|
||||||
// None found.
|
// None found.
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
{
|
|
||||||
throw new Exception("Invalid mod archive: No meta.json contained.");
|
throw new Exception("Invalid mod archive: No meta.json contained.");
|
||||||
}
|
|
||||||
|
|
||||||
var ret = string.Empty;
|
var ret = string.Empty;
|
||||||
leadDir = false;
|
leadDir = false;
|
||||||
|
|
@ -136,19 +132,20 @@ public partial class TexToolsImporter
|
||||||
var directory = Path.GetDirectoryName(entry.Key);
|
var directory = Path.GetDirectoryName(entry.Key);
|
||||||
// Should not happen.
|
// Should not happen.
|
||||||
if (directory.IsNullOrEmpty())
|
if (directory.IsNullOrEmpty())
|
||||||
{
|
|
||||||
throw new Exception("Invalid mod archive: Unknown error fetching meta.json.");
|
throw new Exception("Invalid mod archive: Unknown error fetching meta.json.");
|
||||||
}
|
|
||||||
|
|
||||||
ret = directory;
|
ret = directory;
|
||||||
// Check that all other files are also contained in the top-level directory.
|
// Check that all other files are also contained in the top-level directory.
|
||||||
if( ret.IndexOfAny( new[] { '/', '\\' } ) >= 0
|
if (ret.IndexOfAny(new[]
|
||||||
|| !archive.Entries.All( e => e.Key.StartsWith( ret ) && ( e.Key.Length == ret.Length || e.Key[ ret.Length ] is '/' or '\\' ) ) )
|
|
||||||
{
|
{
|
||||||
|
'/',
|
||||||
|
'\\',
|
||||||
|
})
|
||||||
|
>= 0
|
||||||
|
|| !archive.Entries.All(e => e.Key.StartsWith(ret) && (e.Key.Length == ret.Length || e.Key[ret.Length] is '/' or '\\')))
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Invalid mod archive: meta.json in wrong location. It needs to be either at root or one directory deep, in which all other files must be nested too.");
|
"Invalid mod archive: meta.json in wrong location. It needs to be either at root or one directory deep, in which all other files must be nested too.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,9 @@ public partial class TexToolsImporter
|
||||||
ImGui.ProgressBar(percentage, size, $"Mod {_currentModPackIdx + 1} / {_modPackCount}");
|
ImGui.ProgressBar(percentage, size, $"Mod {_currentModPackIdx + 1} / {_modPackCount}");
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
if (State == ImporterState.DeduplicatingFiles)
|
if (State == ImporterState.DeduplicatingFiles)
|
||||||
{
|
|
||||||
ImGui.TextUnformatted($"Deduplicating {_currentModName}...");
|
ImGui.TextUnformatted($"Deduplicating {_currentModName}...");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ImGui.TextUnformatted($"Extracting {_currentModName}...");
|
ImGui.TextUnformatted($"Extracting {_currentModName}...");
|
||||||
}
|
|
||||||
|
|
||||||
if (_currentNumOptions > 1)
|
if (_currentNumOptions > 1)
|
||||||
{
|
{
|
||||||
|
|
@ -53,11 +49,9 @@ public partial class TexToolsImporter
|
||||||
ImGui.ProgressBar(percentage, size, $"Option {_currentOptionIdx + 1} / {_currentNumOptions}");
|
ImGui.ProgressBar(percentage, size, $"Option {_currentOptionIdx + 1} / {_currentNumOptions}");
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
if (State != ImporterState.DeduplicatingFiles)
|
if (State != ImporterState.DeduplicatingFiles)
|
||||||
{
|
|
||||||
ImGui.TextUnformatted(
|
ImGui.TextUnformatted(
|
||||||
$"Extracting option {(_currentGroupName.Length == 0 ? string.Empty : $"{_currentGroupName} - ")}{_currentOptionName}...");
|
$"Extracting option {(_currentGroupName.Length == 0 ? string.Empty : $"{_currentGroupName} - ")}{_currentOptionName}...");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
@ -65,11 +59,9 @@ public partial class TexToolsImporter
|
||||||
ImGui.ProgressBar(percentage, size, $"File {_currentFileIdx + 1} / {_currentNumFiles}");
|
ImGui.ProgressBar(percentage, size, $"File {_currentFileIdx + 1} / {_currentNumFiles}");
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
if (State != ImporterState.DeduplicatingFiles)
|
if (State != ImporterState.DeduplicatingFiles)
|
||||||
{
|
|
||||||
ImGui.TextUnformatted($"Extracting file {_currentFileName}...");
|
ImGui.TextUnformatted($"Extracting file {_currentFileName}...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DrawEndState()
|
private void DrawEndState()
|
||||||
|
|
@ -80,9 +72,7 @@ public partial class TexToolsImporter
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
using var table = ImRaii.Table("##files", 2);
|
using var table = ImRaii.Table("##files", 2);
|
||||||
if (!table)
|
if (!table)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var (file, dir, ex) in ExtractedMods)
|
foreach (var (file, dir, ex) in ExtractedMods)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,8 @@ public partial class TexToolsMeta
|
||||||
{
|
{
|
||||||
var def = CmpFile.GetDefault(manager, subRace, attribute);
|
var def = CmpFile.GetDefault(manager, subRace, attribute);
|
||||||
if (keepDefault || value != def)
|
if (keepDefault || value != def)
|
||||||
{
|
|
||||||
ret.MetaManipulations.Add(new RspManipulation(subRace, attribute, value));
|
ret.MetaManipulations.Add(new RspManipulation(subRace, attribute, value));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (gender == 1)
|
if (gender == 1)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,7 @@ public partial class TexToolsMeta
|
||||||
{
|
{
|
||||||
var idx = entries.FindIndex(t => t.type == type);
|
var idx = entries.FindIndex(t => t.type == type);
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
reader.BaseStream.Seek(entries[idx].offset, SeekOrigin.Begin);
|
reader.BaseStream.Seek(entries[idx].offset, SeekOrigin.Begin);
|
||||||
return reader.ReadBytes(entries[idx].size);
|
return reader.ReadBytes(entries[idx].size);
|
||||||
|
|
@ -92,9 +90,7 @@ public partial class TexToolsMeta
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
for (var c = reader.ReadChar(); c != 0; c = reader.ReadChar())
|
for (var c = reader.ReadChar(); c != 0; c = reader.ReadChar())
|
||||||
{
|
|
||||||
builder.Append(c);
|
builder.Append(c);
|
||||||
}
|
|
||||||
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,7 @@ public readonly record struct RgbaPixelData(int Width, int Height, byte[] PixelD
|
||||||
|
|
||||||
public RgbaPixelData((int Width, int Height) size, byte[] pixelData)
|
public RgbaPixelData((int Width, int Height) size, byte[] pixelData)
|
||||||
: this(size.Width, size.Height, pixelData)
|
: this(size.Width, size.Height, pixelData)
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
|
|
||||||
public Image<Rgba32> ToImage()
|
public Image<Rgba32> ToImage()
|
||||||
=> Image.LoadPixelData<Rgba32>(PixelData, Width, Height);
|
=> Image.LoadPixelData<Rgba32>(PixelData, Width, Height);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ImGuiScene;
|
using ImGuiScene;
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,8 @@ public sealed unsafe class LiveColorTablePreviewer : LiveMaterialPreviewerBase
|
||||||
textureSize[0] = TextureWidth;
|
textureSize[0] = TextureWidth;
|
||||||
textureSize[1] = TextureHeight;
|
textureSize[1] = TextureHeight;
|
||||||
|
|
||||||
using var texture = new SafeTextureHandle(Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7), false);
|
using var texture =
|
||||||
|
new SafeTextureHandle(Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7), false);
|
||||||
if (texture.IsInvalid)
|
if (texture.IsInvalid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||||
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ public class ResourceNode
|
||||||
Children = new List<ResourceNode>();
|
Children = new List<ResourceNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath[] possibleGamePaths, FullPath fullPath,
|
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath[] possibleGamePaths,
|
||||||
|
FullPath fullPath,
|
||||||
ulong length, bool @internal)
|
ulong length, bool @internal)
|
||||||
{
|
{
|
||||||
Name = uiData.Name;
|
Name = uiData.Name;
|
||||||
|
|
@ -69,7 +70,7 @@ public class ResourceNode
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceNode WithUIData(string? name, ChangedItemIcon icon)
|
public ResourceNode WithUIData(string? name, ChangedItemIcon icon)
|
||||||
=> string.Equals(Name, name, StringComparison.Ordinal) && Icon == icon ? this : new ResourceNode(new(name, icon), this);
|
=> string.Equals(Name, name, StringComparison.Ordinal) && Icon == icon ? this : new ResourceNode(new UIData(name, icon), this);
|
||||||
|
|
||||||
public ResourceNode WithUIData(UIData uiData)
|
public ResourceNode WithUIData(UIData uiData)
|
||||||
=> string.Equals(Name, uiData.Name, StringComparison.Ordinal) && Icon == uiData.Icon ? this : new ResourceNode(uiData, this);
|
=> string.Equals(Name, uiData.Name, StringComparison.Ordinal) && Icon == uiData.Icon ? this : new ResourceNode(uiData, this);
|
||||||
|
|
@ -77,6 +78,6 @@ public class ResourceNode
|
||||||
public readonly record struct UIData(string? Name, ChangedItemIcon Icon)
|
public readonly record struct UIData(string? Name, ChangedItemIcon Icon)
|
||||||
{
|
{
|
||||||
public readonly UIData PrependName(string prefix)
|
public readonly UIData PrependName(string prefix)
|
||||||
=> Name == null ? this : new(prefix + Name, Icon);
|
=> Name == null ? this : new UIData(prefix + Name, Icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,9 @@ public class ResourceTree
|
||||||
|
|
||||||
var legacyDecalNode = context.CreateNodeFromTex((TextureResourceHandle*)human->LegacyBodyDecal);
|
var legacyDecalNode = context.CreateNodeFromTex((TextureResourceHandle*)human->LegacyBodyDecal);
|
||||||
if (legacyDecalNode != null)
|
if (legacyDecalNode != null)
|
||||||
Nodes.Add(globalContext.WithUiData ? legacyDecalNode.WithUIData(legacyDecalNode.Name ?? "Legacy Body Decal", legacyDecalNode.Icon) : legacyDecalNode);
|
Nodes.Add(globalContext.WithUiData
|
||||||
|
? legacyDecalNode.WithUIData(legacyDecalNode.Name ?? "Legacy Body Decal", legacyDecalNode.Icon)
|
||||||
|
: legacyDecalNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, Skeleton* skeleton, string prefix = "")
|
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, Skeleton* skeleton, string prefix = "")
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,25 @@ namespace Penumbra.Interop.SafeHandles;
|
||||||
|
|
||||||
public unsafe class SafeResourceHandle : SafeHandle
|
public unsafe class SafeResourceHandle : SafeHandle
|
||||||
{
|
{
|
||||||
public ResourceHandle* ResourceHandle => (ResourceHandle*)handle;
|
public ResourceHandle* ResourceHandle
|
||||||
|
=> (ResourceHandle*)handle;
|
||||||
|
|
||||||
public override bool IsInvalid => handle == 0;
|
public override bool IsInvalid
|
||||||
|
=> handle == 0;
|
||||||
|
|
||||||
public SafeResourceHandle(ResourceHandle* handle, bool incRef, bool ownsHandle = true) : base(0, ownsHandle)
|
public SafeResourceHandle(ResourceHandle* handle, bool incRef, bool ownsHandle = true)
|
||||||
|
: base(0, ownsHandle)
|
||||||
{
|
{
|
||||||
if (incRef && !ownsHandle)
|
if (incRef && !ownsHandle)
|
||||||
throw new ArgumentException("Non-owning SafeResourceHandle with IncRef is unsupported");
|
throw new ArgumentException("Non-owning SafeResourceHandle with IncRef is unsupported");
|
||||||
|
|
||||||
if (incRef && handle != null)
|
if (incRef && handle != null)
|
||||||
handle->IncRef();
|
handle->IncRef();
|
||||||
SetHandle((nint)handle);
|
SetHandle((nint)handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SafeResourceHandle CreateInvalid()
|
public static SafeResourceHandle CreateInvalid()
|
||||||
=> new(null, incRef: false);
|
=> new(null, false);
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,18 @@ namespace Penumbra.Interop.SafeHandles;
|
||||||
|
|
||||||
public unsafe class SafeTextureHandle : SafeHandle
|
public unsafe class SafeTextureHandle : SafeHandle
|
||||||
{
|
{
|
||||||
public Texture* Texture => (Texture*)handle;
|
public Texture* Texture
|
||||||
|
=> (Texture*)handle;
|
||||||
|
|
||||||
public override bool IsInvalid => handle == 0;
|
public override bool IsInvalid
|
||||||
|
=> handle == 0;
|
||||||
|
|
||||||
public SafeTextureHandle(Texture* handle, bool incRef, bool ownsHandle = true) : base(0, ownsHandle)
|
public SafeTextureHandle(Texture* handle, bool incRef, bool ownsHandle = true)
|
||||||
|
: base(0, ownsHandle)
|
||||||
{
|
{
|
||||||
if (incRef && !ownsHandle)
|
if (incRef && !ownsHandle)
|
||||||
throw new ArgumentException("Non-owning SafeTextureHandle with IncRef is unsupported");
|
throw new ArgumentException("Non-owning SafeTextureHandle with IncRef is unsupported");
|
||||||
|
|
||||||
if (incRef && handle != null)
|
if (incRef && handle != null)
|
||||||
TextureUtility.IncRef(handle);
|
TextureUtility.IncRef(handle);
|
||||||
SetHandle((nint)handle);
|
SetHandle((nint)handle);
|
||||||
|
|
@ -27,7 +31,7 @@ public unsafe class SafeTextureHandle : SafeHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SafeTextureHandle CreateInvalid()
|
public static SafeTextureHandle CreateInvalid()
|
||||||
=> new(null, incRef: false);
|
=> new(null, false);
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
|
|
@ -37,6 +41,7 @@ public unsafe class SafeTextureHandle : SafeHandle
|
||||||
handle = this.handle;
|
handle = this.handle;
|
||||||
this.handle = 0;
|
this.handle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle != 0)
|
if (handle != 0)
|
||||||
TextureUtility.DecRef((Texture*)handle);
|
TextureUtility.DecRef((Texture*)handle);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -265,11 +265,13 @@ public unsafe class GameEventManager : IDisposable
|
||||||
private readonly Hook<TestDelegate>? _testHook = null;
|
private readonly Hook<TestDelegate>? _testHook = null;
|
||||||
|
|
||||||
private delegate void TestDelegate(nint a1, int a2);
|
private delegate void TestDelegate(nint a1, int a2);
|
||||||
|
|
||||||
private void TestDetour(nint a1, int a2)
|
private void TestDetour(nint a1, int a2)
|
||||||
{
|
{
|
||||||
Penumbra.Log.Information($"Test: {a1:X} {a2}");
|
Penumbra.Log.Information($"Test: {a1:X} {a2}");
|
||||||
_testHook!.Original(a1, a2);
|
_testHook!.Original(a1, a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnableDebugHook()
|
private void EnableDebugHook()
|
||||||
=> _testHook?.Enable();
|
=> _testHook?.Enable();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ public unsafe struct Material
|
||||||
[FieldOffset(0x38)]
|
[FieldOffset(0x38)]
|
||||||
public ushort TextureCount;
|
public ushort TextureCount;
|
||||||
|
|
||||||
public Texture* Texture( int index ) => Textures[index].ResourceHandle->KernelTexture;
|
public Texture* Texture(int index)
|
||||||
|
=> Textures[index].ResourceHandle->KernelTexture;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
|
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
|
||||||
public struct TextureEntry
|
public struct TextureEntry
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,7 @@ public unsafe struct ResourceHandle
|
||||||
public byte* FileNamePtr()
|
public byte* FileNamePtr()
|
||||||
{
|
{
|
||||||
if (FileNameLength > SsoSize)
|
if (FileNameLength > SsoSize)
|
||||||
{
|
|
||||||
return FileNameData;
|
return FileNameData;
|
||||||
}
|
|
||||||
|
|
||||||
fixed (byte** name = &FileNameData)
|
fixed (byte** name = &FileNameData)
|
||||||
{
|
{
|
||||||
|
|
@ -128,9 +126,7 @@ public unsafe struct ResourceHandle
|
||||||
public bool SetData(IntPtr data, int length)
|
public bool SetData(IntPtr data, int length)
|
||||||
{
|
{
|
||||||
if (Data == null)
|
if (Data == null)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
Data->DataPtr = length != 0 ? (byte*)data : null;
|
Data->DataPtr = length != 0 ? (byte*)data : null;
|
||||||
Data->DataLength = (ulong)length;
|
Data->DataLength = (ulong)length;
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@ public unsafe struct SeFileDescriptor
|
||||||
public FileMode FileMode;
|
public FileMode FileMode;
|
||||||
|
|
||||||
[FieldOffset(0x30)]
|
[FieldOffset(0x30)]
|
||||||
public void* FileDescriptor; //
|
public void* FileDescriptor;
|
||||||
|
|
||||||
[FieldOffset(0x50)]
|
[FieldOffset(0x50)]
|
||||||
public ResourceHandle* ResourceHandle; //
|
public ResourceHandle* ResourceHandle;
|
||||||
|
|
||||||
|
|
||||||
[FieldOffset(0x70)]
|
[FieldOffset(0x70)]
|
||||||
public char Utf16FileName; //
|
public char Utf16FileName;
|
||||||
}
|
}
|
||||||
|
|
@ -4,12 +4,13 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
|
||||||
|
|
||||||
namespace Penumbra.Interop.Structs;
|
namespace Penumbra.Interop.Structs;
|
||||||
|
|
||||||
public unsafe static class TextureUtility
|
public static unsafe class TextureUtility
|
||||||
{
|
{
|
||||||
private static readonly Functions Funcs = new();
|
private static readonly Functions Funcs = new();
|
||||||
|
|
||||||
public static Texture* Create2D(Device* device, int* size, byte mipLevel, uint textureFormat, uint flags, uint unk)
|
public static Texture* Create2D(Device* device, int* size, byte mipLevel, uint textureFormat, uint flags, uint unk)
|
||||||
=> ((delegate* unmanaged<Device*, int*, byte, uint, uint, uint, Texture*>)Funcs.TextureCreate2D)(device, size, mipLevel, textureFormat, flags, unk);
|
=> ((delegate* unmanaged<Device*, int*, byte, uint, uint, uint, Texture*>)Funcs.TextureCreate2D)(device, size, mipLevel, textureFormat,
|
||||||
|
flags, unk);
|
||||||
|
|
||||||
public static bool InitializeContents(Texture* texture, void* contents)
|
public static bool InitializeContents(Texture* texture, void* contents)
|
||||||
=> ((delegate* unmanaged<Texture*, void*, bool>)Funcs.TextureInitializeContents)(texture, contents);
|
=> ((delegate* unmanaged<Texture*, void*, bool>)Funcs.TextureInitializeContents)(texture, contents);
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,7 @@ public readonly struct EqpManipulation : IMetaManipulation< EqpManipulation >
|
||||||
var entry = file[SetId];
|
var entry = file[SetId];
|
||||||
var mask = Eqp.Mask(Slot);
|
var mask = Eqp.Mask(Slot);
|
||||||
if ((entry & mask) == Entry)
|
if ((entry & mask) == Entry)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
file[SetId] = (entry & ~mask) | Entry;
|
file[SetId] = (entry & ~mask) | Entry;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -74,15 +74,11 @@ public readonly struct EstManipulation : IMetaManipulation< EstManipulation >
|
||||||
{
|
{
|
||||||
var r = Race.CompareTo(other.Race);
|
var r = Race.CompareTo(other.Race);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
{
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
var g = Gender.CompareTo(other.Gender);
|
var g = Gender.CompareTo(other.Gender);
|
||||||
if (g != 0)
|
if (g != 0)
|
||||||
{
|
|
||||||
return g;
|
return g;
|
||||||
}
|
|
||||||
|
|
||||||
var s = Slot.CompareTo(other.Slot);
|
var s = Slot.CompareTo(other.Slot);
|
||||||
return s != 0 ? s : SetId.Id.CompareTo(other.SetId.Id);
|
return s != 0 ? s : SetId.Id.CompareTo(other.SetId.Id);
|
||||||
|
|
@ -109,6 +105,7 @@ public readonly struct EstManipulation : IMetaManipulation< EstManipulation >
|
||||||
return false;
|
return false;
|
||||||
if (Names.CombinedRace(Gender, Race) == GenderRace.Unknown)
|
if (Names.CombinedRace(Gender, Race) == GenderRace.Unknown)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// No known check for set id or entry.
|
// No known check for set id or entry.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,17 +43,13 @@ public readonly struct GmpManipulation : IMetaManipulation< GmpManipulation >
|
||||||
{
|
{
|
||||||
var entry = file[SetId];
|
var entry = file[SetId];
|
||||||
if (entry == Entry)
|
if (entry == Entry)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
file[SetId] = Entry;
|
file[SetId] = Entry;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Validate()
|
public bool Validate()
|
||||||
{
|
|
||||||
// No known conditions.
|
// No known conditions.
|
||||||
return true;
|
=> true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ using Penumbra.Interop.Services;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ public class ModBackup
|
||||||
{
|
{
|
||||||
/// <summary> Set when reading Config and migrating from v4 to v5. </summary>
|
/// <summary> Set when reading Config and migrating from v4 to v5. </summary>
|
||||||
public static bool MigrateModBackups = false;
|
public static bool MigrateModBackups = false;
|
||||||
|
|
||||||
public static bool CreatingBackup { get; private set; }
|
public static bool CreatingBackup { get; private set; }
|
||||||
|
|
||||||
private readonly Mod _mod;
|
private readonly Mod _mod;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods.Editor;
|
namespace Penumbra.Mods.Editor;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Penumbra.Api.Enums;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.UI.ModsTab;
|
using Penumbra.UI.ModsTab;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
|
@ -146,6 +147,7 @@ public class ModMetaEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Split(currentOption.Manipulations);
|
Split(currentOption.Manipulations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Dalamud.Interface.Internal.Notifications;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Tasks;
|
using OtterGui.Tasks;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,20 @@ namespace Penumbra.Mods.ItemSwap;
|
||||||
public static class CustomizationSwap
|
public static class CustomizationSwap
|
||||||
{
|
{
|
||||||
/// The .mdl file for customizations is unique per racecode, slot and id, thus the .mdl redirection itself is independent of the mode.
|
/// The .mdl file for customizations is unique per racecode, slot and id, thus the .mdl redirection itself is independent of the mode.
|
||||||
public static FileSwap CreateMdl( MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, BodySlot slot, GenderRace race, SetId idFrom, SetId idTo )
|
public static FileSwap CreateMdl(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, BodySlot slot, GenderRace race,
|
||||||
|
SetId idFrom, SetId idTo)
|
||||||
{
|
{
|
||||||
if (idFrom.Id > byte.MaxValue)
|
if (idFrom.Id > byte.MaxValue)
|
||||||
{
|
|
||||||
throw new Exception($"The Customization ID {idFrom} is too large for {slot}.");
|
throw new Exception($"The Customization ID {idFrom} is too large for {slot}.");
|
||||||
}
|
|
||||||
|
|
||||||
var mdlPathFrom = GamePaths.Character.Mdl.Path(race, slot, idFrom, slot.ToCustomizationType());
|
var mdlPathFrom = GamePaths.Character.Mdl.Path(race, slot, idFrom, slot.ToCustomizationType());
|
||||||
var mdlPathTo = GamePaths.Character.Mdl.Path(race, slot, idTo, slot.ToCustomizationType());
|
var mdlPathTo = GamePaths.Character.Mdl.Path(race, slot, idTo, slot.ToCustomizationType());
|
||||||
|
|
||||||
var mdl = FileSwap.CreateSwap(manager, ResourceType.Mdl, redirections, mdlPathFrom, mdlPathTo);
|
var mdl = FileSwap.CreateSwap(manager, ResourceType.Mdl, redirections, mdlPathFrom, mdlPathTo);
|
||||||
var range = slot == BodySlot.Tail && race is GenderRace.HrothgarMale or GenderRace.HrothgarFemale or GenderRace.HrothgarMaleNpc or GenderRace.HrothgarMaleNpc ? 5 : 1;
|
var range = slot == BodySlot.Tail
|
||||||
|
&& race is GenderRace.HrothgarMale or GenderRace.HrothgarFemale or GenderRace.HrothgarMaleNpc or GenderRace.HrothgarMaleNpc
|
||||||
|
? 5
|
||||||
|
: 1;
|
||||||
|
|
||||||
foreach (ref var materialFileName in mdl.AsMdl()!.Materials.AsSpan())
|
foreach (ref var materialFileName in mdl.AsMdl()!.Materials.AsSpan())
|
||||||
{
|
{
|
||||||
|
|
@ -39,7 +41,8 @@ public static class CustomizationSwap
|
||||||
return mdl;
|
return mdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap CreateMtrl( MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, BodySlot slot, GenderRace race, SetId idFrom, SetId idTo, byte variant,
|
public static FileSwap CreateMtrl(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, BodySlot slot, GenderRace race,
|
||||||
|
SetId idFrom, SetId idTo, byte variant,
|
||||||
ref string fileName, ref bool dataWasChanged)
|
ref string fileName, ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
variant = slot is BodySlot.Face or BodySlot.Zear ? byte.MaxValue : variant;
|
variant = slot is BodySlot.Face or BodySlot.Zear ? byte.MaxValue : variant;
|
||||||
|
|
@ -49,7 +52,8 @@ public static class CustomizationSwap
|
||||||
var newFileName = fileName;
|
var newFileName = fileName;
|
||||||
newFileName = ItemSwap.ReplaceRace(newFileName, gameRaceTo, race, gameRaceTo != race);
|
newFileName = ItemSwap.ReplaceRace(newFileName, gameRaceTo, race, gameRaceTo != race);
|
||||||
newFileName = ItemSwap.ReplaceBody(newFileName, slot, idTo, idFrom, idFrom != idTo);
|
newFileName = ItemSwap.ReplaceBody(newFileName, slot, idTo, idFrom, idFrom != idTo);
|
||||||
newFileName = ItemSwap.AddSuffix( newFileName, ".mtrl", $"_c{race.ToRaceCode()}", gameRaceFrom != race || MaterialHandling.IsSpecialCase( race, idFrom ) );
|
newFileName = ItemSwap.AddSuffix(newFileName, ".mtrl", $"_c{race.ToRaceCode()}",
|
||||||
|
gameRaceFrom != race || MaterialHandling.IsSpecialCase(race, idFrom));
|
||||||
newFileName = ItemSwap.AddSuffix(newFileName, ".mtrl", $"_{slot.ToAbbreviation()}{idFrom.Id:D4}", gameSetIdFrom != idFrom);
|
newFileName = ItemSwap.AddSuffix(newFileName, ".mtrl", $"_{slot.ToAbbreviation()}{idFrom.Id:D4}", gameSetIdFrom != idFrom);
|
||||||
|
|
||||||
var actualMtrlFromPath = mtrlFromPath;
|
var actualMtrlFromPath = mtrlFromPath;
|
||||||
|
|
@ -73,7 +77,8 @@ public static class CustomizationSwap
|
||||||
return mtrl;
|
return mtrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap CreateTex( MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, BodySlot slot, GenderRace race, SetId idFrom, ref MtrlFile.Texture texture,
|
public static FileSwap CreateTex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, BodySlot slot, GenderRace race,
|
||||||
|
SetId idFrom, ref MtrlFile.Texture texture,
|
||||||
ref bool dataWasChanged)
|
ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var path = texture.Path;
|
var path = texture.Path;
|
||||||
|
|
@ -101,7 +106,8 @@ public static class CustomizationSwap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static FileSwap CreateShader( MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, ref string shaderName, ref bool dataWasChanged )
|
public static FileSwap CreateShader(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, ref string shaderName,
|
||||||
|
ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var path = $"shader/sm5/shpk/{shaderName}";
|
var path = $"shader/sm5/shpk/{shaderName}";
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Shpk, redirections, path, path);
|
return FileSwap.CreateSwap(manager, ResourceType.Shpk, redirections, path, path);
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,8 @@ public static class EquipmentSwap
|
||||||
{
|
{
|
||||||
items = identifier.Identify(slotFrom.IsEquipment()
|
items = identifier.Identify(slotFrom.IsEquipment()
|
||||||
? GamePaths.Equipment.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)
|
? GamePaths.Equipment.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)
|
||||||
: GamePaths.Accessory.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)).Select(kvp => kvp.Value).OfType<EquipItem>().ToArray();
|
: GamePaths.Accessory.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)).Select(kvp => kvp.Value).OfType<EquipItem>()
|
||||||
|
.ToArray();
|
||||||
variants = Enumerable.Range(0, imc.Count + 1).Select(i => (Variant)i).ToArray();
|
variants = Enumerable.Range(0, imc.Count + 1).Select(i => (Variant)i).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,11 +284,13 @@ public static class EquipmentSwap
|
||||||
return new MetaSwap(manips, manipFrom, manipTo);
|
return new MetaSwap(manips, manipFrom, manipTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot,
|
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||||
|
Func<MetaManipulation, MetaManipulation> manips, EquipSlot slot,
|
||||||
SetId idFrom, SetId idTo, Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
SetId idFrom, SetId idTo, Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||||
=> CreateImc(manager, redirections, manips, slot, slot, idFrom, idTo, variantFrom, variantTo, imcFileFrom, imcFileTo);
|
=> CreateImc(manager, redirections, manips, slot, slot, idFrom, idTo, variantFrom, variantTo, imcFileFrom, imcFileTo);
|
||||||
|
|
||||||
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, Func<MetaManipulation, MetaManipulation> manips,
|
public static MetaSwap CreateImc(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||||
|
Func<MetaManipulation, MetaManipulation> manips,
|
||||||
EquipSlot slotFrom, EquipSlot slotTo, SetId idFrom, SetId idTo,
|
EquipSlot slotFrom, EquipSlot slotTo, SetId idFrom, SetId idTo,
|
||||||
Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||||
{
|
{
|
||||||
|
|
@ -401,7 +404,8 @@ public static class EquipmentSwap
|
||||||
ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
||||||
=> CreateTex(manager, redirections, prefix, EquipSlot.Unknown, EquipSlot.Unknown, idFrom, idTo, ref texture, ref dataWasChanged);
|
=> CreateTex(manager, redirections, prefix, EquipSlot.Unknown, EquipSlot.Unknown, idFrom, idTo, ref texture, ref dataWasChanged);
|
||||||
|
|
||||||
public static FileSwap CreateTex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, char prefix, EquipSlot slotFrom, EquipSlot slotTo, SetId idFrom,
|
public static FileSwap CreateTex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, char prefix, EquipSlot slotFrom,
|
||||||
|
EquipSlot slotTo, SetId idFrom,
|
||||||
SetId idTo, ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
SetId idTo, ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var path = texture.Path;
|
var path = texture.Path;
|
||||||
|
|
@ -428,13 +432,15 @@ public static class EquipmentSwap
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Tex, redirections, newPath, path, path);
|
return FileSwap.CreateSwap(manager, ResourceType.Tex, redirections, newPath, path, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap CreateShader(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, ref string shaderName, ref bool dataWasChanged)
|
public static FileSwap CreateShader(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, ref string shaderName,
|
||||||
|
ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var path = $"shader/sm5/shpk/{shaderName}";
|
var path = $"shader/sm5/shpk/{shaderName}";
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Shpk, redirections, path, path);
|
return FileSwap.CreateSwap(manager, ResourceType.Shpk, redirections, path, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap CreateAtex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, ref string filePath, ref bool dataWasChanged)
|
public static FileSwap CreateAtex(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, ref string filePath,
|
||||||
|
ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var oldPath = filePath;
|
var oldPath = filePath;
|
||||||
filePath = ItemSwap.AddSuffix(filePath, ".atex", $"_{Path.GetFileName(filePath).GetStableHashCode():x8}");
|
filePath = ItemSwap.AddSuffix(filePath, ".atex", $"_{Path.GetFileName(filePath).GetStableHashCode():x8}");
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ public static class ItemSwap
|
||||||
private static bool LoadFile(MetaFileManager manager, FullPath path, out byte[] data)
|
private static bool LoadFile(MetaFileManager manager, FullPath path, out byte[] data)
|
||||||
{
|
{
|
||||||
if (path.FullName.Length > 0)
|
if (path.FullName.Length > 0)
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (path.IsRooted)
|
if (path.IsRooted)
|
||||||
|
|
@ -48,7 +47,6 @@ public static class ItemSwap
|
||||||
{
|
{
|
||||||
Penumbra.Log.Debug($"Could not load file {path}:\n{e}");
|
Penumbra.Log.Debug($"Could not load file {path}:\n{e}");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
data = Array.Empty<byte>();
|
data = Array.Empty<byte>();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -72,9 +70,7 @@ public static class ItemSwap
|
||||||
{
|
{
|
||||||
file = new GenericFile(manager, path);
|
file = new GenericFile(manager, path);
|
||||||
if (file.Valid)
|
if (file.Valid)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
file = null;
|
file = null;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -138,26 +134,27 @@ public static class ItemSwap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static FileSwap CreatePhyb(MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, EstManipulation.EstType type, GenderRace race, ushort estEntry )
|
public static FileSwap CreatePhyb(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, EstManipulation.EstType type,
|
||||||
|
GenderRace race, ushort estEntry)
|
||||||
{
|
{
|
||||||
var phybPath = GamePaths.Skeleton.Phyb.Path(race, EstManipulation.ToName(type), estEntry);
|
var phybPath = GamePaths.Skeleton.Phyb.Path(race, EstManipulation.ToName(type), estEntry);
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Phyb, redirections, phybPath, phybPath);
|
return FileSwap.CreateSwap(manager, ResourceType.Phyb, redirections, phybPath, phybPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap CreateSklb(MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, EstManipulation.EstType type, GenderRace race, ushort estEntry )
|
public static FileSwap CreateSklb(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, EstManipulation.EstType type,
|
||||||
|
GenderRace race, ushort estEntry)
|
||||||
{
|
{
|
||||||
var sklbPath = GamePaths.Skeleton.Sklb.Path(race, EstManipulation.ToName(type), estEntry);
|
var sklbPath = GamePaths.Skeleton.Sklb.Path(race, EstManipulation.ToName(type), estEntry);
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Sklb, redirections, sklbPath, sklbPath);
|
return FileSwap.CreateSwap(manager, ResourceType.Sklb, redirections, sklbPath, sklbPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks> metaChanges is not manipulated, but IReadOnlySet does not support TryGetValue. </remarks>
|
/// <remarks> metaChanges is not manipulated, but IReadOnlySet does not support TryGetValue. </remarks>
|
||||||
public static MetaSwap? CreateEst( MetaFileManager manager, Func< Utf8GamePath, FullPath > redirections, Func< MetaManipulation, MetaManipulation > manips, EstManipulation.EstType type,
|
public static MetaSwap? CreateEst(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||||
|
Func<MetaManipulation, MetaManipulation> manips, EstManipulation.EstType type,
|
||||||
GenderRace genderRace, SetId idFrom, SetId idTo, bool ownMdl)
|
GenderRace genderRace, SetId idFrom, SetId idTo, bool ownMdl)
|
||||||
{
|
{
|
||||||
if (type == 0)
|
if (type == 0)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
var (gender, race) = genderRace.Split();
|
var (gender, race) = genderRace.Split();
|
||||||
var fromDefault = new EstManipulation(gender, race, type, idFrom, EstFile.GetDefault(manager, type, genderRace, idFrom));
|
var fromDefault = new EstManipulation(gender, race, type, idFrom, EstFile.GetDefault(manager, type, genderRace, idFrom));
|
||||||
|
|
@ -190,9 +187,7 @@ public static class ItemSwap
|
||||||
{
|
{
|
||||||
hash1 = ((hash1 << 5) + hash1) ^ str[i];
|
hash1 = ((hash1 << 5) + hash1) ^ str[i];
|
||||||
if (i == str.Length - 1 || str[i + 1] == '\0')
|
if (i == str.Length - 1 || str[i + 1] == '\0')
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
|
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.Meta;
|
using Penumbra.Meta;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
namespace Penumbra.Mods.ItemSwap;
|
namespace Penumbra.Mods.ItemSwap;
|
||||||
|
|
@ -40,7 +41,8 @@ public class ItemSwapContainer
|
||||||
NoSwaps,
|
NoSwaps,
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteMod( ModManager manager, Mod mod, WriteType writeType = WriteType.NoSwaps, DirectoryInfo? directory = null, int groupIndex = -1, int optionIndex = 0 )
|
public bool WriteMod(ModManager manager, Mod mod, WriteType writeType = WriteType.NoSwaps, DirectoryInfo? directory = null,
|
||||||
|
int groupIndex = -1, int optionIndex = 0)
|
||||||
{
|
{
|
||||||
var convertedManips = new HashSet<MetaManipulation>(Swaps.Count);
|
var convertedManips = new HashSet<MetaManipulation>(Swaps.Count);
|
||||||
var convertedFiles = new Dictionary<Utf8GamePath, FullPath>(Swaps.Count);
|
var convertedFiles = new Dictionary<Utf8GamePath, FullPath>(Swaps.Count);
|
||||||
|
|
@ -55,9 +57,7 @@ public class ItemSwapContainer
|
||||||
case FileSwap file:
|
case FileSwap file:
|
||||||
// Skip, nothing to do
|
// Skip, nothing to do
|
||||||
if (file.SwapToModdedEqualsOriginal)
|
if (file.SwapToModdedEqualsOriginal)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (writeType == WriteType.UseSwaps && file.SwapToModdedExistsInGame && !file.DataWasChanged)
|
if (writeType == WriteType.UseSwaps && file.SwapToModdedExistsInGame && !file.DataWasChanged)
|
||||||
{
|
{
|
||||||
|
|
@ -75,9 +75,7 @@ public class ItemSwapContainer
|
||||||
break;
|
break;
|
||||||
case MetaSwap meta:
|
case MetaSwap meta:
|
||||||
if (!meta.SwapAppliedIsDefault)
|
if (!meta.SwapAppliedIsDefault)
|
||||||
{
|
|
||||||
convertedManips.Add(meta.SwapApplied);
|
convertedManips.Add(meta.SwapApplied);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -127,11 +125,13 @@ public class ItemSwapContainer
|
||||||
return m => set.TryGetValue(m, out var a) ? a : m;
|
return m => set.TryGetValue(m, out var a) ? a : m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquipItem[] LoadEquipment( EquipItem from, EquipItem to, ModCollection? collection = null, bool useRightRing = true, bool useLeftRing = true )
|
public EquipItem[] LoadEquipment(EquipItem from, EquipItem to, ModCollection? collection = null, bool useRightRing = true,
|
||||||
|
bool useLeftRing = true)
|
||||||
{
|
{
|
||||||
Swaps.Clear();
|
Swaps.Clear();
|
||||||
Loaded = false;
|
Loaded = false;
|
||||||
var ret = EquipmentSwap.CreateItemSwap( _manager, _identifier.AwaitedService, Swaps, PathResolver( collection ), MetaResolver( collection ), from, to, useRightRing, useLeftRing );
|
var ret = EquipmentSwap.CreateItemSwap(_manager, _identifier.AwaitedService, Swaps, PathResolver(collection), MetaResolver(collection),
|
||||||
|
from, to, useRightRing, useLeftRing);
|
||||||
Loaded = true;
|
Loaded = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -140,12 +140,14 @@ public class ItemSwapContainer
|
||||||
{
|
{
|
||||||
Swaps.Clear();
|
Swaps.Clear();
|
||||||
Loaded = false;
|
Loaded = false;
|
||||||
var ret = EquipmentSwap.CreateTypeSwap( _manager, _identifier.AwaitedService, Swaps, PathResolver( collection ), MetaResolver( collection ), slotFrom, from, slotTo, to );
|
var ret = EquipmentSwap.CreateTypeSwap(_manager, _identifier.AwaitedService, Swaps, PathResolver(collection), MetaResolver(collection),
|
||||||
|
slotFrom, from, slotTo, to);
|
||||||
Loaded = true;
|
Loaded = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LoadCustomization( MetaFileManager manager, BodySlot slot, GenderRace race, SetId from, SetId to, ModCollection? collection = null )
|
public bool LoadCustomization(MetaFileManager manager, BodySlot slot, GenderRace race, SetId from, SetId to,
|
||||||
|
ModCollection? collection = null)
|
||||||
{
|
{
|
||||||
var pathResolver = PathResolver(collection);
|
var pathResolver = PathResolver(collection);
|
||||||
var mdl = CustomizationSwap.CreateMdl(manager, pathResolver, slot, race, from, to);
|
var mdl = CustomizationSwap.CreateMdl(manager, pathResolver, slot, race, from, to);
|
||||||
|
|
@ -161,9 +163,7 @@ public class ItemSwapContainer
|
||||||
|
|
||||||
Swaps.Add(mdl);
|
Swaps.Add(mdl);
|
||||||
if (est != null)
|
if (est != null)
|
||||||
{
|
|
||||||
Swaps.Add(est);
|
Swaps.Add(est);
|
||||||
}
|
|
||||||
|
|
||||||
Loaded = true;
|
Loaded = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,9 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods.Manager;
|
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.Util;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Manager;
|
||||||
|
|
||||||
public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable
|
public sealed class ModFileSystem : FileSystem<Mod>, IDisposable, ISavable
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using Penumbra.Import;
|
using Penumbra.Import;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using Penumbra.Api.Enums;
|
||||||
using Penumbra.Mods.Subclasses;
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.Util;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods.Manager;
|
namespace Penumbra.Mods.Manager;
|
||||||
|
|
||||||
|
|
@ -19,7 +18,9 @@ public static partial class ModMigration
|
||||||
private static partial Regex GroupStartRegex();
|
private static partial Regex GroupStartRegex();
|
||||||
|
|
||||||
public static bool Migrate(ModCreator creator, SaveService saveService, Mod mod, JObject json, ref uint fileVersion)
|
public static bool Migrate(ModCreator creator, SaveService saveService, Mod mod, JObject json, ref uint fileVersion)
|
||||||
=> MigrateV0ToV1(creator, saveService, mod, json, ref fileVersion) || MigrateV1ToV2(saveService, mod, ref fileVersion) || MigrateV2ToV3(mod, ref fileVersion);
|
=> MigrateV0ToV1(creator, saveService, mod, json, ref fileVersion)
|
||||||
|
|| MigrateV1ToV2(saveService, mod, ref fileVersion)
|
||||||
|
|| MigrateV2ToV3(mod, ref fileVersion);
|
||||||
|
|
||||||
private static bool MigrateV2ToV3(Mod _, ref uint fileVersion)
|
private static bool MigrateV2ToV3(Mod _, ref uint fileVersion)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
public sealed partial class Mod : IMod
|
public sealed class Mod : IMod
|
||||||
{
|
{
|
||||||
public static readonly TemporaryMod ForcedFiles = new()
|
public static readonly TemporaryMod ForcedFiles = new()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -113,10 +113,8 @@ public partial class ModCreator
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes)
|
if (changes)
|
||||||
{
|
|
||||||
_saveService.SaveAllOptionGroups(mod, true);
|
_saveService.SaveAllOptionGroups(mod, true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Load the default option for a given mod.</summary>
|
/// <summary> Load the default option for a given mod.</summary>
|
||||||
public void LoadDefaultOption(Mod mod)
|
public void LoadDefaultOption(Mod mod)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.Util;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.Util;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Subclasses;
|
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
public interface ISubMod
|
public interface ISubMod
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,9 @@ using OtterGui.Filesystem;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Mods.Subclasses;
|
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
/// <summary> Contains the settings for a given mod. </summary>
|
/// <summary> Contains the settings for a given mod. </summary>
|
||||||
public class ModSettings
|
public class ModSettings
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,8 @@ using Newtonsoft.Json.Linq;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Mods.Subclasses;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
/// <summary> Groups that allow all available options to be selected at once. </summary>
|
/// <summary> Groups that allow all available options to be selected at once. </summary>
|
||||||
public sealed class MultiModGroup : IModGroup
|
public sealed class MultiModGroup : IModGroup
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,8 @@ using Newtonsoft.Json.Linq;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Mods.Subclasses;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
/// <summary> Groups that allow only one of their available options to be selected. </summary>
|
/// <summary> Groups that allow only one of their available options to be selected. </summary>
|
||||||
public sealed class SingleModGroup : IModGroup
|
public sealed class SingleModGroup : IModGroup
|
||||||
|
|
@ -47,12 +46,9 @@ public sealed class SingleModGroup : IModGroup
|
||||||
DefaultSettings = json[nameof(DefaultSettings)]?.ToObject<uint>() ?? 0u,
|
DefaultSettings = json[nameof(DefaultSettings)]?.ToObject<uint>() ?? 0u,
|
||||||
};
|
};
|
||||||
if (ret.Name.Length == 0)
|
if (ret.Name.Length == 0)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
if (options != null)
|
if (options != null)
|
||||||
{
|
|
||||||
foreach (var child in options.Children())
|
foreach (var child in options.Children())
|
||||||
{
|
{
|
||||||
var subMod = new SubMod(mod);
|
var subMod = new SubMod(mod);
|
||||||
|
|
@ -60,7 +56,6 @@ public sealed class SingleModGroup : IModGroup
|
||||||
subMod.Load(mod.ModPath, child, out _);
|
subMod.Load(mod.ModPath, child, out _);
|
||||||
ret.OptionData.Add(subMod);
|
ret.OptionData.Add(subMod);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)ret.DefaultSettings >= ret.Count)
|
if ((int)ret.DefaultSettings >= ret.Count)
|
||||||
ret.DefaultSettings = 0;
|
ret.DefaultSettings = 0;
|
||||||
|
|
@ -90,9 +85,7 @@ public sealed class SingleModGroup : IModGroup
|
||||||
public bool MoveOption(int optionIdxFrom, int optionIdxTo)
|
public bool MoveOption(int optionIdxFrom, int optionIdxTo)
|
||||||
{
|
{
|
||||||
if (!OptionData.Move(optionIdxFrom, optionIdxTo))
|
if (!OptionData.Move(optionIdxFrom, optionIdxTo))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Update default settings with the move.
|
// Update default settings with the move.
|
||||||
if (DefaultSettings == optionIdxFrom)
|
if (DefaultSettings == optionIdxFrom)
|
||||||
|
|
@ -102,10 +95,8 @@ public sealed class SingleModGroup : IModGroup
|
||||||
else if (optionIdxFrom < optionIdxTo)
|
else if (optionIdxFrom < optionIdxTo)
|
||||||
{
|
{
|
||||||
if (DefaultSettings > optionIdxFrom && DefaultSettings <= optionIdxTo)
|
if (DefaultSettings > optionIdxFrom && DefaultSettings <= optionIdxTo)
|
||||||
{
|
|
||||||
--DefaultSettings;
|
--DefaultSettings;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (DefaultSettings < optionIdxFrom && DefaultSettings >= optionIdxTo)
|
else if (DefaultSettings < optionIdxFrom && DefaultSettings >= optionIdxTo)
|
||||||
{
|
{
|
||||||
++DefaultSettings;
|
++DefaultSettings;
|
||||||
|
|
@ -118,8 +109,6 @@ public sealed class SingleModGroup : IModGroup
|
||||||
public void UpdatePositions(int from = 0)
|
public void UpdatePositions(int from = 0)
|
||||||
{
|
{
|
||||||
foreach (var (o, i) in OptionData.WithIndex().Skip(from))
|
foreach (var (o, i) in OptionData.WithIndex().Skip(from))
|
||||||
{
|
|
||||||
o.SetPosition(o.GroupIdx, i);
|
o.SetPosition(o.GroupIdx, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.Import;
|
|
||||||
using Penumbra.Meta;
|
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods.Subclasses;
|
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods.Subclasses;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sub mod is a collection of
|
/// A sub mod is a collection of
|
||||||
|
|
@ -5,7 +5,6 @@ using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Mods.Subclasses;
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.Util;
|
|
||||||
|
|
||||||
namespace Penumbra.Mods;
|
namespace Penumbra.Mods;
|
||||||
|
|
||||||
|
|
@ -27,7 +26,10 @@ public class TemporaryMod : IMod
|
||||||
=> Array.Empty<IModGroup>();
|
=> Array.Empty<IModGroup>();
|
||||||
|
|
||||||
public IEnumerable<SubMod> AllSubMods
|
public IEnumerable<SubMod> AllSubMods
|
||||||
=> new[] { Default };
|
=> new[]
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
};
|
||||||
|
|
||||||
public TemporaryMod()
|
public TemporaryMod()
|
||||||
=> Default = new SubMod(this);
|
=> Default = new SubMod(this);
|
||||||
|
|
@ -44,7 +46,8 @@ public class TemporaryMod : IMod
|
||||||
Default.ManipulationData = manips;
|
Default.ManipulationData = manips;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveTempCollection( Configuration config, SaveService saveService, ModManager modManager, ModCollection collection, string? character = null )
|
public static void SaveTempCollection(Configuration config, SaveService saveService, ModManager modManager, ModCollection collection,
|
||||||
|
string? character = null)
|
||||||
{
|
{
|
||||||
DirectoryInfo? dir = null;
|
DirectoryInfo? dir = null;
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ using Penumbra.UI.Tabs;
|
||||||
using ChangedItemClick = Penumbra.Communication.ChangedItemClick;
|
using ChangedItemClick = Penumbra.Communication.ChangedItemClick;
|
||||||
using ChangedItemHover = Penumbra.Communication.ChangedItemHover;
|
using ChangedItemHover = Penumbra.Communication.ChangedItemHover;
|
||||||
using OtterGui.Tasks;
|
using OtterGui.Tasks;
|
||||||
|
using Penumbra.UI;
|
||||||
|
|
||||||
namespace Penumbra;
|
namespace Penumbra;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using Penumbra.Interop.Services;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
namespace Penumbra.Services;
|
namespace Penumbra.Services;
|
||||||
|
|
@ -331,7 +332,8 @@ public class ConfigMigrationService
|
||||||
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value with { Priority = maxPriority - kvp.Value.Priority });
|
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value with { Priority = maxPriority - kvp.Value.Priority });
|
||||||
|
|
||||||
var emptyStorage = new ModStorage();
|
var emptyStorage = new ModStorage();
|
||||||
var collection = ModCollection.CreateFromData(_saveService, emptyStorage, ModCollection.DefaultCollectionName, 0, 1, dict, Array.Empty<string>());
|
var collection = ModCollection.CreateFromData(_saveService, emptyStorage, ModCollection.DefaultCollectionName, 0, 1, dict,
|
||||||
|
Array.Empty<string>());
|
||||||
_saveService.ImmediateSave(new ModCollectionSave(emptyStorage, collection));
|
_saveService.ImmediateSave(new ModCollectionSave(emptyStorage, collection));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using Dalamud.Game.Gui;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using System.Reflection;
|
|
||||||
using Dalamud.Interface.DragDrop;
|
using Dalamud.Interface.DragDrop;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ using Penumbra.UI;
|
||||||
using Penumbra.UI.AdvancedWindow;
|
using Penumbra.UI.AdvancedWindow;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
using Penumbra.UI.ModsTab;
|
using Penumbra.UI.ModsTab;
|
||||||
|
using Penumbra.UI.ResourceWatcher;
|
||||||
using Penumbra.UI.Tabs;
|
using Penumbra.UI.Tabs;
|
||||||
|
|
||||||
namespace Penumbra.Services;
|
namespace Penumbra.Services;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ public class StainService : IDisposable
|
||||||
{
|
{
|
||||||
using var t = timer.Measure(StartTimeType.Stains);
|
using var t = timer.Measure(StartTimeType.Stains);
|
||||||
StainData = new StainData(pluginInterface, dataManager, dataManager.Language);
|
StainData = new StainData(pluginInterface, dataManager, dataManager.Language);
|
||||||
StainCombo = new FilterComboColors(140, StainData.Data.Prepend(new KeyValuePair<byte, (string Name, uint Dye, bool Gloss)>(0, ("None", 0, false))));
|
StainCombo = new FilterComboColors(140,
|
||||||
|
StainData.Data.Prepend(new KeyValuePair<byte, (string Name, uint Dye, bool Gloss)>(0, ("None", 0, false))));
|
||||||
StmFile = new StmFile(dataManager);
|
StmFile = new StmFile(dataManager);
|
||||||
TemplateCombo = new StainTemplateCombo(StmFile.Entries.Keys.Prepend((ushort)0));
|
TemplateCombo = new StainTemplateCombo(StmFile.Entries.Keys.Prepend((ushort)0));
|
||||||
Penumbra.Log.Verbose($"[{nameof(StainService)}] Created.");
|
Penumbra.Log.Verbose($"[{nameof(StainService)}] Created.");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Reflection;
|
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
|
||||||
|
|
@ -34,7 +33,8 @@ public class ValidityChecker
|
||||||
public void LogExceptions()
|
public void LogExceptions()
|
||||||
{
|
{
|
||||||
if (ImcExceptions.Count > 0)
|
if (ImcExceptions.Count > 0)
|
||||||
Penumbra.Chat.NotificationMessage( $"{ImcExceptions} IMC Exceptions thrown during Penumbra load. Please repair your game files.", "Warning", NotificationType.Warning );
|
Penumbra.Chat.NotificationMessage($"{ImcExceptions} IMC Exceptions thrown during Penumbra load. Please repair your game files.",
|
||||||
|
"Warning", NotificationType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because remnants of penumbra in devPlugins cause issues, we check for them to warn users to remove them.
|
// Because remnants of penumbra in devPlugins cause issues, we check for them to warn users to remove them.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ namespace Penumbra.Services;
|
||||||
public sealed class IdentifierService : AsyncServiceWrapper<IObjectIdentifier>
|
public sealed class IdentifierService : AsyncServiceWrapper<IObjectIdentifier>
|
||||||
{
|
{
|
||||||
public IdentifierService(StartTracker tracker, DalamudPluginInterface pi, IDataManager data, ItemService items)
|
public IdentifierService(StartTracker tracker, DalamudPluginInterface pi, IDataManager data, ItemService items)
|
||||||
: base(nameof(IdentifierService), tracker, StartTimeType.Identifier, () => GameData.GameData.GetIdentifier(pi, data, items.AwaitedService))
|
: base(nameof(IdentifierService), tracker, StartTimeType.Identifier,
|
||||||
|
() => GameData.GameData.GetIdentifier(pi, data, items.AwaitedService))
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,10 +114,8 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
if (tab.Mtrl.HasDyeTable)
|
if (tab.Mtrl.HasDyeTable)
|
||||||
{
|
|
||||||
for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
for (var i = 0; i < MtrlFile.ColorTable.NumRows; ++i)
|
||||||
ret |= tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, i, dyeId);
|
ret |= tab.Mtrl.ApplyDyeTemplate(_stainService.StmFile, i, dyeId);
|
||||||
}
|
|
||||||
|
|
||||||
tab.UpdateColorTablePreview();
|
tab.UpdateColorTablePreview();
|
||||||
|
|
||||||
|
|
@ -301,7 +299,8 @@ public partial class ModEditWindow
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
var tmpFloat = row.SpecularStrength;
|
var tmpFloat = row.SpecularStrength;
|
||||||
ImGui.SetNextItemWidth(floatSize);
|
ImGui.SetNextItemWidth(floatSize);
|
||||||
if (ImGui.DragFloat("##SpecularStrength", ref tmpFloat, 0.01f, 0f, HalfMaxValue, "%.2f") && FixFloat(ref tmpFloat, row.SpecularStrength))
|
if (ImGui.DragFloat("##SpecularStrength", ref tmpFloat, 0.01f, 0f, HalfMaxValue, "%.2f")
|
||||||
|
&& FixFloat(ref tmpFloat, row.SpecularStrength))
|
||||||
{
|
{
|
||||||
row.SpecularStrength = tmpFloat;
|
row.SpecularStrength = tmpFloat;
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ using Penumbra.Interop.Structs;
|
||||||
using Penumbra.Meta;
|
using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
using Penumbra.Mods;
|
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
|
@ -66,17 +65,23 @@ public partial class ModEditWindow
|
||||||
if (!child)
|
if (!child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DrawEditHeader(_editor.MetaEditor.Eqp, "Equipment Parameter Edits (EQP)###EQP", 5, EqpRow.Draw, EqpRow.DrawNew , _editor.MetaEditor.OtherEqpCount);
|
DrawEditHeader(_editor.MetaEditor.Eqp, "Equipment Parameter Edits (EQP)###EQP", 5, EqpRow.Draw, EqpRow.DrawNew,
|
||||||
DrawEditHeader(_editor.MetaEditor.Eqdp, "Racial Model Edits (EQDP)###EQDP", 7, EqdpRow.Draw, EqdpRow.DrawNew, _editor.MetaEditor.OtherEqdpCount);
|
_editor.MetaEditor.OtherEqpCount);
|
||||||
|
DrawEditHeader(_editor.MetaEditor.Eqdp, "Racial Model Edits (EQDP)###EQDP", 7, EqdpRow.Draw, EqdpRow.DrawNew,
|
||||||
|
_editor.MetaEditor.OtherEqdpCount);
|
||||||
DrawEditHeader(_editor.MetaEditor.Imc, "Variant Edits (IMC)###IMC", 10, ImcRow.Draw, ImcRow.DrawNew, _editor.MetaEditor.OtherImcCount);
|
DrawEditHeader(_editor.MetaEditor.Imc, "Variant Edits (IMC)###IMC", 10, ImcRow.Draw, ImcRow.DrawNew, _editor.MetaEditor.OtherImcCount);
|
||||||
DrawEditHeader(_editor.MetaEditor.Est, "Extra Skeleton Parameters (EST)###EST", 7, EstRow.Draw, EstRow.DrawNew , _editor.MetaEditor.OtherEstCount);
|
DrawEditHeader(_editor.MetaEditor.Est, "Extra Skeleton Parameters (EST)###EST", 7, EstRow.Draw, EstRow.DrawNew,
|
||||||
DrawEditHeader(_editor.MetaEditor.Gmp, "Visor/Gimmick Edits (GMP)###GMP", 7, GmpRow.Draw, GmpRow.DrawNew , _editor.MetaEditor.OtherGmpCount);
|
_editor.MetaEditor.OtherEstCount);
|
||||||
DrawEditHeader(_editor.MetaEditor.Rsp, "Racial Scaling Edits (RSP)###RSP", 5, RspRow.Draw, RspRow.DrawNew , _editor.MetaEditor.OtherRspCount);
|
DrawEditHeader(_editor.MetaEditor.Gmp, "Visor/Gimmick Edits (GMP)###GMP", 7, GmpRow.Draw, GmpRow.DrawNew,
|
||||||
|
_editor.MetaEditor.OtherGmpCount);
|
||||||
|
DrawEditHeader(_editor.MetaEditor.Rsp, "Racial Scaling Edits (RSP)###RSP", 5, RspRow.Draw, RspRow.DrawNew,
|
||||||
|
_editor.MetaEditor.OtherRspCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary> The headers for the different meta changes all have basically the same structure for different types.</summary>
|
/// <summary> The headers for the different meta changes all have basically the same structure for different types.</summary>
|
||||||
private void DrawEditHeader<T>(IReadOnlyCollection<T> items, string label, int numColumns, Action<MetaFileManager, T, ModEditor, Vector2> draw,
|
private void DrawEditHeader<T>(IReadOnlyCollection<T> items, string label, int numColumns,
|
||||||
|
Action<MetaFileManager, T, ModEditor, Vector2> draw,
|
||||||
Action<MetaFileManager, ModEditor, Vector2> drawNew, int otherCount)
|
Action<MetaFileManager, ModEditor, Vector2> drawNew, int otherCount)
|
||||||
{
|
{
|
||||||
const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.BordersInnerV;
|
const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.BordersInnerV;
|
||||||
|
|
@ -92,6 +97,7 @@ public partial class ModEditWindow
|
||||||
ImGuiUtil.TextColored(ColorId.RedundantAssignment.Value() | 0xFF000000, text);
|
ImGuiUtil.TextColored(ColorId.RedundantAssignment.Value() | 0xFF000000, text);
|
||||||
ImGui.SetCursorPos(newPos);
|
ImGui.SetCursorPos(newPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!header)
|
if (!header)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -223,7 +229,8 @@ public partial class ModEditWindow
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (IdInput("##eqdpId", IdWidth, _new.SetId.Id, out var setId, 0, ExpandedEqpGmpBase.Count - 1, _new.SetId <= 1))
|
if (IdInput("##eqdpId", IdWidth, _new.SetId.Id, out var setId, 0, ExpandedEqpGmpBase.Count - 1, _new.SetId <= 1))
|
||||||
{
|
{
|
||||||
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, _new.Race), _new.Slot.IsAccessory(), setId);
|
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, _new.Race),
|
||||||
|
_new.Slot.IsAccessory(), setId);
|
||||||
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, _new.Gender, _new.Race, setId);
|
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, _new.Gender, _new.Race, setId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +239,8 @@ public partial class ModEditWindow
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (Combos.Race("##eqdpRace", _new.Race, out var race))
|
if (Combos.Race("##eqdpRace", _new.Race, out var race))
|
||||||
{
|
{
|
||||||
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, race), _new.Slot.IsAccessory(), _new.SetId);
|
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, race),
|
||||||
|
_new.Slot.IsAccessory(), _new.SetId);
|
||||||
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, _new.Gender, race, _new.SetId);
|
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, _new.Gender, race, _new.SetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,7 +249,8 @@ public partial class ModEditWindow
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (Combos.Gender("##eqdpGender", _new.Gender, out var gender))
|
if (Combos.Gender("##eqdpGender", _new.Gender, out var gender))
|
||||||
{
|
{
|
||||||
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(gender, _new.Race), _new.Slot.IsAccessory(), _new.SetId);
|
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(gender, _new.Race),
|
||||||
|
_new.Slot.IsAccessory(), _new.SetId);
|
||||||
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, gender, _new.Race, _new.SetId);
|
_new = new EqdpManipulation(newDefaultEntry, _new.Slot, gender, _new.Race, _new.SetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +259,8 @@ public partial class ModEditWindow
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
if (Combos.EqdpEquipSlot("##eqdpSlot", _new.Slot, out var slot))
|
if (Combos.EqdpEquipSlot("##eqdpSlot", _new.Slot, out var slot))
|
||||||
{
|
{
|
||||||
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, _new.Race), slot.IsAccessory(), _new.SetId);
|
var newDefaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(_new.Gender, _new.Race),
|
||||||
|
slot.IsAccessory(), _new.SetId);
|
||||||
_new = new EqdpManipulation(newDefaultEntry, slot, _new.Gender, _new.Race, _new.SetId);
|
_new = new EqdpManipulation(newDefaultEntry, slot, _new.Gender, _new.Race, _new.SetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +298,8 @@ public partial class ModEditWindow
|
||||||
ImGuiUtil.HoverTooltip(EquipSlotTooltip);
|
ImGuiUtil.HoverTooltip(EquipSlotTooltip);
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
var defaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(meta.Gender, meta.Race), meta.Slot.IsAccessory(), meta.SetId);
|
var defaultEntry = ExpandedEqdpFile.GetDefault(metaFileManager, Names.CombinedRace(meta.Gender, meta.Race), meta.Slot.IsAccessory(),
|
||||||
|
meta.SetId);
|
||||||
var (defaultBit1, defaultBit2) = defaultEntry.ToBits(meta.Slot);
|
var (defaultBit1, defaultBit2) = defaultEntry.ToBits(meta.Slot);
|
||||||
var (bit1, bit2) = meta.Entry.ToBits(meta.Slot);
|
var (bit1, bit2) = meta.Entry.ToBits(meta.Slot);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
@ -370,7 +381,8 @@ public partial class ModEditWindow
|
||||||
if (_new.ObjectType is ObjectType.Equipment)
|
if (_new.ObjectType is ObjectType.Equipment)
|
||||||
{
|
{
|
||||||
if (Combos.EqpEquipSlot("##imcSlot", 100, _new.EquipSlot, out var slot))
|
if (Combos.EqpEquipSlot("##imcSlot", 100, _new.EquipSlot, out var slot))
|
||||||
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot, _new.Entry)
|
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot,
|
||||||
|
_new.Entry)
|
||||||
.Copy(GetDefault(metaFileManager, _new)
|
.Copy(GetDefault(metaFileManager, _new)
|
||||||
?? new ImcEntry());
|
?? new ImcEntry());
|
||||||
|
|
||||||
|
|
@ -379,7 +391,8 @@ public partial class ModEditWindow
|
||||||
else if (_new.ObjectType is ObjectType.Accessory)
|
else if (_new.ObjectType is ObjectType.Accessory)
|
||||||
{
|
{
|
||||||
if (Combos.AccessorySlot("##imcSlot", _new.EquipSlot, out var slot))
|
if (Combos.AccessorySlot("##imcSlot", _new.EquipSlot, out var slot))
|
||||||
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot, _new.Entry)
|
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot,
|
||||||
|
_new.Entry)
|
||||||
.Copy(GetDefault(metaFileManager, _new)
|
.Copy(GetDefault(metaFileManager, _new)
|
||||||
?? new ImcEntry());
|
?? new ImcEntry());
|
||||||
|
|
||||||
|
|
@ -388,7 +401,8 @@ public partial class ModEditWindow
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IdInput("##imcId2", 100 * UiHelpers.Scale, _new.SecondaryId.Id, out var setId2, 0, ushort.MaxValue, false))
|
if (IdInput("##imcId2", 100 * UiHelpers.Scale, _new.SecondaryId.Id, out var setId2, 0, ushort.MaxValue, false))
|
||||||
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, setId2, _new.Variant.Id, _new.EquipSlot, _new.Entry)
|
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, setId2, _new.Variant.Id, _new.EquipSlot,
|
||||||
|
_new.Entry)
|
||||||
.Copy(GetDefault(metaFileManager, _new)
|
.Copy(GetDefault(metaFileManager, _new)
|
||||||
?? new ImcEntry());
|
?? new ImcEntry());
|
||||||
|
|
||||||
|
|
@ -405,7 +419,8 @@ public partial class ModEditWindow
|
||||||
if (_new.ObjectType is ObjectType.DemiHuman)
|
if (_new.ObjectType is ObjectType.DemiHuman)
|
||||||
{
|
{
|
||||||
if (Combos.EqpEquipSlot("##imcSlot", 70, _new.EquipSlot, out var slot))
|
if (Combos.EqpEquipSlot("##imcSlot", 70, _new.EquipSlot, out var slot))
|
||||||
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot, _new.Entry)
|
_new = new ImcManipulation(_new.ObjectType, _new.BodySlot, _new.PrimaryId, _new.SecondaryId, _new.Variant.Id, slot,
|
||||||
|
_new.Entry)
|
||||||
.Copy(GetDefault(metaFileManager, _new)
|
.Copy(GetDefault(metaFileManager, _new)
|
||||||
?? new ImcEntry());
|
?? new ImcEntry());
|
||||||
|
|
||||||
|
|
@ -787,7 +802,8 @@ public partial class ModEditWindow
|
||||||
using var color = ImRaii.PushColor(ImGuiCol.FrameBg,
|
using var color = ImRaii.PushColor(ImGuiCol.FrameBg,
|
||||||
def < value ? ColorId.IncreasedMetaValue.Value() : ColorId.DecreasedMetaValue.Value(),
|
def < value ? ColorId.IncreasedMetaValue.Value() : ColorId.DecreasedMetaValue.Value(),
|
||||||
def != value);
|
def != value);
|
||||||
if (ImGui.DragFloat("##rspValue", ref value, 0.001f, RspManipulation.MinValue, RspManipulation.MaxValue) && value is >= RspManipulation.MinValue and <= RspManipulation.MaxValue)
|
if (ImGui.DragFloat("##rspValue", ref value, 0.001f, RspManipulation.MinValue, RspManipulation.MaxValue)
|
||||||
|
&& value is >= RspManipulation.MinValue and <= RspManipulation.MaxValue)
|
||||||
editor.MetaEditor.Change(meta.Copy(value));
|
editor.MetaEditor.Change(meta.Copy(value));
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip($"Default Value: {def:0.###}");
|
ImGuiUtil.HoverTooltip($"Default Value: {def:0.###}");
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,7 @@ public partial class ModEditWindow
|
||||||
private static bool DrawOtherModelDetails(MdlFile file, bool _)
|
private static bool DrawOtherModelDetails(MdlFile file, bool _)
|
||||||
{
|
{
|
||||||
if (!ImGui.CollapsingHeader("Further Content"))
|
if (!ImGui.CollapsingHeader("Further Content"))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
using (var table = ImRaii.Table("##data", 2, ImGuiTableFlags.SizingFixedFit))
|
using (var table = ImRaii.Table("##data", 2, ImGuiTableFlags.SizingFixedFit))
|
||||||
{
|
{
|
||||||
|
|
@ -88,46 +86,31 @@ public partial class ModEditWindow
|
||||||
using (var attributes = ImRaii.TreeNode("Attributes", ImGuiTreeNodeFlags.DefaultOpen))
|
using (var attributes = ImRaii.TreeNode("Attributes", ImGuiTreeNodeFlags.DefaultOpen))
|
||||||
{
|
{
|
||||||
if (attributes)
|
if (attributes)
|
||||||
{
|
|
||||||
foreach (var attribute in file.Attributes)
|
foreach (var attribute in file.Attributes)
|
||||||
{
|
|
||||||
ImRaii.TreeNode(attribute, ImGuiTreeNodeFlags.Leaf).Dispose();
|
ImRaii.TreeNode(attribute, ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var bones = ImRaii.TreeNode("Bones", ImGuiTreeNodeFlags.DefaultOpen))
|
using (var bones = ImRaii.TreeNode("Bones", ImGuiTreeNodeFlags.DefaultOpen))
|
||||||
{
|
{
|
||||||
if (bones)
|
if (bones)
|
||||||
{
|
|
||||||
foreach (var bone in file.Bones)
|
foreach (var bone in file.Bones)
|
||||||
{
|
|
||||||
ImRaii.TreeNode(bone, ImGuiTreeNodeFlags.Leaf).Dispose();
|
ImRaii.TreeNode(bone, ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var shapes = ImRaii.TreeNode("Shapes", ImGuiTreeNodeFlags.DefaultOpen))
|
using (var shapes = ImRaii.TreeNode("Shapes", ImGuiTreeNodeFlags.DefaultOpen))
|
||||||
{
|
{
|
||||||
if (shapes)
|
if (shapes)
|
||||||
{
|
|
||||||
foreach (var shape in file.Shapes)
|
foreach (var shape in file.Shapes)
|
||||||
{
|
|
||||||
ImRaii.TreeNode(shape.ShapeName, ImGuiTreeNodeFlags.Leaf).Dispose();
|
ImRaii.TreeNode(shape.ShapeName, ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.RemainingData.Length > 0)
|
if (file.RemainingData.Length > 0)
|
||||||
{
|
{
|
||||||
using var t = ImRaii.TreeNode($"Additional Data (Size: {file.RemainingData.Length})###AdditionalData");
|
using var t = ImRaii.TreeNode($"Additional Data (Size: {file.RemainingData.Length})###AdditionalData");
|
||||||
if (t)
|
if (t)
|
||||||
{
|
|
||||||
ImGuiUtil.TextWrapped(string.Join(' ', file.RemainingData.Select(c => $"{c:X2}")));
|
ImGuiUtil.TextWrapped(string.Join(' ', file.RemainingData.Select(c => $"{c:X2}")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using Penumbra.GameData.Files;
|
||||||
using Penumbra.Interop.ResourceTree;
|
using Penumbra.Interop.ResourceTree;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
|
||||||
|
|
@ -489,16 +489,22 @@ public partial class ModEditWindow
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SystemKeys.WithIndex())
|
foreach (var (key, keyIdx) in node.SystemKeys.WithIndex())
|
||||||
|
{
|
||||||
ImRaii.TreeNode($"System Key 0x{tab.Shpk.SystemKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
ImRaii.TreeNode($"System Key 0x{tab.Shpk.SystemKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SceneKeys.WithIndex())
|
foreach (var (key, keyIdx) in node.SceneKeys.WithIndex())
|
||||||
|
{
|
||||||
ImRaii.TreeNode($"Scene Key 0x{tab.Shpk.SceneKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
ImRaii.TreeNode($"Scene Key 0x{tab.Shpk.SceneKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.MaterialKeys.WithIndex())
|
foreach (var (key, keyIdx) in node.MaterialKeys.WithIndex())
|
||||||
|
{
|
||||||
ImRaii.TreeNode($"Material Key 0x{tab.Shpk.MaterialKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
ImRaii.TreeNode($"Material Key 0x{tab.Shpk.MaterialKeys[keyIdx].Id:X8} = 0x{key:X8}",
|
||||||
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var (key, keyIdx) in node.SubViewKeys.WithIndex())
|
foreach (var (key, keyIdx) in node.SubViewKeys.WithIndex())
|
||||||
ImRaii.TreeNode($"Sub-View Key #{keyIdx} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
ImRaii.TreeNode($"Sub-View Key #{keyIdx} = 0x{key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose();
|
||||||
|
|
@ -530,10 +536,12 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
using var font = ImRaii.PushFont(UiBuilder.MonoFont);
|
||||||
foreach (var selector in tab.Shpk.NodeSelectors)
|
foreach (var selector in tab.Shpk.NodeSelectors)
|
||||||
|
{
|
||||||
ImRaii.TreeNode($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
ImRaii.TreeNode($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet)
|
||||||
.Dispose();
|
.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
private static void DrawOtherShaderPackageDetails(ShpkTab tab)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,8 @@ public partial class ModEditWindow
|
||||||
private void OpenSaveAsDialog(string defaultExtension)
|
private void OpenSaveAsDialog(string defaultExtension)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(_left.Path.Length > 0 ? _left.Path : _right.Path);
|
var fileName = Path.GetFileNameWithoutExtension(_left.Path.Length > 0 ? _left.Path : _right.Path);
|
||||||
_fileDialog.OpenSavePicker("Save Texture as TEX, DDS or PNG...", "Textures{.png,.dds,.tex},.tex,.dds,.png", fileName, defaultExtension, (a, b) =>
|
_fileDialog.OpenSavePicker("Save Texture as TEX, DDS or PNG...", "Textures{.png,.dds,.tex},.tex,.dds,.png", fileName, defaultExtension,
|
||||||
|
(a, b) =>
|
||||||
{
|
{
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Compression;
|
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
|
|
@ -19,6 +18,7 @@ using Penumbra.Meta;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ using Dalamud.Interface;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.Mods;
|
|
||||||
using Penumbra.Mods.Editor;
|
using Penumbra.Mods.Editor;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ public class ResourceTreeViewer
|
||||||
ImGui.Dummy(new Vector2(ImGui.GetFrameHeight()));
|
ImGui.Dummy(new Vector2(ImGui.GetFrameHeight()));
|
||||||
ImGui.SameLine(0f, ImGui.GetStyle().ItemInnerSpacing.X);
|
ImGui.SameLine(0f, ImGui.GetStyle().ItemInnerSpacing.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
_changedItemDrawer.DrawCategoryIcon(resourceNode.Icon);
|
_changedItemDrawer.DrawCategoryIcon(resourceNode.Icon);
|
||||||
ImGui.SameLine(0f, ImGui.GetStyle().ItemInnerSpacing.X);
|
ImGui.SameLine(0f, ImGui.GetStyle().ItemInnerSpacing.X);
|
||||||
ImGui.TableHeader(resourceNode.Name);
|
ImGui.TableHeader(resourceNode.Name);
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,17 @@ public class PenumbraChangelog
|
||||||
|
|
||||||
private static void Add7_3_0(Changelog log)
|
private static void Add7_3_0(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.3.0")
|
=> log.NextVersion("Version 0.7.3.0")
|
||||||
.RegisterEntry("Added the ability to drag and drop mod files from external sources (like a file explorer or browser) into Penumbras mod selector to import them.")
|
.RegisterEntry(
|
||||||
|
"Added the ability to drag and drop mod files from external sources (like a file explorer or browser) into Penumbras mod selector to import them.")
|
||||||
.RegisterEntry("You can also drag and drop texture files into the textures tab of the Advanced Editing Window.", 1)
|
.RegisterEntry("You can also drag and drop texture files into the textures tab of the Advanced Editing Window.", 1)
|
||||||
.RegisterEntry("Added a priority display to the mod selector using the currently selected collections priorities. This can be hidden in settings.")
|
.RegisterEntry(
|
||||||
|
"Added a priority display to the mod selector using the currently selected collections priorities. This can be hidden in settings.")
|
||||||
.RegisterEntry("Added IPC for texture conversion, improved texture handling backend and threading.")
|
.RegisterEntry("Added IPC for texture conversion, improved texture handling backend and threading.")
|
||||||
.RegisterEntry("Added Dalamud Substitution so that other plugins can more easily use replaced icons from Penumbras Interface collection when using Dalamuds new Texture Provider.")
|
.RegisterEntry(
|
||||||
|
"Added Dalamud Substitution so that other plugins can more easily use replaced icons from Penumbras Interface collection when using Dalamuds new Texture Provider.")
|
||||||
.RegisterEntry("Added a filter to texture selection combos in the textures tab of the Advanced Editing Window.")
|
.RegisterEntry("Added a filter to texture selection combos in the textures tab of the Advanced Editing Window.")
|
||||||
.RegisterEntry("Changed behaviour when failing to load group JSON files for mods - the pre-existing but failing files are now backed up before being deleted or overwritten.")
|
.RegisterEntry(
|
||||||
|
"Changed behaviour when failing to load group JSON files for mods - the pre-existing but failing files are now backed up before being deleted or overwritten.")
|
||||||
.RegisterEntry("Further backend changes, mostly relating to the Glamourer rework.")
|
.RegisterEntry("Further backend changes, mostly relating to the Glamourer rework.")
|
||||||
.RegisterEntry("Fixed an issue with modded decals not loading correctly when used with the Glamourer rework.")
|
.RegisterEntry("Fixed an issue with modded decals not loading correctly when used with the Glamourer rework.")
|
||||||
.RegisterEntry("Fixed missing scaling with UI Scale for some combos.")
|
.RegisterEntry("Fixed missing scaling with UI Scale for some combos.")
|
||||||
|
|
@ -66,21 +70,31 @@ public class PenumbraChangelog
|
||||||
|
|
||||||
private static void Add7_2_0(Changelog log)
|
private static void Add7_2_0(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.2.0")
|
=> log.NextVersion("Version 0.7.2.0")
|
||||||
.RegisterEntry("Added Changed Item Categories and icons that can filter for specific types of Changed Items, in the Changed Items Tab as well as in the Changed Items panel for specific mods..")
|
.RegisterEntry(
|
||||||
.RegisterEntry("Icons at the top can be clicked to filter, as well as right-clicked to open a context menu with the option to inverse-filter for them", 1)
|
"Added Changed Item Categories and icons that can filter for specific types of Changed Items, in the Changed Items Tab as well as in the Changed Items panel for specific mods..")
|
||||||
|
.RegisterEntry(
|
||||||
|
"Icons at the top can be clicked to filter, as well as right-clicked to open a context menu with the option to inverse-filter for them",
|
||||||
|
1)
|
||||||
.RegisterEntry("There is also an ALL button that can be toggled.", 1)
|
.RegisterEntry("There is also an ALL button that can be toggled.", 1)
|
||||||
.RegisterEntry("Modded files in the Font category now resolve from the Interface assignment instead of the base assignment, despite not technically being in the UI category.")
|
.RegisterEntry(
|
||||||
.RegisterEntry("Timeline files will no longer be associated with specific characters in cutscenes, since there is no way to correctly do this, and it could cause crashes if IVCS-requiring animations were used on characters without IVCS.")
|
"Modded files in the Font category now resolve from the Interface assignment instead of the base assignment, despite not technically being in the UI category.")
|
||||||
|
.RegisterEntry(
|
||||||
|
"Timeline files will no longer be associated with specific characters in cutscenes, since there is no way to correctly do this, and it could cause crashes if IVCS-requiring animations were used on characters without IVCS.")
|
||||||
.RegisterEntry("File deletion in the Advanced Editing Window now also checks for your configured deletion key combo.")
|
.RegisterEntry("File deletion in the Advanced Editing Window now also checks for your configured deletion key combo.")
|
||||||
.RegisterEntry("The Texture tab in the Advanced Editing Window now has some quick convert buttons to just convert the selected texture to a different format in-place.")
|
.RegisterEntry(
|
||||||
.RegisterEntry("These buttons only appear if only one texture is selected on the left side, it is not otherwise manipulated, and the texture is a .tex file.", 1)
|
"The Texture tab in the Advanced Editing Window now has some quick convert buttons to just convert the selected texture to a different format in-place.")
|
||||||
|
.RegisterEntry(
|
||||||
|
"These buttons only appear if only one texture is selected on the left side, it is not otherwise manipulated, and the texture is a .tex file.",
|
||||||
|
1)
|
||||||
.RegisterEntry("The text part of the mod filter in the mod selector now also resets when right-clicking the drop-down arrow.")
|
.RegisterEntry("The text part of the mod filter in the mod selector now also resets when right-clicking the drop-down arrow.")
|
||||||
.RegisterEntry("The Dissolve Folder option in the mod selector context menu has been moved to the bottom.")
|
.RegisterEntry("The Dissolve Folder option in the mod selector context menu has been moved to the bottom.")
|
||||||
.RegisterEntry("Somewhat improved IMC handling to prevent some issues.")
|
.RegisterEntry("Somewhat improved IMC handling to prevent some issues.")
|
||||||
.RegisterEntry("Improved the handling of mod renames on mods with default-search names to correctly rename their search-name in (hopefully) all cases too.")
|
.RegisterEntry(
|
||||||
|
"Improved the handling of mod renames on mods with default-search names to correctly rename their search-name in (hopefully) all cases too.")
|
||||||
.RegisterEntry("A lot of backend improvements and changes related to the pending Glamourer rework.")
|
.RegisterEntry("A lot of backend improvements and changes related to the pending Glamourer rework.")
|
||||||
.RegisterEntry("Fixed an issue where the displayed active collection count in the support info was wrong.")
|
.RegisterEntry("Fixed an issue where the displayed active collection count in the support info was wrong.")
|
||||||
.RegisterEntry("Fixed an issue with created directories dealing badly with non-standard whitespace characters like half-width or non-breaking spaces.")
|
.RegisterEntry(
|
||||||
|
"Fixed an issue with created directories dealing badly with non-standard whitespace characters like half-width or non-breaking spaces.")
|
||||||
.RegisterEntry("Fixed an issue with unknown animation and vfx edits not being recognized correctly.")
|
.RegisterEntry("Fixed an issue with unknown animation and vfx edits not being recognized correctly.")
|
||||||
.RegisterEntry("Fixed an issue where changing option descriptions to be empty was not working correctly.")
|
.RegisterEntry("Fixed an issue where changing option descriptions to be empty was not working correctly.")
|
||||||
.RegisterEntry("Fixed an issue with texture names in the resource tree of the On-Screen views.")
|
.RegisterEntry("Fixed an issue with texture names in the resource tree of the On-Screen views.")
|
||||||
|
|
@ -94,21 +108,29 @@ public class PenumbraChangelog
|
||||||
|
|
||||||
private static void Add7_1_2(Changelog log)
|
private static void Add7_1_2(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.1.2")
|
=> log.NextVersion("Version 0.7.1.2")
|
||||||
.RegisterEntry("Changed threaded handling of collection caches. Maybe this fixes the startup problems some people are experiencing.")
|
.RegisterEntry(
|
||||||
.RegisterEntry("This is just testing and may not be the solution, or may even make things worse. Sorry if I have to put out multiple small patches again to get this right.", 1)
|
"Changed threaded handling of collection caches. Maybe this fixes the startup problems some people are experiencing.")
|
||||||
|
.RegisterEntry(
|
||||||
|
"This is just testing and may not be the solution, or may even make things worse. Sorry if I have to put out multiple small patches again to get this right.",
|
||||||
|
1)
|
||||||
.RegisterEntry("Fixed Penumbra failing to load if the main configuration file is corrupted.")
|
.RegisterEntry("Fixed Penumbra failing to load if the main configuration file is corrupted.")
|
||||||
.RegisterEntry("Some miscellaneous small bug fixes.")
|
.RegisterEntry("Some miscellaneous small bug fixes.")
|
||||||
.RegisterEntry("Slight changes in behaviour for deduplicator/normalizer, mostly backend.")
|
.RegisterEntry("Slight changes in behaviour for deduplicator/normalizer, mostly backend.")
|
||||||
.RegisterEntry("A typo in the 0.7.1.0 Changelog has been fixed.")
|
.RegisterEntry("A typo in the 0.7.1.0 Changelog has been fixed.")
|
||||||
.RegisterEntry("Fixed left rings not being valid for IMC entries after validation. (7.1.1)")
|
.RegisterEntry("Fixed left rings not being valid for IMC entries after validation. (7.1.1)")
|
||||||
.RegisterEntry("Relaxed the scaling restrictions for RSP scaling values to go from 0.01 to 512.0 instead of the prior upper limit of 8.0, in interface as well as validation, to better support the fetish community. (7.1.1)");
|
.RegisterEntry(
|
||||||
|
"Relaxed the scaling restrictions for RSP scaling values to go from 0.01 to 512.0 instead of the prior upper limit of 8.0, in interface as well as validation, to better support the fetish community. (7.1.1)");
|
||||||
|
|
||||||
private static void Add7_1_0(Changelog log)
|
private static void Add7_1_0(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.1.0")
|
=> log.NextVersion("Version 0.7.1.0")
|
||||||
.RegisterEntry("Updated for patch 6.4 - there may be some oversights on edge cases, but I could not find any issues myself.")
|
.RegisterEntry("Updated for patch 6.4 - there may be some oversights on edge cases, but I could not find any issues myself.")
|
||||||
.RegisterHighlight("This update changed some Dragoon skills that were moving the player character before to not do that anymore. If you have any mods that applied to those skills, please make sure that they do not contain any redirections for .tmb files. If skills that should no longer move your character still do that for some reason, this is detectable by the server.", 1)
|
.RegisterHighlight(
|
||||||
.RegisterEntry("Added a Mod Merging tab in the Advanced Editing Window. This can help you merge multiple mods to one, or split off specific options from an existing mod into a new mod.")
|
"This update changed some Dragoon skills that were moving the player character before to not do that anymore. If you have any mods that applied to those skills, please make sure that they do not contain any redirections for .tmb files. If skills that should no longer move your character still do that for some reason, this is detectable by the server.",
|
||||||
.RegisterEntry("Added advanced options to configure the minimum allowed window size for the main window (to reduce it). This is not quite supported and may look bad, so only use it if you really need smaller windows.")
|
1)
|
||||||
|
.RegisterEntry(
|
||||||
|
"Added a Mod Merging tab in the Advanced Editing Window. This can help you merge multiple mods to one, or split off specific options from an existing mod into a new mod.")
|
||||||
|
.RegisterEntry(
|
||||||
|
"Added advanced options to configure the minimum allowed window size for the main window (to reduce it). This is not quite supported and may look bad, so only use it if you really need smaller windows.")
|
||||||
.RegisterEntry("The last tab selected in the main window is now saved and re-used when relaunching Penumbra.")
|
.RegisterEntry("The last tab selected in the main window is now saved and re-used when relaunching Penumbra.")
|
||||||
.RegisterEntry("Added a hook to correctly associate some sounds that are played while weapons are drawn.")
|
.RegisterEntry("Added a hook to correctly associate some sounds that are played while weapons are drawn.")
|
||||||
.RegisterEntry("Added a hook to correctly associate sounds that are played while dismounting.")
|
.RegisterEntry("Added a hook to correctly associate sounds that are played while dismounting.")
|
||||||
|
|
@ -125,7 +147,8 @@ public class PenumbraChangelog
|
||||||
.RegisterEntry("Fixed an issue with the file selectors not always opening at the expected locations. (0.7.0.7)")
|
.RegisterEntry("Fixed an issue with the file selectors not always opening at the expected locations. (0.7.0.7)")
|
||||||
.RegisterEntry("Fixed some cache handling issues. (0.7.0.5 - 0.7.0.10)")
|
.RegisterEntry("Fixed some cache handling issues. (0.7.0.5 - 0.7.0.10)")
|
||||||
.RegisterEntry("Fixed an issue with multiple collection context menus appearing for some identifiers (0.7.0.5)")
|
.RegisterEntry("Fixed an issue with multiple collection context menus appearing for some identifiers (0.7.0.5)")
|
||||||
.RegisterEntry("Fixed an issue where the Update Bibo button did only work if the Advanced Editing window was opened before. (0.7.0.5)");
|
.RegisterEntry(
|
||||||
|
"Fixed an issue where the Update Bibo button did only work if the Advanced Editing window was opened before. (0.7.0.5)");
|
||||||
|
|
||||||
private static void Add7_0_4(Changelog log)
|
private static void Add7_0_4(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.0.4")
|
=> log.NextVersion("Version 0.7.0.4")
|
||||||
|
|
@ -145,26 +168,36 @@ public class PenumbraChangelog
|
||||||
.RegisterEntry("Fixed a bug that showed the Your Character collection as redundant even if it was not.")
|
.RegisterEntry("Fixed a bug that showed the Your Character collection as redundant even if it was not.")
|
||||||
.RegisterEntry("Fixed a bug that caused some required collection caches to not be built on startup and thus mods not to apply.")
|
.RegisterEntry("Fixed a bug that caused some required collection caches to not be built on startup and thus mods not to apply.")
|
||||||
.RegisterEntry("Fixed a bug that showed the current collection as unused even if it was used.");
|
.RegisterEntry("Fixed a bug that showed the current collection as unused even if it was used.");
|
||||||
|
|
||||||
private static void Add7_0_0(Changelog log)
|
private static void Add7_0_0(Changelog log)
|
||||||
=> log.NextVersion("Version 0.7.0.0")
|
=> log.NextVersion("Version 0.7.0.0")
|
||||||
.RegisterHighlight("The entire backend was reworked (this is still in progress). While this does not come with a lot of functionality changes, basically every file and functionality was touched.")
|
.RegisterHighlight(
|
||||||
.RegisterEntry("This may have (re-)introduced some bugs that have not yet been noticed despite a long testing period - there are not many users of the testing branch.", 1)
|
"The entire backend was reworked (this is still in progress). While this does not come with a lot of functionality changes, basically every file and functionality was touched.")
|
||||||
|
.RegisterEntry(
|
||||||
|
"This may have (re-)introduced some bugs that have not yet been noticed despite a long testing period - there are not many users of the testing branch.",
|
||||||
|
1)
|
||||||
.RegisterEntry("If you encounter any - but especially breaking or lossy - bugs, please report them immediately.", 1)
|
.RegisterEntry("If you encounter any - but especially breaking or lossy - bugs, please report them immediately.", 1)
|
||||||
.RegisterEntry("This also fixed or improved numerous bugs and issues that will not be listed here.", 1)
|
.RegisterEntry("This also fixed or improved numerous bugs and issues that will not be listed here.", 1)
|
||||||
.RegisterEntry("GitHub currently reports 321 changed files with 34541 additions and 28464 deletions.", 1)
|
.RegisterEntry("GitHub currently reports 321 changed files with 34541 additions and 28464 deletions.", 1)
|
||||||
.RegisterEntry("Added Notifications on many failures that previously only wrote to log.")
|
.RegisterEntry("Added Notifications on many failures that previously only wrote to log.")
|
||||||
.RegisterEntry("Reworked the Collections Tab to hopefully be much more intuitive. It should be self-explanatory now.")
|
.RegisterEntry("Reworked the Collections Tab to hopefully be much more intuitive. It should be self-explanatory now.")
|
||||||
.RegisterEntry("The tutorial was adapted to the new window, if you are unsure, maybe try restarting it.", 1)
|
.RegisterEntry("The tutorial was adapted to the new window, if you are unsure, maybe try restarting it.", 1)
|
||||||
.RegisterEntry("You can now toggle an incognito mode in the collection window so it shows shortened names of collections and players.", 1)
|
.RegisterEntry(
|
||||||
.RegisterEntry("You can get an overview about the current usage of a selected collection and its active and unused mod settings in the Collection Details panel.", 1)
|
"You can now toggle an incognito mode in the collection window so it shows shortened names of collections and players.", 1)
|
||||||
|
.RegisterEntry(
|
||||||
|
"You can get an overview about the current usage of a selected collection and its active and unused mod settings in the Collection Details panel.",
|
||||||
|
1)
|
||||||
.RegisterEntry("The currently selected collection is now highlighted in green (default, configurable) in multiple places.", 1)
|
.RegisterEntry("The currently selected collection is now highlighted in green (default, configurable) in multiple places.", 1)
|
||||||
.RegisterEntry("Mods now have a 'Collections' panel in the Mod Panel containing an overview about usage of the mod in all collections.")
|
.RegisterEntry(
|
||||||
|
"Mods now have a 'Collections' panel in the Mod Panel containing an overview about usage of the mod in all collections.")
|
||||||
.RegisterEntry("The 'Changed Items' and 'Effective Changes' tab now contain a collection selector.")
|
.RegisterEntry("The 'Changed Items' and 'Effective Changes' tab now contain a collection selector.")
|
||||||
.RegisterEntry("Added the On-Screen tab to find what files a specific character is actually using (by Ny).")
|
.RegisterEntry("Added the On-Screen tab to find what files a specific character is actually using (by Ny).")
|
||||||
.RegisterEntry("Added 3 Quick Move folders in the mod selector that can be setup in context menus for easier cleanup.")
|
.RegisterEntry("Added 3 Quick Move folders in the mod selector that can be setup in context menus for easier cleanup.")
|
||||||
.RegisterEntry("Added handling for certain animation files for mounts and fashion accessories to correctly associate them to players.")
|
.RegisterEntry(
|
||||||
|
"Added handling for certain animation files for mounts and fashion accessories to correctly associate them to players.")
|
||||||
.RegisterEntry("The file selectors in the Advanced Mod Editing Window now use filterable combos.")
|
.RegisterEntry("The file selectors in the Advanced Mod Editing Window now use filterable combos.")
|
||||||
.RegisterEntry("The Advanced Mod Editing Window now shows the number of meta edits and file swaps in unselected options and highlights the option selector.")
|
.RegisterEntry(
|
||||||
|
"The Advanced Mod Editing Window now shows the number of meta edits and file swaps in unselected options and highlights the option selector.")
|
||||||
.RegisterEntry("Added API/IPC to start unpacking and installing mods from external tools (by Sebastina).")
|
.RegisterEntry("Added API/IPC to start unpacking and installing mods from external tools (by Sebastina).")
|
||||||
.RegisterEntry("Hidden files and folders are now ignored for unused files in Advanced Mod Editing (by myr)")
|
.RegisterEntry("Hidden files and folders are now ignored for unused files in Advanced Mod Editing (by myr)")
|
||||||
.RegisterEntry("Paths in mods are now automatically trimmed of whitespace on loading.")
|
.RegisterEntry("Paths in mods are now automatically trimmed of whitespace on loading.")
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,16 @@ public static class Combos
|
||||||
=> ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out gender, RaceEnumExtensions.ToName, 1);
|
=> ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out gender, RaceEnumExtensions.ToName, 1);
|
||||||
|
|
||||||
public static bool EqdpEquipSlot(string label, EquipSlot current, out EquipSlot slot)
|
public static bool EqdpEquipSlot(string label, EquipSlot current, out EquipSlot slot)
|
||||||
=> ImGuiUtil.GenericEnumCombo( label, 100 * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EqdpSlots, EquipSlotExtensions.ToName );
|
=> ImGuiUtil.GenericEnumCombo(label, 100 * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EqdpSlots,
|
||||||
|
EquipSlotExtensions.ToName);
|
||||||
|
|
||||||
public static bool EqpEquipSlot(string label, float width, EquipSlot current, out EquipSlot slot)
|
public static bool EqpEquipSlot(string label, float width, EquipSlot current, out EquipSlot slot)
|
||||||
=> ImGuiUtil.GenericEnumCombo( label, width * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EquipmentSlots, EquipSlotExtensions.ToName );
|
=> ImGuiUtil.GenericEnumCombo(label, width * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EquipmentSlots,
|
||||||
|
EquipSlotExtensions.ToName);
|
||||||
|
|
||||||
public static bool AccessorySlot(string label, EquipSlot current, out EquipSlot slot)
|
public static bool AccessorySlot(string label, EquipSlot current, out EquipSlot slot)
|
||||||
=> ImGuiUtil.GenericEnumCombo( label, 100 * UiHelpers.Scale, current, out slot, EquipSlotExtensions.AccessorySlots, EquipSlotExtensions.ToName );
|
=> ImGuiUtil.GenericEnumCombo(label, 100 * UiHelpers.Scale, current, out slot, EquipSlotExtensions.AccessorySlots,
|
||||||
|
EquipSlotExtensions.ToName);
|
||||||
|
|
||||||
public static bool SubRace(string label, SubRace current, out SubRace subRace)
|
public static bool SubRace(string label, SubRace current, out SubRace subRace)
|
||||||
=> ImGuiUtil.GenericEnumCombo(label, 150 * UiHelpers.Scale, current, out subRace, RaceEnumExtensions.ToName, 1);
|
=> ImGuiUtil.GenericEnumCombo(label, 150 * UiHelpers.Scale, current, out subRace, RaceEnumExtensions.ToName, 1);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ public class InheritanceUi
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
using var id = ImRaii.PushId("##Inheritance");
|
using var id = ImRaii.PushId("##Inheritance");
|
||||||
ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0), (Name(_active.Current), ColorId.SelectedCollection.Value() | 0xFF000000), (" inherits from:", 0));
|
ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0),
|
||||||
|
(Name(_active.Current), ColorId.SelectedCollection.Value() | 0xFF000000), (" inherits from:", 0));
|
||||||
ImGui.Dummy(Vector2.One);
|
ImGui.Dummy(Vector2.One);
|
||||||
|
|
||||||
DrawCurrentCollectionInheritance();
|
DrawCurrentCollectionInheritance();
|
||||||
|
|
@ -122,7 +123,8 @@ public class InheritanceUi
|
||||||
_seenInheritedCollections.Contains(inheritance));
|
_seenInheritedCollections.Contains(inheritance));
|
||||||
_seenInheritedCollections.Add(inheritance);
|
_seenInheritedCollections.Add(inheritance);
|
||||||
|
|
||||||
ImRaii.TreeNode($"{Name(inheritance)}###{inheritance.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
ImRaii.TreeNode($"{Name(inheritance)}###{inheritance.Name}",
|
||||||
|
ImGuiTreeNodeFlags.NoTreePushOnOpen | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet);
|
||||||
var (minRect, maxRect) = (ImGui.GetItemRectMin(), ImGui.GetItemRectMax());
|
var (minRect, maxRect) = (ImGui.GetItemRectMin(), ImGui.GetItemRectMax());
|
||||||
DrawInheritanceTreeClicks(inheritance, false);
|
DrawInheritanceTreeClicks(inheritance, false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Reflection;
|
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.ImGuiFileDialog;
|
using Dalamud.Interface.ImGuiFileDialog;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using Penumbra.Collections.Manager;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Subclasses;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
using ChatService = Penumbra.Services.ChatService;
|
using ChatService = Penumbra.Services.ChatService;
|
||||||
|
|
@ -376,8 +377,10 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
ImGui.BulletText(
|
ImGui.BulletText(
|
||||||
"You can drag and drop mods and subfolders into existing folders. Dropping them onto mods is the same as dropping them onto the parent of the mod.");
|
"You can drag and drop mods and subfolders into existing folders. Dropping them onto mods is the same as dropping them onto the parent of the mod.");
|
||||||
indent.Push();
|
indent.Push();
|
||||||
ImGui.BulletText("You can select multiple mods and folders by holding Control while clicking them, and then drag all of them at once." );
|
ImGui.BulletText(
|
||||||
ImGui.BulletText("Selected mods inside an also selected folder will be ignored when dragging and move inside their folder instead of directly into the target.");
|
"You can select multiple mods and folders by holding Control while clicking them, and then drag all of them at once.");
|
||||||
|
ImGui.BulletText(
|
||||||
|
"Selected mods inside an also selected folder will be ignored when dragging and move inside their folder instead of directly into the target.");
|
||||||
indent.Pop(1);
|
indent.Pop(1);
|
||||||
ImGui.BulletText("Right-clicking a folder opens a context menu.");
|
ImGui.BulletText("Right-clicking a folder opens a context menu.");
|
||||||
ImGui.BulletText("Right-clicking empty space allows you to expand or collapse all folders at once.");
|
ImGui.BulletText("Right-clicking empty space allows you to expand or collapse all folders at once.");
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.UI.AdvancedWindow;
|
using Penumbra.UI.AdvancedWindow;
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab;
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,7 @@ using ImGuiNET;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.Mods;
|
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.UI.Classes;
|
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab;
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,8 @@ using OtterGui;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
using Penumbra.Mods;
|
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface;
|
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Mods.Subclasses;
|
using Penumbra.Mods.Subclasses;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue