just misc
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -11,24 +12,35 @@ public unsafe class BlockedCharacterHandler
|
|||||||
private readonly Dictionary<CharaData, bool> _blockedCharacterCache = new();
|
private readonly Dictionary<CharaData, bool> _blockedCharacterCache = new();
|
||||||
|
|
||||||
private readonly ILogger<BlockedCharacterHandler> _logger;
|
private readonly ILogger<BlockedCharacterHandler> _logger;
|
||||||
|
private readonly IObjectTable _objectTable;
|
||||||
|
|
||||||
public BlockedCharacterHandler(ILogger<BlockedCharacterHandler> logger, IGameInteropProvider gameInteropProvider)
|
public BlockedCharacterHandler(ILogger<BlockedCharacterHandler> logger, IGameInteropProvider gameInteropProvider, IObjectTable objectTable)
|
||||||
{
|
{
|
||||||
gameInteropProvider.InitializeFromAttributes(this);
|
gameInteropProvider.InitializeFromAttributes(this);
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_objectTable = objectTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CharaData GetIdsFromPlayerPointer(nint ptr)
|
private CharaData? TryGetIdsFromPlayerPointer(nint ptr, ushort objectIndex)
|
||||||
{
|
{
|
||||||
if (ptr == nint.Zero) return new(0, 0);
|
if (ptr == nint.Zero || objectIndex >= 200)
|
||||||
var castChar = ((BattleChara*)ptr);
|
return null;
|
||||||
|
|
||||||
|
var obj = _objectTable[objectIndex];
|
||||||
|
if (obj is not IPlayerCharacter player || player.Address != ptr)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var castChar = (BattleChara*)player.Address;
|
||||||
return new(castChar->Character.AccountId, castChar->Character.ContentId);
|
return new(castChar->Character.AccountId, castChar->Character.ContentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCharacterBlocked(nint ptr, out bool firstTime)
|
public bool IsCharacterBlocked(nint ptr, ushort objectIndex, out bool firstTime)
|
||||||
{
|
{
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
var combined = GetIdsFromPlayerPointer(ptr);
|
var combined = TryGetIdsFromPlayerPointer(ptr, objectIndex);
|
||||||
|
if (combined == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (_blockedCharacterCache.TryGetValue(combined, out var isBlocked))
|
if (_blockedCharacterCache.TryGetValue(combined, out var isBlocked))
|
||||||
return isBlocked;
|
return isBlocked;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class PlayerPerformanceConfig : ILightlessConfiguration
|
|||||||
public bool KeepOriginalTextureFiles { get; set; } = false;
|
public bool KeepOriginalTextureFiles { get; set; } = false;
|
||||||
public bool SkipTextureDownscaleForPreferredPairs { get; set; } = true;
|
public bool SkipTextureDownscaleForPreferredPairs { get; set; } = true;
|
||||||
public bool EnableModelDecimation { get; set; } = false;
|
public bool EnableModelDecimation { get; set; } = false;
|
||||||
public int ModelDecimationTriangleThreshold { get; set; } = 50_000;
|
public int ModelDecimationTriangleThreshold { get; set; } = 20_000;
|
||||||
public double ModelDecimationTargetRatio { get; set; } = 0.8;
|
public double ModelDecimationTargetRatio { get; set; } = 0.8;
|
||||||
public bool KeepOriginalModelFiles { get; set; } = true;
|
public bool KeepOriginalModelFiles { get; set; } = true;
|
||||||
public bool SkipModelDecimationForPreferredPairs { get; set; } = true;
|
public bool SkipModelDecimationForPreferredPairs { get; set; } = true;
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
services.AddSingleton<HubFactory>();
|
services.AddSingleton<HubFactory>();
|
||||||
services.AddSingleton<FileUploadManager>();
|
services.AddSingleton<FileUploadManager>();
|
||||||
services.AddSingleton<FileTransferOrchestrator>();
|
services.AddSingleton<FileTransferOrchestrator>();
|
||||||
|
services.AddSingleton<FileDownloadDeduplicator>();
|
||||||
services.AddSingleton<LightlessPlugin>();
|
services.AddSingleton<LightlessPlugin>();
|
||||||
services.AddSingleton<LightlessProfileManager>();
|
services.AddSingleton<LightlessProfileManager>();
|
||||||
services.AddSingleton<TextureCompressionService>();
|
services.AddSingleton<TextureCompressionService>();
|
||||||
@@ -180,7 +181,8 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
|
|
||||||
services.AddSingleton(sp => new BlockedCharacterHandler(
|
services.AddSingleton(sp => new BlockedCharacterHandler(
|
||||||
sp.GetRequiredService<ILogger<BlockedCharacterHandler>>(),
|
sp.GetRequiredService<ILogger<BlockedCharacterHandler>>(),
|
||||||
gameInteropProvider));
|
gameInteropProvider,
|
||||||
|
objectTable));
|
||||||
|
|
||||||
services.AddSingleton(sp => new IpcProvider(
|
services.AddSingleton(sp => new IpcProvider(
|
||||||
sp.GetRequiredService<ILogger<IpcProvider>>(),
|
sp.GetRequiredService<ILogger<IpcProvider>>(),
|
||||||
|
|||||||
@@ -1010,7 +1010,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
|||||||
if (actor.ObjectIndex >= 200)
|
if (actor.ObjectIndex >= 200)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_blockedCharacterHandler.IsCharacterBlocked(playerAddress, out bool firstTime) && firstTime)
|
if (_blockedCharacterHandler.IsCharacterBlocked(playerAddress, actor.ObjectIndex, out bool firstTime) && firstTime)
|
||||||
{
|
{
|
||||||
_logger.LogTrace("Skipping character {addr}, blocked/muted", playerAddress.ToString("X"));
|
_logger.LogTrace("Skipping character {addr}, blocked/muted", playerAddress.ToString("X"));
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Lumina.Data.Parsing;
|
using Lumina.Data.Parsing;
|
||||||
using Lumina.Extensions;
|
using Lumina.Extensions;
|
||||||
using MeshDecimator;
|
using MeshDecimator;
|
||||||
|
using MeshDecimator.Algorithms;
|
||||||
using MeshDecimator.Math;
|
using MeshDecimator.Math;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Penumbra.GameData.Files.ModelStructs;
|
using Penumbra.GameData.Files.ModelStructs;
|
||||||
@@ -94,6 +95,8 @@ internal static class MdlDecimator
|
|||||||
var newVertexBuffer = new List<byte>(mdl.VertexBufferSize[lodIndex] > 0 ? (int)mdl.VertexBufferSize[lodIndex] : 0);
|
var newVertexBuffer = new List<byte>(mdl.VertexBufferSize[lodIndex] > 0 ? (int)mdl.VertexBufferSize[lodIndex] : 0);
|
||||||
var newIndexBuffer = new List<ushort>(mdl.IndexBufferSize[lodIndex] > 0 ? (int)(mdl.IndexBufferSize[lodIndex] / sizeof(ushort)) : 0);
|
var newIndexBuffer = new List<ushort>(mdl.IndexBufferSize[lodIndex] > 0 ? (int)(mdl.IndexBufferSize[lodIndex] / sizeof(ushort)) : 0);
|
||||||
var subMeshCursor = 0;
|
var subMeshCursor = 0;
|
||||||
|
DecimationAlgorithm? decimationAlgorithm = null;
|
||||||
|
int? decimationUvChannelCount = null;
|
||||||
|
|
||||||
for (var meshIndex = 0; meshIndex < meshes.Length; meshIndex++)
|
for (var meshIndex = 0; meshIndex < meshes.Length; meshIndex++)
|
||||||
{
|
{
|
||||||
@@ -119,6 +122,8 @@ internal static class MdlDecimator
|
|||||||
out vertexStreams,
|
out vertexStreams,
|
||||||
out indices,
|
out indices,
|
||||||
out decimated,
|
out decimated,
|
||||||
|
ref decimationAlgorithm,
|
||||||
|
ref decimationUvChannelCount,
|
||||||
logger))
|
logger))
|
||||||
{
|
{
|
||||||
updatedSubMeshes = OffsetSubMeshes(updatedSubMeshes, meshIndexBase);
|
updatedSubMeshes = OffsetSubMeshes(updatedSubMeshes, meshIndexBase);
|
||||||
@@ -309,6 +314,8 @@ internal static class MdlDecimator
|
|||||||
out byte[][] vertexStreams,
|
out byte[][] vertexStreams,
|
||||||
out int[] indices,
|
out int[] indices,
|
||||||
out bool decimated,
|
out bool decimated,
|
||||||
|
ref DecimationAlgorithm? decimationAlgorithm,
|
||||||
|
ref int? decimationUvChannelCount,
|
||||||
MsLogger logger)
|
MsLogger logger)
|
||||||
{
|
{
|
||||||
updatedMesh = mesh;
|
updatedMesh = mesh;
|
||||||
@@ -352,8 +359,7 @@ internal static class MdlDecimator
|
|||||||
}
|
}
|
||||||
|
|
||||||
var meshDecimatorMesh = BuildMesh(decoded, subMeshIndices);
|
var meshDecimatorMesh = BuildMesh(decoded, subMeshIndices);
|
||||||
var algorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default);
|
var algorithm = GetOrCreateAlgorithm(format, ref decimationAlgorithm, ref decimationUvChannelCount, logger);
|
||||||
algorithm.Logger = logger;
|
|
||||||
algorithm.Initialize(meshDecimatorMesh);
|
algorithm.Initialize(meshDecimatorMesh);
|
||||||
algorithm.DecimateMesh(targetTriangles);
|
algorithm.DecimateMesh(targetTriangles);
|
||||||
var decimatedMesh = algorithm.ToMesh();
|
var decimatedMesh = algorithm.ToMesh();
|
||||||
@@ -374,6 +380,23 @@ internal static class MdlDecimator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DecimationAlgorithm GetOrCreateAlgorithm(
|
||||||
|
VertexFormat format,
|
||||||
|
ref DecimationAlgorithm? decimationAlgorithm,
|
||||||
|
ref int? decimationUvChannelCount,
|
||||||
|
MsLogger logger)
|
||||||
|
{
|
||||||
|
var uvChannelCount = format.UvChannelCount;
|
||||||
|
if (decimationAlgorithm == null || decimationUvChannelCount != uvChannelCount)
|
||||||
|
{
|
||||||
|
decimationAlgorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default);
|
||||||
|
decimationAlgorithm.Logger = logger;
|
||||||
|
decimationUvChannelCount = uvChannelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return decimationAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
private static Mesh BuildMesh(DecodedMeshData decoded, int[][] subMeshIndices)
|
private static Mesh BuildMesh(DecodedMeshData decoded, int[][] subMeshIndices)
|
||||||
{
|
{
|
||||||
var mesh = new Mesh(decoded.Positions, subMeshIndices);
|
var mesh = new Mesh(decoded.Positions, subMeshIndices);
|
||||||
|
|||||||
@@ -3635,8 +3635,31 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
|
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
|
||||||
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
|
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
|
||||||
|
|
||||||
|
|
||||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||||
new SeStringUtils.RichTextEntry("this shit is placeholder still owo"));
|
new SeStringUtils.RichTextEntry("This feature is encouraged to help "),
|
||||||
|
new SeStringUtils.RichTextEntry("lower-end systems with limited VRAM", UIColors.Get("LightlessYellow"), true),
|
||||||
|
new SeStringUtils.RichTextEntry(" and for use in "),
|
||||||
|
new SeStringUtils.RichTextEntry("performance-critical scenarios", UIColors.Get("LightlessYellow"), true),
|
||||||
|
new SeStringUtils.RichTextEntry("."));
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||||
|
new SeStringUtils.RichTextEntry("Runtime decimation "),
|
||||||
|
new SeStringUtils.RichTextEntry("MAY", UIColors.Get("DimRed"), true),
|
||||||
|
new SeStringUtils.RichTextEntry(" cause higher load on the system when processing downloads."));
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("!!! ", UIColors.Get("DimRed"),
|
||||||
|
new SeStringUtils.RichTextEntry("When enabled, we cannot provide support for appearance issues caused by this setting!", UIColors.Get("DimRed"), true));
|
||||||
|
|
||||||
|
ImGui.Dummy(new Vector2(15));
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessGreen"),
|
||||||
|
new SeStringUtils.RichTextEntry("If a mesh exceeds the "),
|
||||||
|
new SeStringUtils.RichTextEntry("triangle threshold", UIColors.Get("LightlessGreen"), true),
|
||||||
|
new SeStringUtils.RichTextEntry(", it will be decimated automatically to the set "),
|
||||||
|
new SeStringUtils.RichTextEntry("target triangle ratio", UIColors.Get("LightlessGreen"), true),
|
||||||
|
new SeStringUtils.RichTextEntry(". This will reduce quality of the mesh or may break it's intended structure."));
|
||||||
|
|
||||||
|
|
||||||
var performanceConfig = _playerPerformanceConfigService.Current;
|
var performanceConfig = _playerPerformanceConfigService.Current;
|
||||||
var enableDecimation = performanceConfig.EnableModelDecimation;
|
var enableDecimation = performanceConfig.EnableModelDecimation;
|
||||||
@@ -3667,9 +3690,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
|
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
|
||||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||||
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 10_000, 100_000))
|
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 8_000, 100_000))
|
||||||
{
|
{
|
||||||
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 10_000, 100_000);
|
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 8_000, 100_000);
|
||||||
_playerPerformanceConfigService.Save();
|
_playerPerformanceConfigService.Save();
|
||||||
}
|
}
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
@@ -3677,7 +3700,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_uiShared.DrawHelpText($"Models below this triangle count are left untouched.{UiSharedService.TooltipSeparator}Default: 50,000");
|
_uiShared.DrawHelpText($"Models below this triangle count are left untouched.{UiSharedService.TooltipSeparator}Default: 50,000");
|
||||||
|
|
||||||
var targetPercent = (float)(performanceConfig.ModelDecimationTargetRatio * 100.0);
|
var targetPercent = (float)(performanceConfig.ModelDecimationTargetRatio * 100.0);
|
||||||
var clampedPercent = Math.Clamp(targetPercent, 70f, 99f);
|
var clampedPercent = Math.Clamp(targetPercent, 60f, 99f);
|
||||||
if (Math.Abs(clampedPercent - targetPercent) > float.Epsilon)
|
if (Math.Abs(clampedPercent - targetPercent) > float.Epsilon)
|
||||||
{
|
{
|
||||||
performanceConfig.ModelDecimationTargetRatio = clampedPercent / 100.0;
|
performanceConfig.ModelDecimationTargetRatio = clampedPercent / 100.0;
|
||||||
@@ -3685,17 +3708,30 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
targetPercent = clampedPercent;
|
targetPercent = clampedPercent;
|
||||||
}
|
}
|
||||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||||
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 70f, 99f, "%.0f%%"))
|
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 60f, 99f, "%.0f%%"))
|
||||||
{
|
{
|
||||||
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.7f, 0.99f);
|
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.6f, 0.99f);
|
||||||
_playerPerformanceConfigService.Save();
|
_playerPerformanceConfigService.Save();
|
||||||
}
|
}
|
||||||
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (70% keeps 70% of triangles).{UiSharedService.TooltipSeparator}Default: 70%");
|
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (80% keeps 80% of triangles).{UiSharedService.TooltipSeparator}Default: 80%");
|
||||||
|
|
||||||
ImGui.Dummy(new Vector2(5));
|
ImGui.Dummy(new Vector2(15));
|
||||||
ImGui.TextUnformatted("Decimation targets");
|
ImGui.TextUnformatted("Decimation targets");
|
||||||
_uiShared.DrawHelpText("Hair mods are always excluded from decimation.");
|
_uiShared.DrawHelpText("Hair mods are always excluded from decimation.");
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessGreen"),
|
||||||
|
new SeStringUtils.RichTextEntry("Automatic decimation will only target the selected "),
|
||||||
|
new SeStringUtils.RichTextEntry("decimation targets", UIColors.Get("LightlessGreen"), true),
|
||||||
|
new SeStringUtils.RichTextEntry("."));
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"),
|
||||||
|
new SeStringUtils.RichTextEntry("It is advised to not decimate any body related meshes which includes: "),
|
||||||
|
new SeStringUtils.RichTextEntry("facial mods + sculpts, chest, legs, hands and feet", UIColors.Get("LightlessYellow"), true),
|
||||||
|
new SeStringUtils.RichTextEntry("."));
|
||||||
|
|
||||||
|
_uiShared.DrawNoteLine("!!! ", UIColors.Get("DimRed"),
|
||||||
|
new SeStringUtils.RichTextEntry("Remember, automatic decimation is not perfect and can cause meshes to be ruined, especially hair mods.", UIColors.Get("DimRed"), true));
|
||||||
|
|
||||||
var allowBody = performanceConfig.ModelDecimationAllowBody;
|
var allowBody = performanceConfig.ModelDecimationAllowBody;
|
||||||
if (ImGui.Checkbox("Body", ref allowBody))
|
if (ImGui.Checkbox("Body", ref allowBody))
|
||||||
{
|
{
|
||||||
@@ -3731,6 +3767,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_playerPerformanceConfigService.Save();
|
_playerPerformanceConfigService.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.Dummy(new Vector2(5));
|
||||||
|
|
||||||
|
UiSharedService.ColoredSeparator(UIColors.Get("LightlessGrey"), 3f);
|
||||||
|
|
||||||
ImGui.Dummy(new Vector2(5));
|
ImGui.Dummy(new Vector2(5));
|
||||||
DrawTriangleDecimationCounters();
|
DrawTriangleDecimationCounters();
|
||||||
ImGui.Dummy(new Vector2(5));
|
ImGui.Dummy(new Vector2(5));
|
||||||
|
|||||||
@@ -205,10 +205,8 @@ public sealed class ZoneChatUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
private void ApplyUiVisibilitySettings()
|
private void ApplyUiVisibilitySettings()
|
||||||
{
|
{
|
||||||
var config = _chatConfigService.Current;
|
|
||||||
_uiBuilder.DisableUserUiHide = true;
|
_uiBuilder.DisableUserUiHide = true;
|
||||||
_uiBuilder.DisableCutsceneUiHide = config.ShowInCutscenes;
|
_uiBuilder.DisableCutsceneUiHide = true;
|
||||||
_uiBuilder.DisableGposeUiHide = config.ShowInGpose;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldHide()
|
private bool ShouldHide()
|
||||||
@@ -220,6 +218,16 @@ public sealed class ZoneChatUi : WindowMediatorSubscriberBase
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!config.ShowInGpose && _dalamudUtilService.IsInGpose)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.ShowInCutscenes && _dalamudUtilService.IsInCutscene)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.HideInCombat && _dalamudUtilService.IsInCombat)
|
if (config.HideInCombat && _dalamudUtilService.IsInCombat)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user