mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Update advanced dyes.
This commit is contained in:
parent
61cb46a298
commit
a1b455d9a5
7 changed files with 157 additions and 48 deletions
|
|
@ -1,6 +1,7 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using FFXIVClientStructs.Interop;
|
||||
using Glamourer.Designs;
|
||||
|
|
@ -27,6 +28,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
private MaterialValueIndex? _drawIndex;
|
||||
private ActorState _state = null!;
|
||||
private Actor _actor;
|
||||
private ColorRow.Mode _mode;
|
||||
private byte _selectedMaterial = byte.MaxValue;
|
||||
private bool _anyChanged;
|
||||
private bool _forceFocus;
|
||||
|
|
@ -96,7 +98,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
return (path, gamePath);
|
||||
}
|
||||
|
||||
private void DrawTabBar(ReadOnlySpan<Pointer<Texture>> textures, ref bool firstAvailable)
|
||||
private void DrawTabBar(ReadOnlySpan<Pointer<Texture>> textures, ReadOnlySpan<Pointer<Material>> materials, ref bool firstAvailable)
|
||||
{
|
||||
using var bar = ImRaii.TabBar("tabs");
|
||||
if (!bar)
|
||||
|
|
@ -105,8 +107,9 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
var table = new ColorTable.Table();
|
||||
for (byte i = 0; i < MaterialService.MaterialsPerModel; ++i)
|
||||
{
|
||||
var index = _drawIndex!.Value with { MaterialIndex = i };
|
||||
var available = index.TryGetTexture(textures, out var texture) && directX.TryGetColorTable(*texture, out table);
|
||||
var index = _drawIndex!.Value with { MaterialIndex = i };
|
||||
var available = index.TryGetTexture(textures, materials, out var texture, out _mode)
|
||||
&& directX.TryGetColorTable(*texture, out table);
|
||||
|
||||
|
||||
if (index == preview.LastValueIndex with { RowIndex = 0 })
|
||||
|
|
@ -163,16 +166,16 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawContent(ReadOnlySpan<Pointer<Texture>> textures)
|
||||
private void DrawContent(ReadOnlySpan<Pointer<Texture>> textures, ReadOnlySpan<Pointer<Material>> materials)
|
||||
{
|
||||
var firstAvailable = true;
|
||||
DrawTabBar(textures, ref firstAvailable);
|
||||
DrawTabBar(textures, materials, ref firstAvailable);
|
||||
|
||||
if (firstAvailable)
|
||||
ImGui.TextUnformatted("No Editable Materials available.");
|
||||
}
|
||||
|
||||
private void DrawWindow(ReadOnlySpan<Pointer<Texture>> textures)
|
||||
private void DrawWindow(ReadOnlySpan<Pointer<Texture>> textures, ReadOnlySpan<Pointer<Material>> materials)
|
||||
{
|
||||
var flags = ImGuiWindowFlags.NoFocusOnAppearing
|
||||
| ImGuiWindowFlags.NoCollapse
|
||||
|
|
@ -208,7 +211,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
try
|
||||
{
|
||||
if (window)
|
||||
DrawContent(textures);
|
||||
DrawContent(textures, materials);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -223,8 +226,8 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
if (!ShouldBeDrawn())
|
||||
return;
|
||||
|
||||
if (_drawIndex!.Value.TryGetTextures(actor, out var textures))
|
||||
DrawWindow(textures);
|
||||
if (_drawIndex!.Value.TryGetTextures(actor, out var textures, out var materials))
|
||||
DrawWindow(textures, materials);
|
||||
}
|
||||
|
||||
private void DrawTable(MaterialValueIndex materialIndex, ColorTable.Table table)
|
||||
|
|
@ -340,15 +343,30 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
v => value.Model.Emissive = v, "E");
|
||||
|
||||
ImGui.SameLine(0, spacing.X);
|
||||
ImGui.SetNextItemWidth(100 * ImGuiHelpers.GlobalScale);
|
||||
applied |= ImGui.DragFloat("##Gloss", ref value.Model.GlossStrength, 0.01f, 0.001f, float.MaxValue, "%.3f G")
|
||||
&& value.Model.GlossStrength > 0;
|
||||
ImGuiUtil.HoverTooltip("Change the gloss strength for this row.");
|
||||
if (_mode is not ColorRow.Mode.Dawntrail)
|
||||
{
|
||||
ImGui.SetNextItemWidth(100 * ImGuiHelpers.GlobalScale);
|
||||
applied |= ImGui.DragFloat("##Gloss", ref value.Model.GlossStrength, 0.01f, 0.001f, float.MaxValue, "%.3f G")
|
||||
&& value.Model.GlossStrength > 0;
|
||||
ImGuiUtil.HoverTooltip("Change the gloss strength for this row.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.Dummy(new Vector2(100 * ImGuiHelpers.GlobalScale, 0));
|
||||
}
|
||||
|
||||
ImGui.SameLine(0, spacing.X);
|
||||
ImGui.SetNextItemWidth(100 * ImGuiHelpers.GlobalScale);
|
||||
applied |= ImGui.DragFloat("##Specular Strength", ref value.Model.SpecularStrength, 0.01f, float.MinValue, float.MaxValue, "%.3f%% SS");
|
||||
ImGuiUtil.HoverTooltip("Change the specular strength for this row.");
|
||||
if (_mode is not ColorRow.Mode.Dawntrail)
|
||||
{
|
||||
ImGui.SetNextItemWidth(100 * ImGuiHelpers.GlobalScale);
|
||||
applied |= ImGui.DragFloat("##Specular Strength", ref value.Model.SpecularStrength, 0.01f, float.MinValue, float.MaxValue,
|
||||
"%.3f%% SS");
|
||||
ImGuiUtil.HoverTooltip("Change the specular strength for this row.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.Dummy(new Vector2(100 * ImGuiHelpers.GlobalScale, 0));
|
||||
}
|
||||
|
||||
ImGui.SameLine(0, spacing.X);
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), buttonSize, "Export this row to your clipboard.", false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using FFXIVClientStructs.Havok.Animation.Rig;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop.Penumbra;
|
||||
using Glamourer.State;
|
||||
|
|
@ -67,7 +68,8 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
|||
MaterialValueIndex.DrawObjectType.Human => GetTempSlot((Human*)characterBase, slotId),
|
||||
_ => GetTempSlot((Weapon*)characterBase),
|
||||
};
|
||||
UpdateMaterialValues(state, values, drawData, ref baseColorSet);
|
||||
var mode = PrepareColorSet.GetMode(material);
|
||||
UpdateMaterialValues(state, values, drawData, ref baseColorSet, mode);
|
||||
|
||||
if (MaterialService.GenerateNewColorTable(baseColorSet, out var texture))
|
||||
ret = (nint)texture;
|
||||
|
|
@ -75,7 +77,7 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
|||
|
||||
/// <summary> Update and apply the glamourer state of an actor according to the application sources when updated by the game. </summary>
|
||||
private void UpdateMaterialValues(ActorState state, ReadOnlySpan<(uint Key, MaterialValueState Value)> values, CharacterWeapon drawData,
|
||||
ref ColorTable.Table colorTable)
|
||||
ref ColorTable.Table colorTable, ColorRow.Mode mode)
|
||||
{
|
||||
var deleteList = _deleteList.Value!;
|
||||
deleteList.Clear();
|
||||
|
|
@ -86,17 +88,17 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
|||
ref var row = ref colorTable[idx.RowIndex];
|
||||
var newGame = new ColorRow(row);
|
||||
if (materialValue.EqualGame(newGame, drawData))
|
||||
materialValue.Model.Apply(ref row);
|
||||
materialValue.Model.Apply(ref row, mode);
|
||||
else
|
||||
switch (materialValue.Source)
|
||||
{
|
||||
case StateSource.Pending:
|
||||
materialValue.Model.Apply(ref row);
|
||||
materialValue.Model.Apply(ref row, mode);
|
||||
state.Materials.UpdateValue(idx, new MaterialValueState(newGame, materialValue.Model, drawData, StateSource.Manual),
|
||||
out _);
|
||||
break;
|
||||
case StateSource.IpcPending:
|
||||
materialValue.Model.Apply(ref row);
|
||||
materialValue.Model.Apply(ref row, mode);
|
||||
state.Materials.UpdateValue(idx, new MaterialValueState(newGame, materialValue.Model, drawData, StateSource.IpcManual),
|
||||
out _);
|
||||
break;
|
||||
|
|
@ -106,7 +108,7 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
|||
break;
|
||||
case StateSource.Fixed:
|
||||
case StateSource.IpcFixed:
|
||||
materialValue.Model.Apply(ref row);
|
||||
materialValue.Model.Apply(ref row, mode);
|
||||
state.Materials.UpdateValue(idx, new MaterialValueState(newGame, materialValue.Model, drawData, materialValue.Source),
|
||||
out _);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using FFXIVClientStructs.Interop;
|
||||
using Newtonsoft.Json;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Files.MaterialStructs;
|
||||
using Penumbra.GameData.Interop;
|
||||
using CsMaterial = FFXIVClientStructs.FFXIV.Client.Graphics.Render.Material;
|
||||
|
||||
namespace Glamourer.Interop.Material;
|
||||
|
||||
|
|
@ -75,21 +77,39 @@ public readonly record struct MaterialValueIndex(
|
|||
return model.IsCharacterBase;
|
||||
}
|
||||
|
||||
public unsafe bool TryGetTextures(Actor actor, out ReadOnlySpan<Pointer<Texture>> textures, out ReadOnlySpan<Pointer<CsMaterial>> materials)
|
||||
{
|
||||
if (!TryGetModel(actor, out var model)
|
||||
|| SlotIndex >= model.AsCharacterBase->SlotCount
|
||||
|| model.AsCharacterBase->ColorTableTexturesSpan.Length < (SlotIndex + 1) * MaterialService.MaterialsPerModel)
|
||||
{
|
||||
textures = [];
|
||||
materials = [];
|
||||
return false;
|
||||
}
|
||||
|
||||
var from = SlotIndex * MaterialService.MaterialsPerModel;
|
||||
textures = model.AsCharacterBase->ColorTableTexturesSpan.Slice(from, MaterialService.MaterialsPerModel);
|
||||
materials = model.AsCharacterBase->MaterialsSpan.Slice(from, MaterialService.MaterialsPerModel);
|
||||
return true;
|
||||
}
|
||||
|
||||
public unsafe bool TryGetTextures(Actor actor, out ReadOnlySpan<Pointer<Texture>> textures)
|
||||
{
|
||||
if (!TryGetModel(actor, out var model)
|
||||
|| SlotIndex >= model.AsCharacterBase->SlotCount
|
||||
|| model.AsCharacterBase->ColorTableTexturesSpan.Length < (SlotIndex + 1) * MaterialService.MaterialsPerModel)
|
||||
{
|
||||
textures = [];
|
||||
textures = [];
|
||||
return false;
|
||||
}
|
||||
|
||||
textures = model.AsCharacterBase->ColorTableTexturesSpan.Slice(SlotIndex * MaterialService.MaterialsPerModel,
|
||||
MaterialService.MaterialsPerModel);
|
||||
var from = SlotIndex * MaterialService.MaterialsPerModel;
|
||||
textures = model.AsCharacterBase->ColorTableTexturesSpan.Slice(from, MaterialService.MaterialsPerModel);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public unsafe bool TryGetTexture(Actor actor, out Texture** texture)
|
||||
{
|
||||
if (TryGetTextures(actor, out var textures))
|
||||
|
|
@ -99,6 +119,38 @@ public readonly record struct MaterialValueIndex(
|
|||
return false;
|
||||
}
|
||||
|
||||
public unsafe bool TryGetTexture(Actor actor, out Texture** texture, out ColorRow.Mode mode)
|
||||
{
|
||||
if (TryGetTextures(actor, out var textures, out var materials))
|
||||
return TryGetTexture(textures, materials, out texture, out mode);
|
||||
|
||||
mode = ColorRow.Mode.Dawntrail;
|
||||
texture = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public unsafe bool TryGetTexture(ReadOnlySpan<Pointer<Texture>> textures, ReadOnlySpan<Pointer<CsMaterial>> materials,
|
||||
out Texture** texture, out ColorRow.Mode mode)
|
||||
{
|
||||
mode = MaterialIndex >= materials.Length
|
||||
? ColorRow.Mode.Dawntrail
|
||||
: PrepareColorSet.GetMode((MaterialResourceHandle*)materials[MaterialIndex].Value);
|
||||
|
||||
|
||||
if (MaterialIndex >= textures.Length || textures[MaterialIndex].Value == null)
|
||||
{
|
||||
texture = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
fixed (Pointer<Texture>* ptr = textures)
|
||||
{
|
||||
texture = (Texture**)ptr + MaterialIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public unsafe bool TryGetTexture(ReadOnlySpan<Pointer<Texture>> textures, out Texture** texture)
|
||||
{
|
||||
if (MaterialIndex >= textures.Length || textures[MaterialIndex].Value == null)
|
||||
|
|
@ -115,6 +167,7 @@ public readonly record struct MaterialValueIndex(
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static MaterialValueIndex FromKey(uint key)
|
||||
=> new(key);
|
||||
|
||||
|
|
@ -190,4 +243,4 @@ public readonly record struct MaterialValueIndex(
|
|||
JsonSerializer serializer)
|
||||
=> FromKey(serializer.Deserialize<uint>(reader), out var value) ? value : throw new Exception($"Invalid material key {value.Key}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ namespace Glamourer.Interop.Material;
|
|||
/// <summary> Values are not squared. </summary>
|
||||
public struct ColorRow(Vector3 diffuse, Vector3 specular, Vector3 emissive, float specularStrength, float glossStrength)
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
Legacy,
|
||||
Dawntrail,
|
||||
}
|
||||
|
||||
public static readonly ColorRow Empty = new(Vector3.Zero, Vector3.Zero, Vector3.Zero, 0, 0);
|
||||
|
||||
public Vector3 Diffuse = diffuse;
|
||||
|
|
@ -22,8 +28,9 @@ public struct ColorRow(Vector3 diffuse, Vector3 specular, Vector3 emissive, floa
|
|||
public float GlossStrength = glossStrength;
|
||||
|
||||
public ColorRow(in ColorTableRow row)
|
||||
: this(Root((Vector3)row.DiffuseColor), Root((Vector3)row.SpecularColor), Root((Vector3)row.EmissiveColor), (float)row.SheenRate,
|
||||
(float)row.Metalness)
|
||||
: this(Root((Vector3)row.DiffuseColor), Root((Vector3)row.SpecularColor), Root((Vector3)row.EmissiveColor),
|
||||
(float)row.LegacySpecularStrength(),
|
||||
(float)row.LegacyGloss())
|
||||
{ }
|
||||
|
||||
public readonly bool NearEqual(in ColorRow rhs)
|
||||
|
|
@ -45,7 +52,7 @@ public struct ColorRow(Vector3 diffuse, Vector3 specular, Vector3 emissive, floa
|
|||
private static float Root(float value)
|
||||
=> value < 0 ? MathF.Sqrt(-value) : MathF.Sqrt(value);
|
||||
|
||||
public readonly bool Apply(ref ColorTableRow row)
|
||||
public readonly bool Apply(ref ColorTableRow row, Mode mode)
|
||||
{
|
||||
var ret = false;
|
||||
var d = Square(Diffuse);
|
||||
|
|
@ -69,22 +76,40 @@ public struct ColorRow(Vector3 diffuse, Vector3 specular, Vector3 emissive, floa
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if (!((float)row.SheenRate).NearEqual(SpecularStrength))
|
||||
if (mode is Mode.Legacy)
|
||||
{
|
||||
row.SheenRate = (Half)SpecularStrength;
|
||||
ret = true;
|
||||
}
|
||||
if (!((float)row.LegacySpecularStrength()).NearEqual(SpecularStrength))
|
||||
{
|
||||
row.LegacySpecularStrengthWrite() = (Half)SpecularStrength;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (!((float)row.Metalness).NearEqual(GlossStrength))
|
||||
{
|
||||
row.Metalness = (Half)GlossStrength;
|
||||
ret = true;
|
||||
if (!((float)row.LegacyGloss()).NearEqual(GlossStrength))
|
||||
{
|
||||
row.LegacyGlossWrite() = (Half)GlossStrength;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ColorTableRowExtensions
|
||||
{
|
||||
internal static Half LegacySpecularStrength(this in ColorTableRow row)
|
||||
=> row[7];
|
||||
|
||||
internal static Half LegacyGloss(this in ColorTableRow row)
|
||||
=> row[3];
|
||||
|
||||
internal static ref Half LegacySpecularStrengthWrite(this ref ColorTableRow row)
|
||||
=> ref row[7];
|
||||
|
||||
internal static ref Half LegacyGlossWrite(this ref ColorTableRow row)
|
||||
=> ref row[3];
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(Converter))]
|
||||
public struct MaterialValueDesign(ColorRow value, bool enabled, bool revert)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -91,11 +91,12 @@ public sealed unsafe class PrepareColorSet
|
|||
}
|
||||
|
||||
/// <summary> Assumes the actor is valid. </summary>
|
||||
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out ColorTable.Table table)
|
||||
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out ColorTable.Table table, out ColorRow.Mode mode)
|
||||
{
|
||||
var idx = index.SlotIndex * MaterialService.MaterialsPerModel + index.MaterialIndex;
|
||||
if (!index.TryGetModel(actor, out var model))
|
||||
{
|
||||
mode = ColorRow.Mode.Dawntrail;
|
||||
table = default;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -103,10 +104,12 @@ public sealed unsafe class PrepareColorSet
|
|||
var handle = (MaterialResourceHandle*)model.AsCharacterBase->Materials[idx];
|
||||
if (handle == null)
|
||||
{
|
||||
mode = ColorRow.Mode.Dawntrail;
|
||||
table = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
mode = GetMode(handle);
|
||||
return TryGetColorTable(handle, GetStains(), out table);
|
||||
|
||||
StainIds GetStains()
|
||||
|
|
@ -126,6 +129,14 @@ public sealed unsafe class PrepareColorSet
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary> Get the shader mode of the material. </summary>
|
||||
public static ColorRow.Mode GetMode(MaterialResourceHandle* handle)
|
||||
=> handle == null
|
||||
? ColorRow.Mode.Dawntrail
|
||||
: handle->ShpkNameSpan.SequenceEqual("characterlegacy.shpk"u8)
|
||||
? ColorRow.Mode.Legacy
|
||||
: ColorRow.Mode.Dawntrail;
|
||||
|
||||
/// <summary> Get the correct dye table for a material. </summary>
|
||||
private static bool GetDyeTable(MaterialResourceHandle* material, out ushort* ptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class StateApplier(
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeCustomize(ActorData, in CustomizeArray, ActorState?)"/>
|
||||
/// <inheritdoc cref="ChangeCustomize(ActorData,in CustomizeArray,ActorState?)"/>
|
||||
public ActorData ChangeCustomize(ActorState state, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
|
|
@ -177,7 +177,7 @@ public class StateApplier(
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeStain(ActorData,EquipSlot,StainId)"/>
|
||||
/// <inheritdoc cref="ChangeStain(ActorData,EquipSlot,StainIds)"/>
|
||||
public ActorData ChangeStain(ActorState state, EquipSlot slot, bool apply)
|
||||
{
|
||||
var data = GetData(state);
|
||||
|
|
@ -197,7 +197,7 @@ public class StateApplier(
|
|||
ChangeOffhand(data, item, stains);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ChangeWeapon(ActorData,EquipSlot,EquipItem,StainId)"/>
|
||||
/// <inheritdoc cref="ChangeWeapon(ActorData,EquipSlot,EquipItem,StainIds)"/>
|
||||
public ActorData ChangeWeapon(ActorState state, EquipSlot slot, bool apply, bool onlyGPose)
|
||||
{
|
||||
var data = GetData(state);
|
||||
|
|
@ -229,7 +229,7 @@ public class StateApplier(
|
|||
}
|
||||
|
||||
/// <summary> Change a meta state. </summary>
|
||||
public unsafe void ChangeMetaState(ActorData data, MetaIndex index, bool value)
|
||||
public void ChangeMetaState(ActorData data, MetaIndex index, bool value)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
|
|
@ -311,15 +311,15 @@ public class StateApplier(
|
|||
|
||||
foreach (var actor in data.Objects.Where(a => a is { IsCharacter: true, Model.IsHuman: true }))
|
||||
{
|
||||
if (!index.TryGetTexture(actor, out var texture))
|
||||
if (!index.TryGetTexture(actor, out var texture, out var mode))
|
||||
continue;
|
||||
|
||||
if (!_directX.TryGetColorTable(*texture, out var table))
|
||||
continue;
|
||||
|
||||
if (value.HasValue)
|
||||
value.Value.Apply(ref table[index.RowIndex]);
|
||||
else if (PrepareColorSet.TryGetColorTable(actor, index, out var baseTable))
|
||||
value.Value.Apply(ref table[index.RowIndex], mode);
|
||||
else if (PrepareColorSet.TryGetColorTable(actor, index, out var baseTable, out _))
|
||||
table[index.RowIndex] = baseTable[index.RowIndex];
|
||||
else
|
||||
continue;
|
||||
|
|
@ -353,11 +353,11 @@ public class StateApplier(
|
|||
if (!mainKey.TryGetTexture(actor, out var texture))
|
||||
continue;
|
||||
|
||||
if (!PrepareColorSet.TryGetColorTable(actor, mainKey, out var table))
|
||||
if (!PrepareColorSet.TryGetColorTable(actor, mainKey, out var table, out var mode))
|
||||
continue;
|
||||
|
||||
foreach (var (key, value) in values)
|
||||
value.Model.Apply(ref table[key.RowIndex]);
|
||||
value.Model.Apply(ref table[key.RowIndex], mode);
|
||||
|
||||
_directX.ReplaceColorTable(texture, table);
|
||||
}
|
||||
|
|
|
|||
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
|||
Subproject commit 51bab6dd1bd7d98cc468e8122f410e1c79e3c92d
|
||||
Subproject commit d9486ae54b5a4b61cf74f79ed27daa659eb1ce5b
|
||||
Loading…
Add table
Add a link
Reference in a new issue