Merged Cake and Abel branched into 2.0.3 (#131)
Co-authored-by: azyges <aaaaaa@aaa.aaa> Co-authored-by: cake <admin@cakeandbanana.nl> Co-authored-by: defnotken <itsdefnotken@gmail.com> Reviewed-on: #131
This commit was merged in pull request #131.
This commit is contained in:
@@ -15,6 +15,7 @@ using LightlessSync.Interop.Ipc;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.LightlessConfiguration.Configurations;
|
||||
using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.PlayerData.Factories;
|
||||
using LightlessSync.PlayerData.Handlers;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services;
|
||||
@@ -41,6 +42,7 @@ using System.Globalization;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
@@ -52,7 +54,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private readonly CacheMonitor _cacheMonitor;
|
||||
private readonly LightlessConfigService _configService;
|
||||
private readonly UiThemeConfigService _themeConfigService;
|
||||
private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new();
|
||||
private readonly ConcurrentDictionary<GameObjectHandler, IReadOnlyDictionary<string, FileDownloadStatus>> _currentDownloads = new();
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly FileCacheManager _fileCacheManager;
|
||||
@@ -108,8 +110,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
};
|
||||
private readonly UiSharedService.TabOption<TransferSettingsTab>[] _transferTabOptions = new UiSharedService.TabOption<TransferSettingsTab>[2];
|
||||
private readonly List<UiSharedService.TabOption<ServerSettingsTab>> _serverTabOptions = new(4);
|
||||
private readonly string[] _generalTreeNavOrder = new[]
|
||||
{
|
||||
private readonly string[] _generalTreeNavOrder =
|
||||
[
|
||||
"Import & Export",
|
||||
"Popup & Auto Fill",
|
||||
"Behavior",
|
||||
@@ -119,7 +121,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
"Colors",
|
||||
"Server Info Bar",
|
||||
"Nameplate",
|
||||
};
|
||||
"Animation & Bones"
|
||||
];
|
||||
private static readonly HashSet<string> _generalNavSeparatorAfter = new(StringComparer.Ordinal)
|
||||
{
|
||||
"Popup & Auto Fill",
|
||||
@@ -581,6 +584,94 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangleDecimationCounters()
|
||||
{
|
||||
HashSet<Pair> trackedPairs = new();
|
||||
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
|
||||
foreach (var pair in snapshot.DirectPairs)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
|
||||
foreach (var group in snapshot.GroupPairs.Values)
|
||||
{
|
||||
foreach (var pair in group)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
long totalOriginalTris = 0;
|
||||
long totalEffectiveTris = 0;
|
||||
var hasData = false;
|
||||
|
||||
foreach (var pair in trackedPairs)
|
||||
{
|
||||
if (!pair.IsVisible)
|
||||
continue;
|
||||
|
||||
var original = pair.LastAppliedDataTris;
|
||||
var effective = pair.LastAppliedApproximateEffectiveTris;
|
||||
|
||||
if (original >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalOriginalTris += original;
|
||||
}
|
||||
|
||||
if (effective >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalEffectiveTris += effective;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasData)
|
||||
{
|
||||
ImGui.TextDisabled("Triangle usage has not been calculated yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
var savedTris = Math.Max(0L, totalOriginalTris - totalEffectiveTris);
|
||||
var originalText = FormatTriangleCount(totalOriginalTris);
|
||||
var effectiveText = FormatTriangleCount(totalEffectiveTris);
|
||||
var savedText = FormatTriangleCount(savedTris);
|
||||
|
||||
ImGui.TextUnformatted($"Total triangle usage (original): {originalText}");
|
||||
ImGui.TextUnformatted($"Total triangle usage (effective): {effectiveText}");
|
||||
|
||||
if (savedTris > 0)
|
||||
{
|
||||
UiSharedService.ColorText($"Triangles saved by decimation: {savedText}", UIColors.Get("LightlessGreen"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted($"Triangles saved by decimation: {savedText}");
|
||||
}
|
||||
|
||||
static string FormatTriangleCount(long triangleCount)
|
||||
{
|
||||
if (triangleCount < 0)
|
||||
{
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
if (triangleCount >= 1_000_000)
|
||||
{
|
||||
return FormattableString.Invariant($"{triangleCount / 1_000_000d:0.#}m tris");
|
||||
}
|
||||
|
||||
if (triangleCount >= 1_000)
|
||||
{
|
||||
return FormattableString.Invariant($"{triangleCount / 1_000d:0.#}k tris");
|
||||
}
|
||||
|
||||
return $"{triangleCount} tris";
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawThemeVectorRow(MainStyle.StyleVector2Option option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
@@ -870,10 +961,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
_uiShared.DrawHelpText(
|
||||
$"The download window will show the current progress of outstanding downloads.{Environment.NewLine}{Environment.NewLine}" +
|
||||
$"What do W/Q/P/D stand for?{Environment.NewLine}W = Waiting for Slot (see Maximum Parallel Downloads){Environment.NewLine}" +
|
||||
$"What do W/Q/P/D/C stand for?{Environment.NewLine}W = Waiting for Slot (see Maximum Parallel Downloads){Environment.NewLine}" +
|
||||
$"Q = Queued on Server, waiting for queue ready signal{Environment.NewLine}" +
|
||||
$"P = Processing download (aka downloading){Environment.NewLine}" +
|
||||
$"D = Decompressing download");
|
||||
$"D = Decompressing download{Environment.NewLine}" +
|
||||
$"C = Completed download");
|
||||
if (!_configService.Current.ShowTransferWindow) ImGui.BeginDisabled();
|
||||
ImGui.Indent();
|
||||
|
||||
@@ -1148,7 +1240,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
private async Task<List<string>?> RunSpeedTest(List<string> servers, CancellationToken token)
|
||||
{
|
||||
List<string> speedTestResults = new();
|
||||
List<string> speedTestResults = [];
|
||||
foreach (var server in servers)
|
||||
{
|
||||
HttpResponseMessage? result = null;
|
||||
@@ -1533,6 +1625,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
DrawPairPropertyRow("Approx. VRAM", FormatBytes(pair.LastAppliedApproximateVRAMBytes));
|
||||
DrawPairPropertyRow("Effective VRAM", FormatBytes(pair.LastAppliedApproximateEffectiveVRAMBytes));
|
||||
DrawPairPropertyRow("Last Triangles", pair.LastAppliedDataTris < 0 ? "n/a" : pair.LastAppliedDataTris.ToString(CultureInfo.InvariantCulture));
|
||||
DrawPairPropertyRow("Effective Triangles", pair.LastAppliedApproximateEffectiveTris < 0 ? "n/a" : pair.LastAppliedApproximateEffectiveTris.ToString(CultureInfo.InvariantCulture));
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
@@ -1964,14 +2057,25 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
using (ImRaii.PushIndent(20f))
|
||||
{
|
||||
if (_validationTask.IsCompleted)
|
||||
if (_validationTask.IsCompletedSuccessfully)
|
||||
{
|
||||
UiSharedService.TextWrapped(
|
||||
$"The storage validation has completed and removed {_validationTask.Result.Count} invalid files from storage.");
|
||||
}
|
||||
else if (_validationTask.IsCanceled)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped(
|
||||
"Storage validation was cancelled.",
|
||||
UIColors.Get("LightlessYellow"));
|
||||
}
|
||||
else if (_validationTask.IsFaulted)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped(
|
||||
"Storage validation failed with an error.",
|
||||
UIColors.Get("DimRed"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UiSharedService.TextWrapped(
|
||||
$"Storage validation is running: {_currentProgress.Item1}/{_currentProgress.Item2}");
|
||||
if (_currentProgress.Item3 != null)
|
||||
@@ -3127,10 +3231,102 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.Dummy(new Vector2(10));
|
||||
_uiShared.BigText("Animation");
|
||||
|
||||
using (var animationTree = BeginGeneralTree("Animation & Bones", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
if (animationTree.Visible)
|
||||
{
|
||||
ImGui.TextUnformatted("Animation Options");
|
||||
|
||||
var modes = new[]
|
||||
{
|
||||
AnimationValidationMode.Unsafe,
|
||||
AnimationValidationMode.Safe,
|
||||
AnimationValidationMode.Safest,
|
||||
};
|
||||
|
||||
var labels = new[]
|
||||
{
|
||||
"Unsafe",
|
||||
"Safe (Race)",
|
||||
"Safest (Race + Bones)",
|
||||
};
|
||||
|
||||
var tooltips = new[]
|
||||
{
|
||||
"No validation. Fastest, but may allow incompatible animations (riskier).",
|
||||
"Validates skeleton race + modded skeleton check (recommended).",
|
||||
"Requires matching skeleton race + bone compatibility (strictest).",
|
||||
};
|
||||
|
||||
|
||||
var currentMode = _configService.Current.AnimationValidationMode;
|
||||
int selectedIndex = Array.IndexOf(modes, currentMode);
|
||||
if (selectedIndex < 0) selectedIndex = 1;
|
||||
|
||||
ImGui.SetNextItemWidth(140 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
bool open = ImGui.BeginCombo("Animation validation", labels[selectedIndex]);
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(tooltips[selectedIndex]);
|
||||
|
||||
if (open)
|
||||
{
|
||||
for (int i = 0; i < modes.Length; i++)
|
||||
{
|
||||
bool isSelected = (i == selectedIndex);
|
||||
|
||||
if (ImGui.Selectable(labels[i], isSelected))
|
||||
{
|
||||
selectedIndex = i;
|
||||
_configService.Current.AnimationValidationMode = modes[i];
|
||||
_configService.Save();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(tooltips[i]);
|
||||
|
||||
if (isSelected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
|
||||
var cfg = _configService.Current;
|
||||
|
||||
bool oneBased = cfg.AnimationAllowOneBasedShift;
|
||||
if (ImGui.Checkbox("Treat 1-based PAP indices as compatible", ref oneBased))
|
||||
{
|
||||
cfg.AnimationAllowOneBasedShift = oneBased;
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Fixes off-by-one PAPs (one bone differance in bones and PAP). Can also increase crashing, toggle off if alot of crashing is happening");
|
||||
|
||||
bool neighbor = cfg.AnimationAllowNeighborIndexTolerance;
|
||||
if (ImGui.Checkbox("Allow 1+- bone index tolerance", ref neighbor))
|
||||
{
|
||||
cfg.AnimationAllowNeighborIndexTolerance = neighbor;
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Looser matching on bone matching. Can reduce false blocks happening but also reduces safety and more prone to crashing.");
|
||||
|
||||
ImGui.TreePop();
|
||||
animationTree.MarkContentEnd();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
|
||||
ImGui.Separator();
|
||||
generalSelune.DrawHighlightOnly(ImGui.GetIO().DeltaTime);
|
||||
}
|
||||
}
|
||||
@@ -3220,6 +3416,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
return 1f - (elapsed / GeneralTreeHighlightDuration);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
private struct GeneralTreeScope : IDisposable
|
||||
{
|
||||
private readonly bool _visible;
|
||||
@@ -3527,7 +3724,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText("Controls whether Lightless reduces index textures that exceed the size limit.");
|
||||
|
||||
var dimensionOptions = new[] { 512, 1024, 2048, 4096 };
|
||||
var optionLabels = dimensionOptions.Select(static value => value.ToString()).ToArray();
|
||||
var optionLabels = dimensionOptions.Select(selector: static value => value.ToString()).ToArray();
|
||||
var currentDimension = textureConfig.TextureDownscaleMaxDimension;
|
||||
var selectedIndex = Array.IndexOf(dimensionOptions, currentDimension);
|
||||
if (selectedIndex < 0)
|
||||
@@ -3553,6 +3750,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.SameLine();
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), new SeStringUtils.RichTextEntry("If disabled, saved + effective VRAM usage information will not work.", UIColors.Get("LightlessYellow")));
|
||||
|
||||
var skipPreferredDownscale = textureConfig.SkipTextureDownscaleForPreferredPairs;
|
||||
if (ImGui.Checkbox("Skip downscale for preferred/direct pairs", ref skipPreferredDownscale))
|
||||
{
|
||||
textureConfig.SkipTextureDownscaleForPreferredPairs = skipPreferredDownscale;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, textures for direct pairs with preferred permissions are left untouched.");
|
||||
|
||||
if (!textureConfig.EnableNonIndexTextureMipTrim && !textureConfig.EnableIndexTextureDownscale)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Both trimming and downscale are disabled. Lightless will keep original textures regardless of size.", UIColors.Get("DimRed"));
|
||||
@@ -3580,6 +3785,160 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (_uiShared.MediumTreeNode("Model Optimization", UIColors.Get("DimRed")))
|
||||
{
|
||||
_uiShared.MediumText("Warning", UIColors.Get("DimRed"));
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("Model decimation is a "),
|
||||
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
|
||||
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
|
||||
|
||||
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
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 enableDecimation = performanceConfig.EnableModelDecimation;
|
||||
if (ImGui.Checkbox("Enable model decimation", ref enableDecimation))
|
||||
{
|
||||
performanceConfig.EnableModelDecimation = enableDecimation;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, Lightless generates a decimated copy of given model after download.");
|
||||
|
||||
var keepOriginalModels = performanceConfig.KeepOriginalModelFiles;
|
||||
if (ImGui.Checkbox("Keep original model files", ref keepOriginalModels))
|
||||
{
|
||||
performanceConfig.KeepOriginalModelFiles = keepOriginalModels;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When disabled, Lightless removes the original model after a decimated copy is created.");
|
||||
ImGui.SameLine();
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), new SeStringUtils.RichTextEntry("If disabled, saved + effective triangle usage information will not work.", UIColors.Get("LightlessYellow")));
|
||||
|
||||
var skipPreferredDecimation = performanceConfig.SkipModelDecimationForPreferredPairs;
|
||||
if (ImGui.Checkbox("Skip decimation for preferred/direct pairs", ref skipPreferredDecimation))
|
||||
{
|
||||
performanceConfig.SkipModelDecimationForPreferredPairs = skipPreferredDecimation;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, models for direct pairs with preferred permissions are left untouched.");
|
||||
|
||||
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
|
||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 8_000, 100_000))
|
||||
{
|
||||
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 8_000, 100_000);
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.Text("triangles");
|
||||
_uiShared.DrawHelpText($"Models below this triangle count are left untouched.{UiSharedService.TooltipSeparator}Default: 50,000");
|
||||
|
||||
var targetPercent = (float)(performanceConfig.ModelDecimationTargetRatio * 100.0);
|
||||
var clampedPercent = Math.Clamp(targetPercent, 60f, 99f);
|
||||
if (Math.Abs(clampedPercent - targetPercent) > float.Epsilon)
|
||||
{
|
||||
performanceConfig.ModelDecimationTargetRatio = clampedPercent / 100.0;
|
||||
_playerPerformanceConfigService.Save();
|
||||
targetPercent = clampedPercent;
|
||||
}
|
||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 60f, 99f, "%.0f%%"))
|
||||
{
|
||||
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.6f, 0.99f);
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (80% keeps 80% of triangles).{UiSharedService.TooltipSeparator}Default: 80%");
|
||||
|
||||
ImGui.Dummy(new Vector2(15));
|
||||
ImGui.TextUnformatted("Decimation targets");
|
||||
_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;
|
||||
if (ImGui.Checkbox("Body", ref allowBody))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowBody = allowBody;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowFaceHead = performanceConfig.ModelDecimationAllowFaceHead;
|
||||
if (ImGui.Checkbox("Face/head", ref allowFaceHead))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowFaceHead = allowFaceHead;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowTail = performanceConfig.ModelDecimationAllowTail;
|
||||
if (ImGui.Checkbox("Tails/Ears", ref allowTail))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowTail = allowTail;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowClothing = performanceConfig.ModelDecimationAllowClothing;
|
||||
if (ImGui.Checkbox("Clothing (body/legs/shoes/gloves/hats)", ref allowClothing))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowClothing = allowClothing;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
var allowAccessories = performanceConfig.ModelDecimationAllowAccessories;
|
||||
if (ImGui.Checkbox("Accessories (earring/rings/bracelet/necklace)", ref allowAccessories))
|
||||
{
|
||||
performanceConfig.ModelDecimationAllowAccessories = allowAccessories;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessGrey"), 3f);
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
DrawTriangleDecimationCounters();
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("DimRed"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.Dummy(new Vector2(10));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user