mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Update other things.
This commit is contained in:
parent
81059411e5
commit
9529963aa2
31 changed files with 575 additions and 294 deletions
|
|
@ -106,6 +106,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
["Tags"] = JArray.FromObject(Tags),
|
||||
["WriteProtected"] = WriteProtected(),
|
||||
["Equipment"] = SerializeEquipment(),
|
||||
["Bonus"] = SerializeBonusItems(),
|
||||
["Customize"] = SerializeCustomize(),
|
||||
["Parameters"] = SerializeParameters(),
|
||||
["Materials"] = SerializeMaterials(),
|
||||
|
|
@ -171,6 +172,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
|||
design.SetWriteProtected(json["WriteProtected"]?.ToObject<bool>() ?? false);
|
||||
LoadCustomize(customizations, json["Customize"], design, design.Name, true, false);
|
||||
LoadEquip(items, json["Equipment"], design, design.Name, true);
|
||||
LoadBonus(items, design, json["Bonus"]);
|
||||
LoadMods(json["Mods"], design);
|
||||
LoadParameters(json["Parameters"], design, design.Name);
|
||||
LoadMaterials(json["Materials"], design, design.Name);
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ public class DesignBase
|
|||
{
|
||||
["FileVersion"] = FileVersion,
|
||||
["Equipment"] = SerializeEquipment(),
|
||||
["Bonus"] = SerializeBonusItems(),
|
||||
["Customize"] = SerializeCustomize(),
|
||||
["Parameters"] = SerializeParameters(),
|
||||
["Materials"] = SerializeMaterials(),
|
||||
|
|
@ -279,7 +280,7 @@ public class DesignBase
|
|||
var item = _designData.BonusItem(slot);
|
||||
ret[slot.ToString()] = new JObject()
|
||||
{
|
||||
["BonusId"] = item.ModelId.Id,
|
||||
["BonusId"] = item.Id.Id,
|
||||
["Apply"] = DoApplyBonusItem(slot),
|
||||
};
|
||||
}
|
||||
|
|
@ -424,9 +425,35 @@ public class DesignBase
|
|||
LoadEquip(items, json["Equipment"], ret, "Temporary Design", true);
|
||||
LoadParameters(json["Parameters"], ret, "Temporary Design");
|
||||
LoadMaterials(json["Materials"], ret, "Temporary Design");
|
||||
LoadBonus(items, ret, json["Bonus"]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected static void LoadBonus(ItemManager items, DesignBase design, JToken? json)
|
||||
{
|
||||
if (json is not JObject obj)
|
||||
{
|
||||
design.Application.BonusItem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var slot in BonusExtensions.AllFlags)
|
||||
{
|
||||
var itemJson = json[slot.ToString()] as JObject;
|
||||
if (itemJson == null)
|
||||
{
|
||||
design.Application.BonusItem &= ~slot;
|
||||
design.GetDesignDataRef().SetBonusItem(slot, BonusItem.Empty(slot));
|
||||
continue;
|
||||
}
|
||||
|
||||
design.SetApplyBonusItem(slot, itemJson["Apply"]?.ToObject<bool>() ?? false);
|
||||
var id = itemJson["BonusId"]?.ToObject<ushort>() ?? 0;
|
||||
var item = items.Resolve(slot, id);
|
||||
design.GetDesignDataRef().SetBonusItem(slot, item);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void LoadParameters(JToken? parameters, DesignBase design, string name)
|
||||
{
|
||||
if (parameters == null)
|
||||
|
|
@ -436,7 +463,6 @@ public class DesignBase
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.ValueFlags)
|
||||
{
|
||||
if (!TryGetToken(flag, out var token))
|
||||
|
|
@ -523,32 +549,15 @@ public class DesignBase
|
|||
return;
|
||||
}
|
||||
|
||||
static (CustomItemId, StainIds, bool, bool, bool, bool) ParseItem(EquipSlot slot, JToken? item)
|
||||
{
|
||||
var id = item?["ItemId"]?.ToObject<ulong>() ?? ItemManager.NothingId(slot).Id;
|
||||
var stain = (StainId)(item?["Stain"]?.ToObject<byte>() ?? 0);
|
||||
var crest = item?["Crest"]?.ToObject<bool>() ?? false;
|
||||
var apply = item?["Apply"]?.ToObject<bool>() ?? false;
|
||||
var applyStain = item?["ApplyStain"]?.ToObject<bool>() ?? false;
|
||||
var applyCrest = item?["ApplyCrest"]?.ToObject<bool>() ?? false;
|
||||
return (id, stain, crest, apply, applyStain, applyCrest);
|
||||
}
|
||||
|
||||
void PrintWarning(string msg)
|
||||
{
|
||||
if (msg.Length > 0 && name != "Temporary Design")
|
||||
Glamourer.Messager.NotificationMessage($"{msg} ({name})", NotificationType.Warning);
|
||||
}
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
var (id, stain, crest, apply, applyStain, applyCrest) = ParseItem(slot, equip[slot.ToString()]);
|
||||
var (id, stains, crest, apply, applyStain, applyCrest) = ParseItem(slot, equip[slot.ToString()]);
|
||||
|
||||
PrintWarning(items.ValidateItem(slot, id, out var item, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stain, out stain, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stains, out stains, allowUnknown));
|
||||
var crestSlot = slot.ToCrestFlag();
|
||||
design._designData.SetItem(slot, item);
|
||||
design._designData.SetStain(slot, stain);
|
||||
design._designData.SetStain(slot, stains);
|
||||
design._designData.SetCrest(crestSlot, crest);
|
||||
design.SetApplyEquip(slot, apply);
|
||||
design.SetApplyStain(slot, applyStain);
|
||||
|
|
@ -556,21 +565,21 @@ public class DesignBase
|
|||
}
|
||||
|
||||
{
|
||||
var (id, stain, crest, apply, applyStain, applyCrest) = ParseItem(EquipSlot.MainHand, equip[EquipSlot.MainHand.ToString()]);
|
||||
var (id, stains, crest, apply, applyStain, applyCrest) = ParseItem(EquipSlot.MainHand, equip[EquipSlot.MainHand.ToString()]);
|
||||
if (id == ItemManager.NothingId(EquipSlot.MainHand))
|
||||
id = items.DefaultSword.ItemId;
|
||||
var (idOff, stainOff, crestOff, applyOff, applyStainOff, applyCrestOff) =
|
||||
var (idOff, stainsOff, crestOff, applyOff, applyStainOff, applyCrestOff) =
|
||||
ParseItem(EquipSlot.OffHand, equip[EquipSlot.OffHand.ToString()]);
|
||||
if (id == ItemManager.NothingId(EquipSlot.OffHand))
|
||||
id = ItemManager.NothingId(FullEquipType.Shield);
|
||||
|
||||
PrintWarning(items.ValidateWeapons(id, idOff, out var main, out var off, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stain, out stain, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stainOff, out stainOff, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stains, out stains, allowUnknown));
|
||||
PrintWarning(items.ValidateStain(stainsOff, out stainsOff, allowUnknown));
|
||||
design._designData.SetItem(EquipSlot.MainHand, main);
|
||||
design._designData.SetItem(EquipSlot.OffHand, off);
|
||||
design._designData.SetStain(EquipSlot.MainHand, stain);
|
||||
design._designData.SetStain(EquipSlot.OffHand, stainOff);
|
||||
design._designData.SetStain(EquipSlot.MainHand, stains);
|
||||
design._designData.SetStain(EquipSlot.OffHand, stainsOff);
|
||||
design._designData.SetCrest(CrestFlag.MainHand, crest);
|
||||
design._designData.SetCrest(CrestFlag.OffHand, crestOff);
|
||||
design.SetApplyEquip(EquipSlot.MainHand, apply);
|
||||
|
|
@ -591,6 +600,24 @@ public class DesignBase
|
|||
metaValue = QuadBool.FromJObject(equip["Visor"], "IsToggled", "Apply", QuadBool.NullFalse);
|
||||
design.SetApplyMeta(MetaIndex.VisorState, metaValue.Enabled);
|
||||
design._designData.SetVisor(metaValue.ForcedValue);
|
||||
return;
|
||||
|
||||
void PrintWarning(string msg)
|
||||
{
|
||||
if (msg.Length > 0 && name != "Temporary Design")
|
||||
Glamourer.Messager.NotificationMessage($"{msg} ({name})", NotificationType.Warning);
|
||||
}
|
||||
|
||||
static (CustomItemId, StainIds, bool, bool, bool, bool) ParseItem(EquipSlot slot, JToken? item)
|
||||
{
|
||||
var id = item?["ItemId"]?.ToObject<ulong>() ?? ItemManager.NothingId(slot).Id;
|
||||
var stains = StainIds.ParseFromObject(item as JObject);
|
||||
var crest = item?["Crest"]?.ToObject<bool>() ?? false;
|
||||
var apply = item?["Apply"]?.ToObject<bool>() ?? false;
|
||||
var applyStain = item?["ApplyStain"]?.ToObject<bool>() ?? false;
|
||||
var applyCrest = item?["ApplyCrest"]?.ToObject<bool>() ?? false;
|
||||
return (id, stains, crest, apply, applyStain, applyCrest);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void LoadCustomize(CustomizeService customizations, JToken? json, DesignBase design, string name, bool forbidNonHuman,
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ public class DesignConverter(
|
|||
foreach (var (key, value) in materials.Values)
|
||||
{
|
||||
var idx = MaterialValueIndex.FromKey(key);
|
||||
if (idx.RowIndex >= LegacyColorTable.NumUsedRows)
|
||||
if (idx.RowIndex >= ColorTable.NumUsedRows)
|
||||
continue;
|
||||
if (idx.MaterialIndex >= MaterialService.MaterialsPerModel)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public unsafe struct DesignData
|
|||
8 => EquipItem.FromIds(_itemIds[ 8], _iconIds[ 8], ((CharacterArmor*)ptr)[8].Set, 0, ((CharacterArmor*)ptr)[8].Variant, FullEquipType.Finger, name: _nameRFinger ),
|
||||
9 => EquipItem.FromIds(_itemIds[ 9], _iconIds[ 9], ((CharacterArmor*)ptr)[9].Set, 0, ((CharacterArmor*)ptr)[9].Variant, FullEquipType.Finger, name: _nameLFinger ),
|
||||
10 => EquipItem.FromIds(_itemIds[10], _iconIds[10], *(PrimaryId*)(ptr + EquipmentByteSize + 0), *(SecondaryId*)(ptr + EquipmentByteSize + 2), *(Variant*)(ptr + EquipmentByteSize + 4), _typeMainhand, name: _nameMainhand),
|
||||
11 => EquipItem.FromIds(_itemIds[11], _iconIds[11], *(PrimaryId*)(ptr + EquipmentByteSize + 4), *(SecondaryId*)(ptr + EquipmentByteSize + 2), *(Variant*)(ptr + EquipmentByteSize + 4), _typeOffhand, name: _nameOffhand ),
|
||||
11 => EquipItem.FromIds(_itemIds[11], _iconIds[11], *(PrimaryId*)(ptr + EquipmentByteSize + 8), *(SecondaryId*)(ptr + EquipmentByteSize + 10), *(Variant*)(ptr + EquipmentByteSize + 12), _typeOffhand, name: _nameOffhand ),
|
||||
_ => new EquipItem(),
|
||||
// @formatter:on
|
||||
};
|
||||
|
|
@ -176,12 +176,14 @@ public unsafe struct DesignData
|
|||
_nameMainhand = item.Name;
|
||||
_equipmentBytes[EquipmentByteSize + 2] = (byte)item.SecondaryId.Id;
|
||||
_equipmentBytes[EquipmentByteSize + 3] = (byte)(item.SecondaryId.Id >> 8);
|
||||
_equipmentBytes[EquipmentByteSize + 4] = item.Variant.Id;
|
||||
_typeMainhand = item.Type;
|
||||
return true;
|
||||
case 11:
|
||||
_nameOffhand = item.Name;
|
||||
_equipmentBytes[EquipmentByteSize + 2] = (byte)item.SecondaryId.Id;
|
||||
_equipmentBytes[EquipmentByteSize + 3] = (byte)(item.SecondaryId.Id >> 8);
|
||||
_equipmentBytes[EquipmentByteSize + 10] = (byte)item.SecondaryId.Id;
|
||||
_equipmentBytes[EquipmentByteSize + 11] = (byte)(item.SecondaryId.Id >> 8);
|
||||
_equipmentBytes[EquipmentByteSize + 12] = item.Variant.Id;
|
||||
_typeOffhand = item.Type;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -212,18 +214,18 @@ public unsafe struct DesignData
|
|||
=> slot.ToIndex() switch
|
||||
{
|
||||
// @formatter:off
|
||||
0 => SetIfDifferent(ref _equipmentBytes[0 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[0 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
1 => SetIfDifferent(ref _equipmentBytes[1 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[1 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
2 => SetIfDifferent(ref _equipmentBytes[2 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[2 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
3 => SetIfDifferent(ref _equipmentBytes[3 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[3 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
4 => SetIfDifferent(ref _equipmentBytes[4 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[4 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
5 => SetIfDifferent(ref _equipmentBytes[5 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[5 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
6 => SetIfDifferent(ref _equipmentBytes[6 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[6 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
7 => SetIfDifferent(ref _equipmentBytes[7 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[7 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
8 => SetIfDifferent(ref _equipmentBytes[8 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[8 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
9 => SetIfDifferent(ref _equipmentBytes[9 * CharacterArmor.Size + 3], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[9 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
10 => SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 6], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 7], stains.Stain2.Id),
|
||||
11 => SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 14], stains.Stain1.Id) || SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 15], stains.Stain2.Id),
|
||||
0 => SetIfDifferent(ref _equipmentBytes[0 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[0 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
1 => SetIfDifferent(ref _equipmentBytes[1 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[1 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
2 => SetIfDifferent(ref _equipmentBytes[2 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[2 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
3 => SetIfDifferent(ref _equipmentBytes[3 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[3 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
4 => SetIfDifferent(ref _equipmentBytes[4 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[4 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
5 => SetIfDifferent(ref _equipmentBytes[5 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[5 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
6 => SetIfDifferent(ref _equipmentBytes[6 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[6 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
7 => SetIfDifferent(ref _equipmentBytes[7 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[7 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
8 => SetIfDifferent(ref _equipmentBytes[8 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[8 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
9 => SetIfDifferent(ref _equipmentBytes[9 * CharacterArmor.Size + 3], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[9 * CharacterArmor.Size + 4], stains.Stain2.Id),
|
||||
10 => SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 6], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 7], stains.Stain2.Id),
|
||||
11 => SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 14], stains.Stain1.Id) | SetIfDifferent(ref _equipmentBytes[EquipmentByteSize + 15], stains.Stain2.Id),
|
||||
_ => false,
|
||||
// @formatter:on
|
||||
};
|
||||
|
|
@ -322,6 +324,13 @@ public unsafe struct DesignData
|
|||
SetItem(EquipSlot.OffHand, ItemManager.NothingItem(FullEquipType.Shield));
|
||||
SetStain(EquipSlot.OffHand, StainIds.None);
|
||||
SetCrest(CrestFlag.OffHand, false);
|
||||
SetDefaultBonusItems();
|
||||
}
|
||||
|
||||
public void SetDefaultBonusItems()
|
||||
{
|
||||
foreach (var slot in BonusExtensions.AllFlags)
|
||||
SetBonusItem(slot, Penumbra.GameData.Structs.BonusItem.Empty(slot));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -165,9 +165,21 @@ public class DesignEditor(
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ChangeBonusItem(object data, BonusItemFlag slot, BonusItem item, ApplySettings settings = default)
|
||||
{
|
||||
var design = (Design)data;
|
||||
if (!Items.IsBonusItemValid(slot, item.Id, out item))
|
||||
return;
|
||||
|
||||
var oldItem = design.DesignData.BonusItem(slot);
|
||||
if (!design.GetDesignDataRef().SetBonusItem(slot, item))
|
||||
return;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set {slot} bonus item to {item}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.BonusItem, design, (oldItem, item, slot));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ public sealed class DesignManager : DesignEditor
|
|||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
SaveService.QueueSave(design);
|
||||
Glamourer.Log.Debug($"Set applying of {slot} bonus item to {value}.");
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyBonus, design, slot);
|
||||
DesignChanged.Invoke(DesignChanged.Type.ApplyBonusItem, design, slot);
|
||||
}
|
||||
|
||||
/// <summary> Change whether to apply a specific stain. </summary>
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ public sealed class DesignChanged()
|
|||
/// <summary> An existing design had an equipment piece changed. Data is the old value, the new value and the slot [(EquipItem, EquipItem, EquipSlot)]. </summary>
|
||||
Equip,
|
||||
|
||||
/// <summary> An existing design had a bonus item changed. Data is the old value, the new value and the slot [(BonusItem, BonusItem, BonusItemFlag)]. </summary>
|
||||
BonusItem,
|
||||
|
||||
/// <summary> An existing design had its weapons changed. Data is the old mainhand, the old offhand, the new mainhand, the new offhand (if any) and the new gauntlets (if any). [(EquipItem, EquipItem, EquipItem, EquipItem?, EquipItem?)]. </summary>
|
||||
Weapon,
|
||||
|
||||
|
|
@ -90,7 +93,7 @@ public sealed class DesignChanged()
|
|||
ApplyEquip,
|
||||
|
||||
/// <summary> An existing design changed whether a specific bonus item is applied. Data is the slot of the item [BonusItemFlag]. </summary>
|
||||
ApplyBonus,
|
||||
ApplyBonusItem,
|
||||
|
||||
/// <summary> An existing design changed whether a specific stain is applied. Data is the slot of the equipment [EquipSlot]. </summary>
|
||||
ApplyStain,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ public struct CustomizeParameterData
|
|||
public Vector3 HairSpecular;
|
||||
public Vector3 HairHighlight;
|
||||
public Vector3 LeftEye;
|
||||
public float LeftScleraIntensity;
|
||||
public Vector3 RightEye;
|
||||
public float RightScleraIntensity;
|
||||
public Vector3 FeatureColor;
|
||||
public float FacePaintUvMultiplier;
|
||||
public float FacePaintUvOffset;
|
||||
|
|
@ -33,7 +35,9 @@ public struct CustomizeParameterData
|
|||
CustomizeParameterFlag.HairSpecular => new CustomizeParameterValue(HairSpecular),
|
||||
CustomizeParameterFlag.HairHighlight => new CustomizeParameterValue(HairHighlight),
|
||||
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(LeftEye),
|
||||
CustomizeParameterFlag.LeftScleraIntensity => new CustomizeParameterValue(LeftScleraIntensity),
|
||||
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(RightEye),
|
||||
CustomizeParameterFlag.RightScleraIntensity => new CustomizeParameterValue(RightScleraIntensity),
|
||||
CustomizeParameterFlag.FeatureColor => new CustomizeParameterValue(FeatureColor),
|
||||
CustomizeParameterFlag.DecalColor => new CustomizeParameterValue(DecalColor),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => new CustomizeParameterValue(FacePaintUvMultiplier),
|
||||
|
|
@ -57,7 +61,9 @@ public struct CustomizeParameterData
|
|||
CustomizeParameterFlag.HairSpecular => SetIfDifferent(ref HairSpecular, value.InternalTriple),
|
||||
CustomizeParameterFlag.HairHighlight => SetIfDifferent(ref HairHighlight, value.InternalTriple),
|
||||
CustomizeParameterFlag.LeftEye => SetIfDifferent(ref LeftEye, value.InternalTriple),
|
||||
CustomizeParameterFlag.LeftScleraIntensity => SetIfDifferent(ref LeftScleraIntensity, value.Single),
|
||||
CustomizeParameterFlag.RightEye => SetIfDifferent(ref RightEye, value.InternalTriple),
|
||||
CustomizeParameterFlag.RightScleraIntensity => SetIfDifferent(ref RightScleraIntensity, value.Single),
|
||||
CustomizeParameterFlag.FeatureColor => SetIfDifferent(ref FeatureColor, value.InternalTriple),
|
||||
CustomizeParameterFlag.DecalColor => SetIfDifferent(ref DecalColor, value.InternalQuadruple),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => SetIfDifferent(ref FacePaintUvMultiplier, value.Single),
|
||||
|
|
@ -67,7 +73,7 @@ public struct CustomizeParameterData
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public readonly void Apply(ref CustomizeParameter parameters, CustomizeParameterFlag flags = CustomizeParameterExtensions.All)
|
||||
public readonly unsafe void Apply(ref CustomizeParameter parameters, CustomizeParameterFlag flags = CustomizeParameterExtensions.All)
|
||||
{
|
||||
parameters.SkinColor = (flags & (CustomizeParameterFlag.SkinDiffuse | CustomizeParameterFlag.MuscleTone)) switch
|
||||
{
|
||||
|
|
@ -77,20 +83,20 @@ public struct CustomizeParameterData
|
|||
_ => new CustomizeParameterValue(SkinDiffuse, MuscleTone).XivQuadruple,
|
||||
};
|
||||
|
||||
parameters.LeftColor = (flags & (CustomizeParameterFlag.LeftEye | CustomizeParameterFlag.FacePaintUvMultiplier)) switch
|
||||
parameters.LeftColor = (flags & (CustomizeParameterFlag.LeftEye | CustomizeParameterFlag.LeftScleraIntensity)) switch
|
||||
{
|
||||
0 => parameters.LeftColor,
|
||||
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(LeftEye, parameters.LeftColor.W).XivQuadruple,
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => parameters.LeftColor with { W = FacePaintUvMultiplier },
|
||||
_ => new CustomizeParameterValue(LeftEye, FacePaintUvMultiplier).XivQuadruple,
|
||||
CustomizeParameterFlag.LeftScleraIntensity => parameters.LeftColor with { W = LeftScleraIntensity },
|
||||
_ => new CustomizeParameterValue(LeftEye, LeftScleraIntensity).XivQuadruple,
|
||||
};
|
||||
|
||||
parameters.RightColor = (flags & (CustomizeParameterFlag.RightEye | CustomizeParameterFlag.FacePaintUvOffset)) switch
|
||||
parameters.RightColor = (flags & (CustomizeParameterFlag.RightEye | CustomizeParameterFlag.RightScleraIntensity)) switch
|
||||
{
|
||||
0 => parameters.RightColor,
|
||||
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(RightEye, parameters.RightColor.W).XivQuadruple,
|
||||
CustomizeParameterFlag.FacePaintUvOffset => parameters.RightColor with { W = FacePaintUvOffset },
|
||||
_ => new CustomizeParameterValue(RightEye, FacePaintUvOffset).XivQuadruple,
|
||||
CustomizeParameterFlag.RightScleraIntensity => parameters.RightColor with { W = RightScleraIntensity },
|
||||
_ => new CustomizeParameterValue(RightEye, RightScleraIntensity).XivQuadruple,
|
||||
};
|
||||
|
||||
if (flags.HasFlag(CustomizeParameterFlag.SkinSpecular))
|
||||
|
|
@ -101,6 +107,10 @@ public struct CustomizeParameterData
|
|||
parameters.HairFresnelValue0 = new CustomizeParameterValue(HairSpecular).XivTriple;
|
||||
if (flags.HasFlag(CustomizeParameterFlag.HairHighlight))
|
||||
parameters.MeshColor = new CustomizeParameterValue(HairHighlight).XivTriple;
|
||||
if (flags.HasFlag(CustomizeParameterFlag.FacePaintUvMultiplier))
|
||||
GetUvMultiplierWrite(ref parameters) = FacePaintUvMultiplier;
|
||||
if (flags.HasFlag(CustomizeParameterFlag.FacePaintUvOffset))
|
||||
GetUvOffsetWrite(ref parameters) = FacePaintUvOffset;
|
||||
if (flags.HasFlag(CustomizeParameterFlag.LipDiffuse))
|
||||
parameters.LipColor = new CustomizeParameterValue(LipDiffuse).XivQuadruple;
|
||||
if (flags.HasFlag(CustomizeParameterFlag.FeatureColor))
|
||||
|
|
@ -115,7 +125,7 @@ public struct CustomizeParameterData
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public readonly void ApplySingle(ref CustomizeParameter parameters, CustomizeParameterFlag flag)
|
||||
public readonly unsafe void ApplySingle(ref CustomizeParameter parameters, CustomizeParameterFlag flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
|
|
@ -150,19 +160,25 @@ public struct CustomizeParameterData
|
|||
parameters.OptionColor = new CustomizeParameterValue(FeatureColor).XivTriple;
|
||||
break;
|
||||
case CustomizeParameterFlag.FacePaintUvMultiplier:
|
||||
parameters.LeftColor.W = FacePaintUvMultiplier;
|
||||
GetUvMultiplierWrite(ref parameters) = FacePaintUvMultiplier;
|
||||
break;
|
||||
case CustomizeParameterFlag.FacePaintUvOffset:
|
||||
parameters.RightColor.W = FacePaintUvOffset;
|
||||
GetUvOffsetWrite(ref parameters) = FacePaintUvOffset;
|
||||
break;
|
||||
case CustomizeParameterFlag.LeftScleraIntensity:
|
||||
parameters.LeftColor.W = LeftScleraIntensity;
|
||||
break;
|
||||
case CustomizeParameterFlag.RightScleraIntensity:
|
||||
parameters.RightColor.W = RightScleraIntensity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static CustomizeParameterData FromParameters(in CustomizeParameter parameter, in DecalParameters decal)
|
||||
public static unsafe CustomizeParameterData FromParameters(in CustomizeParameter parameter, in DecalParameters decal)
|
||||
=> new()
|
||||
{
|
||||
FacePaintUvOffset = parameter.RightColor.W,
|
||||
FacePaintUvMultiplier = parameter.LeftColor.W,
|
||||
FacePaintUvOffset = GetUvOffset(parameter),
|
||||
FacePaintUvMultiplier = GetUvMultiplier(parameter),
|
||||
MuscleTone = parameter.SkinColor.W,
|
||||
SkinDiffuse = new CustomizeParameterValue(parameter.SkinColor).InternalTriple,
|
||||
SkinSpecular = new CustomizeParameterValue(parameter.SkinFresnelValue0).InternalTriple,
|
||||
|
|
@ -171,12 +187,14 @@ public struct CustomizeParameterData
|
|||
HairSpecular = new CustomizeParameterValue(parameter.HairFresnelValue0).InternalTriple,
|
||||
HairHighlight = new CustomizeParameterValue(parameter.MeshColor).InternalTriple,
|
||||
LeftEye = new CustomizeParameterValue(parameter.LeftColor).InternalTriple,
|
||||
LeftScleraIntensity = new CustomizeParameterValue(parameter.LeftColor.W).Single,
|
||||
RightEye = new CustomizeParameterValue(parameter.RightColor).InternalTriple,
|
||||
RightScleraIntensity = new CustomizeParameterValue(parameter.RightColor.W).Single,
|
||||
FeatureColor = new CustomizeParameterValue(parameter.OptionColor).InternalTriple,
|
||||
DecalColor = FromParameter(decal),
|
||||
};
|
||||
|
||||
public static CustomizeParameterValue FromParameter(in CustomizeParameter parameter, CustomizeParameterFlag flag)
|
||||
public static unsafe CustomizeParameterValue FromParameter(in CustomizeParameter parameter, CustomizeParameterFlag flag)
|
||||
=> flag switch
|
||||
{
|
||||
CustomizeParameterFlag.SkinDiffuse => new CustomizeParameterValue(parameter.SkinColor),
|
||||
|
|
@ -189,8 +207,8 @@ public struct CustomizeParameterData
|
|||
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(parameter.LeftColor),
|
||||
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(parameter.RightColor),
|
||||
CustomizeParameterFlag.FeatureColor => new CustomizeParameterValue(parameter.OptionColor),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => new CustomizeParameterValue(parameter.LeftColor.W),
|
||||
CustomizeParameterFlag.FacePaintUvOffset => new CustomizeParameterValue(parameter.RightColor.W),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => new CustomizeParameterValue(GetUvMultiplier(parameter)),
|
||||
CustomizeParameterFlag.FacePaintUvOffset => new CustomizeParameterValue(GetUvOffset(parameter)),
|
||||
_ => CustomizeParameterValue.Zero,
|
||||
};
|
||||
|
||||
|
|
@ -223,4 +241,41 @@ public struct CustomizeParameterData
|
|||
val = @new;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static unsafe float GetUvOffset(in CustomizeParameter parameter)
|
||||
{
|
||||
// TODO CS Update
|
||||
fixed (CustomizeParameter* ptr = ¶meter)
|
||||
{
|
||||
return ((float*)ptr)[23];
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe ref float GetUvOffsetWrite(ref CustomizeParameter parameter)
|
||||
{
|
||||
// TODO CS Update
|
||||
fixed (CustomizeParameter* ptr = ¶meter)
|
||||
{
|
||||
return ref ((float*)ptr)[23];
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe float GetUvMultiplier(in CustomizeParameter parameter)
|
||||
{
|
||||
// TODO CS Update
|
||||
fixed (CustomizeParameter* ptr = ¶meter)
|
||||
{
|
||||
return ((float*)ptr)[15];
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe ref float GetUvMultiplierWrite(ref CustomizeParameter parameter)
|
||||
{
|
||||
// TODO CS Update
|
||||
fixed (CustomizeParameter* ptr = ¶meter)
|
||||
{
|
||||
return ref ((float*)ptr)[15];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,24 @@ public enum CustomizeParameterFlag : ushort
|
|||
FacePaintUvMultiplier = 0x0400,
|
||||
FacePaintUvOffset = 0x0800,
|
||||
DecalColor = 0x1000,
|
||||
LeftScleraIntensity = 0x2000,
|
||||
RightScleraIntensity = 0x4000,
|
||||
}
|
||||
|
||||
public static class CustomizeParameterExtensions
|
||||
{
|
||||
public const CustomizeParameterFlag All = (CustomizeParameterFlag)0x1FFF;
|
||||
// Speculars are not available anymore.
|
||||
public const CustomizeParameterFlag All = (CustomizeParameterFlag)0x1FDB;
|
||||
|
||||
public const CustomizeParameterFlag RgbTriples = All
|
||||
& ~(RgbaQuadruples | Percentages | Values);
|
||||
|
||||
public const CustomizeParameterFlag RgbaQuadruples = CustomizeParameterFlag.DecalColor | CustomizeParameterFlag.LipDiffuse;
|
||||
public const CustomizeParameterFlag Percentages = CustomizeParameterFlag.MuscleTone;
|
||||
|
||||
public const CustomizeParameterFlag Percentages = CustomizeParameterFlag.MuscleTone
|
||||
| CustomizeParameterFlag.LeftScleraIntensity
|
||||
| CustomizeParameterFlag.RightScleraIntensity;
|
||||
|
||||
public const CustomizeParameterFlag Values = CustomizeParameterFlag.FacePaintUvOffset | CustomizeParameterFlag.FacePaintUvMultiplier;
|
||||
|
||||
public static readonly IReadOnlyList<CustomizeParameterFlag> AllFlags = [.. Enum.GetValues<CustomizeParameterFlag>()];
|
||||
|
|
@ -60,6 +67,8 @@ public static class CustomizeParameterExtensions
|
|||
CustomizeParameterFlag.FacePaintUvMultiplier => "Multiplier for Face Paint",
|
||||
CustomizeParameterFlag.FacePaintUvOffset => "Offset of Face Paint",
|
||||
CustomizeParameterFlag.DecalColor => "Face Paint Color",
|
||||
CustomizeParameterFlag.LeftScleraIntensity => "Left Sclera Intensity",
|
||||
CustomizeParameterFlag.RightScleraIntensity => "Right Sclera Intensity",
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,22 +158,22 @@ public class EquipmentDrawer
|
|||
}
|
||||
}
|
||||
|
||||
public bool DrawAllStain(out StainId ret, bool locked)
|
||||
public bool DrawAllStain(out StainIds ret, bool locked)
|
||||
{
|
||||
using var disabled = ImRaii.Disabled(locked);
|
||||
var change = _stainCombo.Draw("Dye All Slots", Stain.None.RgbaColor, string.Empty, false, false, MouseWheelType.None);
|
||||
ret = Stain.None.RowIndex;
|
||||
ret = StainIds.None;
|
||||
if (change)
|
||||
if (_stainData.TryGetValue(_stainCombo.CurrentSelection.Key, out var stain))
|
||||
ret = stain.RowIndex;
|
||||
ret = StainIds.All(stain.RowIndex);
|
||||
else if (_stainCombo.CurrentSelection.Key == Stain.None.RowIndex)
|
||||
ret = Stain.None.RowIndex;
|
||||
ret = StainIds.None;
|
||||
|
||||
if (!locked)
|
||||
{
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _config.DeleteDesignModifier.IsActive())
|
||||
{
|
||||
ret = Stain.None.RowIndex;
|
||||
ret = StainIds.None;
|
||||
change = true;
|
||||
}
|
||||
|
||||
|
|
@ -420,7 +420,7 @@ public class EquipmentDrawer
|
|||
|
||||
private void DrawBonusItemNormal(in BonusDrawData bonusDrawData)
|
||||
{
|
||||
ImGui.Dummy(_iconSize with { Y = ImUtf8.FrameHeight });
|
||||
bonusDrawData.CurrentItem.DrawIcon(_textures, _iconSize, bonusDrawData.Slot);
|
||||
var right = ImGui.IsItemClicked(ImGuiMouseButton.Right);
|
||||
var left = ImGui.IsItemClicked(ImGuiMouseButton.Left);
|
||||
ImGui.SameLine();
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
|
||||
private void DrawButton(MaterialValueIndex index)
|
||||
{
|
||||
// TODO fix when working
|
||||
return;
|
||||
if (!config.UseAdvancedDyes)
|
||||
return;
|
||||
|
||||
|
|
@ -193,11 +195,11 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
DrawWindow(textures);
|
||||
}
|
||||
|
||||
private void DrawTable(MaterialValueIndex materialIndex, in LegacyColorTable table)
|
||||
private void DrawTable(MaterialValueIndex materialIndex, in ColorTable table)
|
||||
{
|
||||
using var disabled = ImRaii.Disabled(_state.IsLocked);
|
||||
_anyChanged = false;
|
||||
for (byte i = 0; i < LegacyColorTable.NumUsedRows; ++i)
|
||||
for (byte i = 0; i < ColorTable.NumUsedRows; ++i)
|
||||
{
|
||||
var index = materialIndex with { RowIndex = i };
|
||||
ref var row = ref table[i];
|
||||
|
|
@ -208,7 +210,7 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
DrawAllRow(materialIndex, table);
|
||||
}
|
||||
|
||||
private void DrawAllRow(MaterialValueIndex materialIndex, in LegacyColorTable table)
|
||||
private void DrawAllRow(MaterialValueIndex materialIndex, in ColorTable table)
|
||||
{
|
||||
using var id = ImRaii.PushId(100);
|
||||
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||
|
|
@ -245,11 +247,11 @@ public sealed unsafe class AdvancedDyePopup(
|
|||
ImGui.SameLine(0, spacing);
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.UndoAlt.ToIconString(), buttonSize, "Reset this table to game state.", !_anyChanged,
|
||||
true))
|
||||
for (byte i = 0; i < LegacyColorTable.NumUsedRows; ++i)
|
||||
for (byte i = 0; i < ColorTable.NumUsedRows; ++i)
|
||||
stateManager.ResetMaterialValue(_state, materialIndex with { RowIndex = i }, ApplySettings.Game);
|
||||
}
|
||||
|
||||
private void DrawRow(ref LegacyColorTable.Row row, MaterialValueIndex index, in LegacyColorTable table)
|
||||
private void DrawRow(ref ColorTable.Row row, MaterialValueIndex index, in ColorTable table)
|
||||
{
|
||||
using var id = ImRaii.PushId(index.RowIndex);
|
||||
var changed = _state.Materials.TryGetValue(index, out var value);
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ namespace Glamourer.Gui.Materials;
|
|||
public static class ColorRowClipboard
|
||||
{
|
||||
private static ColorRow _row;
|
||||
private static LegacyColorTable _table;
|
||||
private static ColorTable _table;
|
||||
|
||||
public static bool IsSet { get; private set; }
|
||||
|
||||
public static bool IsTableSet { get; private set; }
|
||||
|
||||
public static LegacyColorTable Table
|
||||
public static ColorTable Table
|
||||
{
|
||||
get => _table;
|
||||
set
|
||||
|
|
|
|||
|
|
@ -175,9 +175,9 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config)
|
|||
{
|
||||
_newRowIdx += 1;
|
||||
ImGui.SetNextItemWidth(ImGui.CalcTextSize("Row #0000").X);
|
||||
if (ImGui.DragInt("##Row", ref _newRowIdx, 0.01f, 1, LegacyColorTable.NumUsedRows, "Row #%i"))
|
||||
if (ImGui.DragInt("##Row", ref _newRowIdx, 0.01f, 1, ColorTable.NumUsedRows, "Row #%i"))
|
||||
{
|
||||
_newRowIdx = Math.Clamp(_newRowIdx, 1, LegacyColorTable.NumUsedRows);
|
||||
_newRowIdx = Math.Clamp(_newRowIdx, 1, ColorTable.NumUsedRows);
|
||||
_newKey = _newKey with { RowIndex = (byte)(_newRowIdx - 1) };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
using FFXIVClientStructs.FFXIV.Shader;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
|
|
@ -94,7 +95,8 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
|
|||
|
||||
foreach (var type in Enum.GetValues<CustomizeIndex>())
|
||||
{
|
||||
PrintRow(type.ToDefaultName(), state.BaseData.Customize[type].Value, state.ModelData.Customize[type].Value, state.Sources[type]);
|
||||
PrintRow(type.ToDefaultName(), state.BaseData.Customize[type].Value, state.ModelData.Customize[type].Value,
|
||||
state.Sources[type]);
|
||||
ImGui.TableNextRow();
|
||||
}
|
||||
|
||||
|
|
|
|||
135
Glamourer/Gui/Tabs/DebugTab/AdvancedCustomizationDrawer.cs
Normal file
135
Glamourer/Gui/Tabs/DebugTab/AdvancedCustomizationDrawer.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Text;
|
||||
using Penumbra.GameData.Gui.Debug;
|
||||
|
||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||
|
||||
public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDataDrawer
|
||||
{
|
||||
public string Label
|
||||
=> "Advanced Customizations";
|
||||
|
||||
public bool Disabled
|
||||
=> false;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var (player, data) = objects.PlayerData;
|
||||
if (!data.Valid)
|
||||
{
|
||||
ImUtf8.Text("Invalid player."u8);
|
||||
return;
|
||||
}
|
||||
|
||||
var model = data.Objects[0].Model;
|
||||
if (!model.IsHuman)
|
||||
{
|
||||
ImUtf8.Text("Invalid model."u8);
|
||||
return;
|
||||
}
|
||||
|
||||
DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0);
|
||||
DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1);
|
||||
DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2);
|
||||
DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3);
|
||||
}
|
||||
|
||||
|
||||
private static void DrawCBuffer(ReadOnlySpan<byte> label, ConstantBuffer* cBuffer, int type)
|
||||
{
|
||||
using var tree = ImUtf8.TreeNode(label);
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
if (cBuffer == null)
|
||||
{
|
||||
ImUtf8.Text("Invalid CBuffer."u8);
|
||||
return;
|
||||
}
|
||||
|
||||
ImUtf8.Text($"{cBuffer->ByteSize / 4}");
|
||||
ImUtf8.Text($"{cBuffer->Flags}");
|
||||
ImUtf8.Text($"0x{(ulong)cBuffer:X}");
|
||||
var parameters = (float*)cBuffer->UnsafeSourcePointer;
|
||||
if (parameters == null)
|
||||
{
|
||||
ImUtf8.Text("No Parameters."u8);
|
||||
return;
|
||||
}
|
||||
|
||||
var start = parameters;
|
||||
using (ImUtf8.Group())
|
||||
{
|
||||
for (var end = start + cBuffer->ByteSize / 4; parameters < end; parameters += 2)
|
||||
DrawParameters(parameters, type, (int)(parameters - start));
|
||||
}
|
||||
|
||||
ImGui.SameLine(0, 50 * ImUtf8.GlobalScale);
|
||||
parameters = start + 1;
|
||||
using (ImUtf8.Group())
|
||||
{
|
||||
for (var end = start + cBuffer->ByteSize / 4; parameters < end; parameters += 2)
|
||||
DrawParameters(parameters, type, (int)(parameters - start));
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawParameters(float* param, int type, int idx)
|
||||
{
|
||||
using var id = ImUtf8.PushId((nint)param);
|
||||
ImUtf8.TextFrameAligned($"{idx:D2}: ");
|
||||
ImUtf8.SameLineInner();
|
||||
ImGui.SetNextItemWidth(200 * ImUtf8.GlobalScale);
|
||||
if (TryGetKnown(type, idx, out var known))
|
||||
{
|
||||
ImUtf8.DragScalar(known, ref *param, float.MinValue, float.MaxValue, 0.01f);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, ImGui.GetColorU32(ImGuiCol.TextDisabled));
|
||||
ImUtf8.DragScalar($"+0x{idx * 4:X2}", ref *param, float.MinValue, float.MaxValue, 0.01f);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetKnown(int type, int idx, out ReadOnlySpan<byte> text)
|
||||
{
|
||||
if (type == 0)
|
||||
text = idx switch
|
||||
{
|
||||
0 => "Diffuse.R"u8,
|
||||
1 => "Diffuse.G"u8,
|
||||
2 => "Diffuse.B"u8,
|
||||
3 => "Muscle Tone"u8,
|
||||
8 => "Lipstick.R"u8,
|
||||
9 => "Lipstick.G"u8,
|
||||
10 => "Lipstick.B"u8,
|
||||
11 => "Lipstick.Opacity"u8,
|
||||
12 => "Hair.R"u8,
|
||||
13 => "Hair.G"u8,
|
||||
14 => "Hair.B"u8,
|
||||
15 => "Facepaint.Offset"u8,
|
||||
20 => "Highlight.R"u8,
|
||||
21 => "Highlight.G"u8,
|
||||
22 => "Highlight.B"u8,
|
||||
23 => "Facepaint.Multiplier"u8,
|
||||
24 => "LeftEye.R"u8,
|
||||
25 => "LeftEye.G"u8,
|
||||
26 => "LeftEye.B"u8,
|
||||
27 => "LeftSclera"u8,
|
||||
28 => "RightEye.R"u8,
|
||||
29 => "RightEye.G"u8,
|
||||
30 => "RightEye.B"u8,
|
||||
31 => "RightSclera"u8,
|
||||
32 => "Feature.R"u8,
|
||||
33 => "Feature.G"u8,
|
||||
34 => "Feature.B"u8,
|
||||
_ => [],
|
||||
};
|
||||
else
|
||||
text = [];
|
||||
|
||||
return text.Length > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,8 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
|||
provider.GetRequiredService<PenumbraPanel>(),
|
||||
provider.GetRequiredService<IpcTesterPanel>(),
|
||||
provider.GetRequiredService<DatFilePanel>(),
|
||||
provider.GetRequiredService<GlamourPlatePanel>()
|
||||
provider.GetRequiredService<GlamourPlatePanel>(),
|
||||
provider.GetRequiredService<AdvancedCustomizationDrawer>()
|
||||
);
|
||||
|
||||
public static DebugTabHeader CreateGameData(IServiceProvider provider)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Services;
|
||||
|
|
@ -12,23 +13,23 @@ using ImGuiClip = OtterGui.ImGuiClip;
|
|||
|
||||
namespace Glamourer.Gui.Tabs.UnlocksTab;
|
||||
|
||||
public class UnlockOverview
|
||||
public class UnlockOverview(
|
||||
ItemManager items,
|
||||
CustomizeService customizations,
|
||||
ItemUnlockManager itemUnlocks,
|
||||
CustomizeUnlockManager customizeUnlocks,
|
||||
PenumbraChangedItemTooltip tooltip,
|
||||
TextureService textures,
|
||||
CodeService codes,
|
||||
JobService jobs,
|
||||
FavoriteManager favorites)
|
||||
{
|
||||
private readonly ItemManager _items;
|
||||
private readonly ItemUnlockManager _itemUnlocks;
|
||||
private readonly CustomizeService _customizations;
|
||||
private readonly CustomizeUnlockManager _customizeUnlocks;
|
||||
private readonly PenumbraChangedItemTooltip _tooltip;
|
||||
private readonly TextureService _textures;
|
||||
private readonly CodeService _codes;
|
||||
private readonly JobService _jobs;
|
||||
private readonly FavoriteManager _favorites;
|
||||
|
||||
private static readonly Vector4 UnavailableTint = new(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
|
||||
private FullEquipType _selected1 = FullEquipType.Unknown;
|
||||
private SubRace _selected2 = SubRace.Unknown;
|
||||
private Gender _selected3 = Gender.Unknown;
|
||||
private BonusItemFlag _selected4 = BonusItemFlag.Unknown;
|
||||
|
||||
private void DrawSelector()
|
||||
{
|
||||
|
|
@ -38,7 +39,7 @@ public class UnlockOverview
|
|||
|
||||
foreach (var type in Enum.GetValues<FullEquipType>())
|
||||
{
|
||||
if (type.IsOffhandType() || !_items.ItemData.ByType.TryGetValue(type, out var items) || items.Count == 0)
|
||||
if (type.IsOffhandType() || !items.ItemData.ByType.TryGetValue(type, out var value) || value.Count == 0)
|
||||
continue;
|
||||
|
||||
if (ImGui.Selectable(type.ToName(), _selected1 == type))
|
||||
|
|
@ -46,12 +47,21 @@ public class UnlockOverview
|
|||
_selected1 = type;
|
||||
_selected2 = SubRace.Unknown;
|
||||
_selected3 = Gender.Unknown;
|
||||
_selected4 = BonusItemFlag.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.Selectable("Bonus Items", _selected4 == BonusItemFlag.Glasses))
|
||||
{
|
||||
_selected1 = FullEquipType.Unknown;
|
||||
_selected2 = SubRace.Unknown;
|
||||
_selected3 = Gender.Unknown;
|
||||
_selected4 = BonusItemFlag.Glasses;
|
||||
}
|
||||
|
||||
foreach (var (clan, gender) in CustomizeManager.AllSets())
|
||||
{
|
||||
if (_customizations.Manager.GetSet(clan, gender).HairStyles.Count == 0)
|
||||
if (customizations.Manager.GetSet(clan, gender).HairStyles.Count == 0)
|
||||
continue;
|
||||
|
||||
if (ImGui.Selectable($"{(gender is Gender.Male ? '♂' : '♀')} {clan.ToShortName()} Hair & Paint",
|
||||
|
|
@ -60,25 +70,11 @@ public class UnlockOverview
|
|||
_selected1 = FullEquipType.Unknown;
|
||||
_selected2 = clan;
|
||||
_selected3 = gender;
|
||||
_selected4 = BonusItemFlag.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnlockOverview(ItemManager items, CustomizeService customizations, ItemUnlockManager itemUnlocks,
|
||||
CustomizeUnlockManager customizeUnlocks, PenumbraChangedItemTooltip tooltip, TextureService textures, CodeService codes,
|
||||
JobService jobs, FavoriteManager favorites)
|
||||
{
|
||||
_items = items;
|
||||
_customizations = customizations;
|
||||
_itemUnlocks = itemUnlocks;
|
||||
_customizeUnlocks = customizeUnlocks;
|
||||
_tooltip = tooltip;
|
||||
_textures = textures;
|
||||
_codes = codes;
|
||||
_jobs = jobs;
|
||||
_favorites = favorites;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Border, ImGui.GetColorU32(ImGuiCol.TableBorderStrong));
|
||||
|
|
@ -97,11 +93,13 @@ public class UnlockOverview
|
|||
DrawItems();
|
||||
else if (_selected2 is not SubRace.Unknown && _selected3 is not Gender.Unknown)
|
||||
DrawCustomizations();
|
||||
else if (_selected4 is not BonusItemFlag.Unknown)
|
||||
DrawBonusItems();
|
||||
}
|
||||
|
||||
private void DrawCustomizations()
|
||||
{
|
||||
var set = _customizations.Manager.GetSet(_selected2, _selected3);
|
||||
var set = customizations.Manager.GetSet(_selected2, _selected3);
|
||||
|
||||
var spacing = IconSpacing;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
|
||||
|
|
@ -111,16 +109,16 @@ public class UnlockOverview
|
|||
var counter = 0;
|
||||
foreach (var customize in set.HairStyles.Concat(set.FacePaints))
|
||||
{
|
||||
if (!_customizeUnlocks.Unlockable.TryGetValue(customize, out var unlockData))
|
||||
if (!customizeUnlocks.Unlockable.TryGetValue(customize, out var unlockData))
|
||||
continue;
|
||||
|
||||
var unlocked = _customizeUnlocks.IsUnlocked(customize, out var time);
|
||||
var icon = _customizations.Manager.GetIcon(customize.IconId);
|
||||
var unlocked = customizeUnlocks.IsUnlocked(customize, out var time);
|
||||
var icon = customizations.Manager.GetIcon(customize.IconId);
|
||||
var hasIcon = icon.TryGetWrap(out var wrap, out _);
|
||||
ImGui.Image(wrap?.ImGuiHandle ?? icon.GetWrapOrEmpty().ImGuiHandle, iconSize, Vector2.Zero, Vector2.One,
|
||||
unlocked || _codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
|
||||
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
|
||||
|
||||
if (_favorites.Contains(_selected3, _selected2, customize.Index, customize.Value))
|
||||
if (favorites.Contains(_selected3, _selected2, customize.Index, customize.Value))
|
||||
ImGui.GetWindowDrawList().AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), ColorId.FavoriteStarOn.Value(),
|
||||
12 * ImGuiHelpers.GlobalScale, ImDrawFlags.RoundCornersAll, 6 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
|
|
@ -147,24 +145,90 @@ public class UnlockOverview
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawBonusItems()
|
||||
{
|
||||
var spacing = IconSpacing;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
|
||||
var iconSize = ImGuiHelpers.ScaledVector2(64);
|
||||
var iconsPerRow = IconsPerRow(iconSize.X, spacing.X);
|
||||
var numRows = (items.DictBonusItems.Count + iconsPerRow - 1) / iconsPerRow;
|
||||
var numVisibleRows = (int)(Math.Ceiling(ImGui.GetContentRegionAvail().Y / (iconSize.Y + spacing.Y)) + 0.5f) + 1;
|
||||
|
||||
var skips = ImGuiClip.GetNecessarySkips(iconSize.Y + spacing.Y);
|
||||
var start = skips * iconsPerRow;
|
||||
var end = Math.Min(numVisibleRows * iconsPerRow + skips * iconsPerRow, items.DictBonusItems.Count);
|
||||
var counter = 0;
|
||||
|
||||
foreach (var item in items.DictBonusItems.Values.Skip(start).Take(end - start))
|
||||
{
|
||||
DrawItem(item);
|
||||
if (counter != iconsPerRow - 1)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
++counter;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.GetCursorPosX() != 0)
|
||||
ImGui.NewLine();
|
||||
var remainder = numRows - numVisibleRows - skips;
|
||||
if (remainder > 0)
|
||||
ImGuiClip.DrawEndDummy(remainder, iconSize.Y + spacing.Y);
|
||||
|
||||
void DrawItem(BonusItem item)
|
||||
{
|
||||
// TODO check unlocks
|
||||
var unlocked = true;
|
||||
if (!textures.TryLoadIcon(item.Icon.Id, out var iconHandle))
|
||||
return;
|
||||
|
||||
var (icon, size) = (iconHandle.ImGuiHandle, new Vector2(iconHandle.Width, iconHandle.Height));
|
||||
|
||||
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One,
|
||||
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
|
||||
if (favorites.Contains(item))
|
||||
ImGui.GetWindowDrawList().AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), ColorId.FavoriteStarOn.Value(),
|
||||
2 * ImGuiHelpers.GlobalScale, ImDrawFlags.RoundCornersAll, 4 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
// TODO handle clicking
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
using var tt = ImRaii.Tooltip();
|
||||
if (size.X >= iconSize.X && size.Y >= iconSize.Y)
|
||||
ImGui.Image(icon, size);
|
||||
ImGui.TextUnformatted(item.Name);
|
||||
ImGui.TextUnformatted($"{item.Slot.ToName()}");
|
||||
ImGui.TextUnformatted($"{item.ModelId.Id}-{item.Variant.Id}");
|
||||
// TODO
|
||||
ImGui.TextUnformatted("Always Unlocked"); // : $"Unlocked on {time:g}" : "Not Unlocked.");
|
||||
// TODO
|
||||
//tooltip.CreateTooltip(item, string.Empty, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawItems()
|
||||
{
|
||||
if (!_items.ItemData.ByType.TryGetValue(_selected1, out var items))
|
||||
if (!items.ItemData.ByType.TryGetValue(_selected1, out var value))
|
||||
return;
|
||||
|
||||
var spacing = IconSpacing;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing);
|
||||
var iconSize = ImGuiHelpers.ScaledVector2(64);
|
||||
var iconsPerRow = IconsPerRow(iconSize.X, spacing.X);
|
||||
var numRows = (items.Count + iconsPerRow - 1) / iconsPerRow;
|
||||
var numRows = (value.Count + iconsPerRow - 1) / iconsPerRow;
|
||||
var numVisibleRows = (int)(Math.Ceiling(ImGui.GetContentRegionAvail().Y / (iconSize.Y + spacing.Y)) + 0.5f) + 1;
|
||||
|
||||
var skips = ImGuiClip.GetNecessarySkips(iconSize.Y + spacing.Y);
|
||||
var end = Math.Min(numVisibleRows * iconsPerRow + skips * iconsPerRow, items.Count);
|
||||
var end = Math.Min(numVisibleRows * iconsPerRow + skips * iconsPerRow, value.Count);
|
||||
var counter = 0;
|
||||
for (var idx = skips * iconsPerRow; idx < end; ++idx)
|
||||
{
|
||||
DrawItem(items[idx]);
|
||||
DrawItem(value[idx]);
|
||||
if (counter != iconsPerRow - 1)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
|
|
@ -185,23 +249,23 @@ public class UnlockOverview
|
|||
|
||||
void DrawItem(EquipItem item)
|
||||
{
|
||||
var unlocked = _itemUnlocks.IsUnlocked(item.Id, out var time);
|
||||
if (!_textures.TryLoadIcon(item.IconId.Id, out var iconHandle))
|
||||
var unlocked = itemUnlocks.IsUnlocked(item.Id, out var time);
|
||||
if (!textures.TryLoadIcon(item.IconId.Id, out var iconHandle))
|
||||
return;
|
||||
|
||||
var (icon, size) = (iconHandle.ImGuiHandle, new Vector2(iconHandle.Width, iconHandle.Height));
|
||||
|
||||
ImGui.Image(icon, iconSize, Vector2.Zero, Vector2.One,
|
||||
unlocked || _codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
|
||||
if (_favorites.Contains(item))
|
||||
unlocked || codes.Enabled(CodeService.CodeFlag.Shirts) ? Vector4.One : UnavailableTint);
|
||||
if (favorites.Contains(item))
|
||||
ImGui.GetWindowDrawList().AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), ColorId.FavoriteStarOn.Value(),
|
||||
2 * ImGuiHelpers.GlobalScale, ImDrawFlags.RoundCornersAll, 4 * ImGuiHelpers.GlobalScale);
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
Glamourer.Messager.Chat.Print(new SeStringBuilder().AddItemLink(item.ItemId.Id, false).BuiltString);
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state))
|
||||
_tooltip.ApplyItem(state, item);
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && tooltip.Player(out var state))
|
||||
tooltip.ApplyItem(state, item);
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
|
|
@ -213,7 +277,7 @@ public class UnlockOverview
|
|||
ImGui.TextUnformatted($"{item.Type.ToName()} ({slot.ToName()})");
|
||||
if (item.Type.ValidOffhand().IsOffhandType())
|
||||
ImGui.TextUnformatted(
|
||||
$"{item.Weapon()}{(_items.ItemData.TryGetValue(item.ItemId, EquipSlot.OffHand, out var offhand) ? $" | {offhand.Weapon()}" : string.Empty)}");
|
||||
$"{item.Weapon()}{(items.ItemData.TryGetValue(item.ItemId, EquipSlot.OffHand, out var offhand) ? $" | {offhand.Weapon()}" : string.Empty)}");
|
||||
else
|
||||
ImGui.TextUnformatted(slot is EquipSlot.MainHand ? $"{item.Weapon()}" : $"{item.Armor()}");
|
||||
ImGui.TextUnformatted(
|
||||
|
|
@ -221,17 +285,17 @@ public class UnlockOverview
|
|||
|
||||
if (item.Level.Value <= 1)
|
||||
{
|
||||
if (item.JobRestrictions.Id <= 1 || item.JobRestrictions.Id >= _jobs.AllJobGroups.Count)
|
||||
if (item.JobRestrictions.Id <= 1 || item.JobRestrictions.Id >= jobs.AllJobGroups.Count)
|
||||
ImGui.TextUnformatted("For Everyone");
|
||||
else
|
||||
ImGui.TextUnformatted($"For all {_jobs.AllJobGroups[item.JobRestrictions.Id].Name}");
|
||||
ImGui.TextUnformatted($"For all {jobs.AllJobGroups[item.JobRestrictions.Id].Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.JobRestrictions.Id <= 1 || item.JobRestrictions.Id >= _jobs.AllJobGroups.Count)
|
||||
if (item.JobRestrictions.Id <= 1 || item.JobRestrictions.Id >= jobs.AllJobGroups.Count)
|
||||
ImGui.TextUnformatted($"For Everyone of at least Level {item.Level}");
|
||||
else
|
||||
ImGui.TextUnformatted($"For all {_jobs.AllJobGroups[item.JobRestrictions.Id].Name} of at least Level {item.Level}");
|
||||
ImGui.TextUnformatted($"For all {jobs.AllJobGroups[item.JobRestrictions.Id].Name} of at least Level {item.Level}");
|
||||
}
|
||||
|
||||
if (item.Flags.HasFlag(ItemFlags.IsDyable1))
|
||||
|
|
@ -240,7 +304,7 @@ public class UnlockOverview
|
|||
ImGui.TextUnformatted("Tradable");
|
||||
if (item.Flags.HasFlag(ItemFlags.IsCrestWorthy))
|
||||
ImGui.TextUnformatted("Can apply Crest");
|
||||
_tooltip.CreateTooltip(item, string.Empty, false);
|
||||
tooltip.CreateTooltip(item, string.Empty, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,30 @@ public static class UiHelpers
|
|||
if (empty)
|
||||
{
|
||||
var (bgColor, tint) = isEmpty
|
||||
? (ImGui.GetColorU32(ImGuiCol.FrameBg), new Vector4(0.1f, 0.1f, 0.1f, 0.5f))
|
||||
: (ImGui.GetColorU32(ImGuiCol.FrameBgActive), new Vector4(0.3f, 0.3f, 0.3f, 0.8f));
|
||||
? (ImGui.GetColorU32(ImGuiCol.FrameBg), Vector4.One)
|
||||
: (ImGui.GetColorU32(ImGuiCol.FrameBgActive), new Vector4(0.3f, 0.3f, 0.3f, 1f));
|
||||
var pos = ImGui.GetCursorScreenPos();
|
||||
ImGui.GetWindowDrawList().AddRectFilled(pos, pos + size, bgColor, 5 * ImGuiHelpers.GlobalScale);
|
||||
if (ptr != nint.Zero)
|
||||
ImGui.Image(ptr, size, Vector2.Zero, Vector2.One, tint);
|
||||
else
|
||||
ImGui.Dummy(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiUtil.HoverIcon(ptr, textureSize, size);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawIcon(this BonusItem item, TextureService textures, Vector2 size, BonusItemFlag slot)
|
||||
{
|
||||
var isEmpty = item.ModelId.Id == 0;
|
||||
var (ptr, textureSize, empty) = textures.GetIcon(item, slot);
|
||||
if (empty)
|
||||
{
|
||||
var (bgColor, tint) = isEmpty
|
||||
? (ImGui.GetColorU32(ImGuiCol.FrameBg), Vector4.One)
|
||||
: (ImGui.GetColorU32(ImGuiCol.FrameBgActive), new Vector4(0.3f, 0.3f, 0.3f, 1f));
|
||||
var pos = ImGui.GetCursorScreenPos();
|
||||
ImGui.GetWindowDrawList().AddRectFilled(pos, pos + size, bgColor, 5 * ImGuiHelpers.GlobalScale);
|
||||
if (ptr != nint.Zero)
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ namespace Glamourer.Interop.Material;
|
|||
public unsafe class DirectXService(IFramework framework) : IService
|
||||
{
|
||||
private readonly object _lock = new();
|
||||
private readonly ConcurrentDictionary<nint, (DateTime Update, LegacyColorTable Table)> _textures = [];
|
||||
private readonly ConcurrentDictionary<nint, (DateTime Update, ColorTable Table)> _textures = [];
|
||||
|
||||
/// <summary> Generate a color table the way the game does inside the original texture, and release the original. </summary>
|
||||
/// <param name="original"> The original texture that will be replaced with a new one. </param>
|
||||
/// <param name="colorTable"> The input color table. </param>
|
||||
/// <returns> Success or failure. </returns>
|
||||
public bool ReplaceColorTable(Texture** original, in LegacyColorTable colorTable)
|
||||
public bool ReplaceColorTable(Texture** original, in ColorTable colorTable)
|
||||
{
|
||||
if (original == null)
|
||||
return false;
|
||||
|
|
@ -38,7 +38,7 @@ public unsafe class DirectXService(IFramework framework) : IService
|
|||
if (texture.IsInvalid)
|
||||
return false;
|
||||
|
||||
fixed (LegacyColorTable* ptr = &colorTable)
|
||||
fixed (ColorTable* ptr = &colorTable)
|
||||
{
|
||||
if (!texture.Texture->InitializeContents(ptr))
|
||||
return false;
|
||||
|
|
@ -51,7 +51,7 @@ public unsafe class DirectXService(IFramework framework) : IService
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetColorTable(Texture* texture, out LegacyColorTable table)
|
||||
public bool TryGetColorTable(Texture* texture, out ColorTable table)
|
||||
{
|
||||
if (_textures.TryGetValue((nint)texture, out var p) && framework.LastUpdateUTC == p.Update)
|
||||
{
|
||||
|
|
@ -73,7 +73,7 @@ public unsafe class DirectXService(IFramework framework) : IService
|
|||
/// <param name="texture"> A pointer to the internal texture struct containing the GPU handle. </param>
|
||||
/// <param name="table"> The returned color table. </param>
|
||||
/// <returns> Whether the table could be fetched. </returns>
|
||||
private static bool TextureColorTable(Texture* texture, out LegacyColorTable table)
|
||||
private static bool TextureColorTable(Texture* texture, out ColorTable table)
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
|
|
@ -114,7 +114,7 @@ public unsafe class DirectXService(IFramework framework) : IService
|
|||
}
|
||||
|
||||
/// <summary> Turn a mapped texture into a color table. </summary>
|
||||
private static LegacyColorTable GetTextureData(ID3D11Texture2D1 resource, MappedSubresource map)
|
||||
private static ColorTable GetTextureData(ID3D11Texture2D1 resource, MappedSubresource map)
|
||||
{
|
||||
var desc = resource.Description1;
|
||||
|
||||
|
|
@ -133,14 +133,14 @@ public unsafe class DirectXService(IFramework framework) : IService
|
|||
/// <param name="height"> The height of the texture. (Needs to be 16).</param>
|
||||
/// <param name="pitch"> The stride in the texture data. </param>
|
||||
/// <returns></returns>
|
||||
private static LegacyColorTable ReadTexture(nint data, int length, int height, int pitch)
|
||||
private static ColorTable ReadTexture(nint data, int length, int height, int pitch)
|
||||
{
|
||||
// Check that the data has sufficient dimension and size.
|
||||
var expectedSize = sizeof(Half) * MaterialService.TextureWidth * height * 4;
|
||||
if (length < expectedSize || sizeof(LegacyColorTable) != expectedSize || height != MaterialService.TextureHeight)
|
||||
if (length < expectedSize || sizeof(ColorTable) != expectedSize || height != MaterialService.TextureHeight)
|
||||
return default;
|
||||
|
||||
var ret = new LegacyColorTable();
|
||||
var ret = new ColorTable();
|
||||
var target = (byte*)&ret;
|
||||
// If the stride is the same as in the table, just copy.
|
||||
if (pitch == MaterialService.TextureWidth)
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
|||
private readonly DirectXService _directXService;
|
||||
|
||||
public MaterialValueIndex LastValueIndex { get; private set; } = MaterialValueIndex.Invalid;
|
||||
public LegacyColorTable LastOriginalColorTable { get; private set; }
|
||||
public ColorTable LastOriginalColorTable { get; private set; }
|
||||
private MaterialValueIndex _valueIndex = MaterialValueIndex.Invalid;
|
||||
private ObjectIndex _lastObjectIndex = ObjectIndex.AnyIndex;
|
||||
private ObjectIndex _objectIndex = ObjectIndex.AnyIndex;
|
||||
private LegacyColorTable _originalColorTable;
|
||||
private ColorTable _originalColorTable;
|
||||
|
||||
public LiveColorTablePreviewer(global::Penumbra.GameData.Interop.ObjectManager objects, IFramework framework, DirectXService directXService)
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
|||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < LegacyColorTable.NumUsedRows; ++i)
|
||||
for (var i = 0; i < ColorTable.NumUsedRows; ++i)
|
||||
{
|
||||
table[i].Diffuse = diffuse;
|
||||
table[i].Emissive = emissive;
|
||||
|
|
@ -92,7 +92,7 @@ public sealed unsafe class LiveColorTablePreviewer : IService, IDisposable
|
|||
_objectIndex = ObjectIndex.AnyIndex;
|
||||
}
|
||||
|
||||
public void OnHover(MaterialValueIndex index, ObjectIndex objectIndex, LegacyColorTable table)
|
||||
public void OnHover(MaterialValueIndex index, ObjectIndex objectIndex, ColorTable table)
|
||||
{
|
||||
if (_valueIndex.DrawObject is not MaterialValueIndex.DrawObjectType.Invalid)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
|||
|
||||
private void OnPrepareColorSet(CharacterBase* characterBase, MaterialResourceHandle* material, ref StainId stain, ref nint ret)
|
||||
{
|
||||
// TODO fix when working
|
||||
return;
|
||||
if (!_config.UseAdvancedDyes)
|
||||
return;
|
||||
|
||||
|
|
@ -76,7 +78,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 LegacyColorTable colorTable)
|
||||
ref ColorTable colorTable)
|
||||
{
|
||||
var deleteList = _deleteList.Value!;
|
||||
deleteList.Clear();
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ namespace Glamourer.Interop.Material;
|
|||
|
||||
public static unsafe class MaterialService
|
||||
{
|
||||
public const int TextureWidth = 4;
|
||||
public const int TextureHeight = LegacyColorTable.NumUsedRows;
|
||||
public const int MaterialsPerModel = 4;
|
||||
public const int TextureWidth = 8;
|
||||
public const int TextureHeight = ColorTable.NumUsedRows;
|
||||
public const int MaterialsPerModel = 10;
|
||||
|
||||
public static bool GenerateNewColorTable(in LegacyColorTable colorTable, out Texture* texture)
|
||||
public static bool GenerateNewColorTable(in ColorTable colorTable, out Texture* texture)
|
||||
{
|
||||
var textureSize = stackalloc int[2];
|
||||
textureSize[0] = TextureWidth;
|
||||
|
|
@ -24,7 +24,7 @@ public static unsafe class MaterialService
|
|||
if (texture == null)
|
||||
return false;
|
||||
|
||||
fixed (LegacyColorTable* ptr = &colorTable)
|
||||
fixed (ColorTable* ptr = &colorTable)
|
||||
{
|
||||
return texture->InitializeContents(ptr);
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ public static unsafe class MaterialService
|
|||
/// <param name="modelSlot"> The model slot. </param>
|
||||
/// <param name="materialSlot"> The material slot in the model. </param>
|
||||
/// <returns> A pointer to the color table or null. </returns>
|
||||
public static LegacyColorTable* GetMaterialColorTable(Model model, int modelSlot, byte materialSlot)
|
||||
public static ColorTable* GetMaterialColorTable(Model model, int modelSlot, byte materialSlot)
|
||||
{
|
||||
if (!model.IsCharacterBase)
|
||||
return null;
|
||||
|
|
@ -66,6 +66,6 @@ public static unsafe class MaterialService
|
|||
if (material == null || material->ColorTable == null)
|
||||
return null;
|
||||
|
||||
return (LegacyColorTable*)material->ColorTable;
|
||||
return (ColorTable*)material->ColorTable;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ public readonly record struct MaterialValueIndex(
|
|||
=> materialIndex < MaterialService.MaterialsPerModel;
|
||||
|
||||
public static bool ValidateRow(byte rowIndex)
|
||||
=> rowIndex < LegacyColorTable.NumUsedRows;
|
||||
=> rowIndex < ColorTable.NumUsedRows;
|
||||
|
||||
private static uint ToKey(DrawObjectType type, byte slotIndex, byte materialIndex, byte rowIndex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public struct ColorRow(Vector3 diffuse, Vector3 specular, Vector3 emissive, floa
|
|||
public float SpecularStrength = specularStrength;
|
||||
public float GlossStrength = glossStrength;
|
||||
|
||||
public ColorRow(in LegacyColorTable.Row row)
|
||||
public ColorRow(in ColorTable.Row row)
|
||||
: this(Root(row.Diffuse), Root(row.Specular), Root(row.Emissive), row.SpecularStrength, row.GlossStrength)
|
||||
{ }
|
||||
|
||||
|
|
@ -44,7 +44,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 LegacyColorTable.Row row)
|
||||
public readonly bool Apply(ref ColorTable.Row row)
|
||||
{
|
||||
var ret = false;
|
||||
var d = Square(Diffuse);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public sealed unsafe class PrepareColorSet
|
|||
}
|
||||
|
||||
public static bool TryGetColorTable(CharacterBase* characterBase, MaterialResourceHandle* material, StainIds stainIds,
|
||||
out LegacyColorTable table)
|
||||
out ColorTable table)
|
||||
{
|
||||
if (material->ColorTable == null)
|
||||
{
|
||||
|
|
@ -64,7 +64,7 @@ public sealed unsafe class PrepareColorSet
|
|||
return false;
|
||||
}
|
||||
|
||||
var newTable = *(LegacyColorTable*)material->ColorTable;
|
||||
var newTable = *(ColorTable*)material->ColorTable;
|
||||
// TODO
|
||||
//if (stainIds.Stain1.Id != 0 || stainIds.Stain2.Id != 0)
|
||||
// characterBase->ReadStainingTemplate(material, stainId.Id, (Half*)(&newTable));
|
||||
|
|
@ -73,7 +73,7 @@ public sealed unsafe class PrepareColorSet
|
|||
}
|
||||
|
||||
/// <summary> Assumes the actor is valid. </summary>
|
||||
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out LegacyColorTable table)
|
||||
public static bool TryGetColorTable(Actor actor, MaterialValueIndex index, out ColorTable table)
|
||||
{
|
||||
var idx = index.SlotIndex * MaterialService.MaterialsPerModel + index.MaterialIndex;
|
||||
if (!index.TryGetModel(actor, out var model))
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ public unsafe class WeaponService : IDisposable
|
|||
private readonly WeaponLoading _event;
|
||||
private readonly ThreadLocal<bool> _inUpdate = new(() => false);
|
||||
|
||||
|
||||
private readonly delegate* unmanaged[Stdcall]<DrawDataContainer*, uint, ulong, byte, byte, byte, byte, void>
|
||||
_original;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,21 @@ public sealed class TextureService(IUiBuilder uiBuilder, IDataManager dataManage
|
|||
: (nint.Zero, Vector2.Zero, true);
|
||||
}
|
||||
|
||||
public (nint, Vector2, bool) GetIcon(BonusItem item, BonusItemFlag slot)
|
||||
{
|
||||
if (item.Icon.Id != 0 && TryLoadIcon(item.Icon.Id, out var ret))
|
||||
return (ret.ImGuiHandle, new Vector2(ret.Width, ret.Height), false);
|
||||
|
||||
var idx = slot.ToIndex();
|
||||
if (idx == uint.MaxValue)
|
||||
return (nint.Zero, Vector2.Zero, true);
|
||||
|
||||
idx += 12;
|
||||
return idx < 13 && _slotIcons[idx] != null
|
||||
? (_slotIcons[idx]!.ImGuiHandle, new Vector2(_slotIcons[idx]!.Width, _slotIcons[idx]!.Height), true)
|
||||
: (nint.Zero, Vector2.Zero, true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
for (var i = 0; i < _slotIcons.Length; ++i)
|
||||
|
|
@ -34,9 +49,9 @@ public sealed class TextureService(IUiBuilder uiBuilder, IDataManager dataManage
|
|||
|
||||
private static IDalamudTextureWrap?[] CreateSlotIcons(IUiBuilder uiBuilder)
|
||||
{
|
||||
var ret = new IDalamudTextureWrap?[12];
|
||||
var ret = new IDalamudTextureWrap?[13];
|
||||
|
||||
using var uldWrapper = uiBuilder.LoadUld("ui/uld/ArmouryBoard.uld");
|
||||
using var uldWrapper = uiBuilder.LoadUld("ui/uld/Character.uld");
|
||||
|
||||
if (!uldWrapper.Valid)
|
||||
{
|
||||
|
|
@ -44,33 +59,37 @@ public sealed class TextureService(IUiBuilder uiBuilder, IDataManager dataManage
|
|||
return ret;
|
||||
}
|
||||
|
||||
SetIcon(EquipSlot.Head, 1);
|
||||
SetIcon(EquipSlot.Body, 2);
|
||||
SetIcon(EquipSlot.Hands, 3);
|
||||
SetIcon(EquipSlot.Legs, 5);
|
||||
SetIcon(EquipSlot.Feet, 6);
|
||||
SetIcon(EquipSlot.Ears, 8);
|
||||
SetIcon(EquipSlot.Neck, 9);
|
||||
SetIcon(EquipSlot.Wrists, 10);
|
||||
SetIcon(EquipSlot.RFinger, 11);
|
||||
SetIcon(EquipSlot.MainHand, 0);
|
||||
SetIcon(EquipSlot.OffHand, 7);
|
||||
SetIcon(EquipSlot.Head, 19);
|
||||
SetIcon(EquipSlot.Body, 20);
|
||||
SetIcon(EquipSlot.Hands, 21);
|
||||
SetIcon(EquipSlot.Legs, 23);
|
||||
SetIcon(EquipSlot.Feet, 24);
|
||||
SetIcon(EquipSlot.Ears, 25);
|
||||
SetIcon(EquipSlot.Neck, 26);
|
||||
SetIcon(EquipSlot.Wrists, 27);
|
||||
SetIcon(EquipSlot.RFinger, 28);
|
||||
SetIcon(EquipSlot.MainHand, 17);
|
||||
SetIcon(EquipSlot.OffHand, 18);
|
||||
Set(BonusItemFlag.Glasses.ToName(), (int) BonusItemFlag.Glasses.ToIndex() + 12, 55);
|
||||
ret[EquipSlot.LFinger.ToIndex()] = ret[EquipSlot.RFinger.ToIndex()];
|
||||
|
||||
return ret;
|
||||
|
||||
void SetIcon(EquipSlot slot, int index)
|
||||
void Set(string name, int slot, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret[slot.ToIndex()] = uldWrapper.LoadTexturePart("ui/uld/ArmouryBoard_hr1.tex", index)!;
|
||||
ret[slot] = uldWrapper.LoadTexturePart("ui/uld/Character_hr1.tex", index)!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Could not get empty slot texture for {slot.ToName()}, icon will be left empty. "
|
||||
Glamourer.Log.Error($"Could not get empty slot texture for {name}, icon will be left empty. "
|
||||
+ $"This may be because of incompatible mods affecting your character screen interface:\n{ex}");
|
||||
ret[slot.ToIndex()] = null;
|
||||
ret[slot] = null;
|
||||
}
|
||||
}
|
||||
|
||||
void SetIcon(EquipSlot slot, int index)
|
||||
=> Set(slot.ToName(), (int)slot.ToIndex(), index);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,6 +306,8 @@ public class StateApplier(
|
|||
|
||||
public unsafe void ChangeMaterialValue(ActorData data, MaterialValueIndex index, ColorRow? value, bool force)
|
||||
{
|
||||
// TODO fix when working
|
||||
return;
|
||||
if (!force && !_config.UseAdvancedDyes)
|
||||
return;
|
||||
|
||||
|
|
@ -338,6 +340,8 @@ public class StateApplier(
|
|||
|
||||
public unsafe void ChangeMaterialValues(ActorData data, in StateMaterialManager materials, bool force)
|
||||
{
|
||||
// TODO: fix when working
|
||||
return;
|
||||
if (!force && !_config.UseAdvancedDyes)
|
||||
return;
|
||||
|
||||
|
|
@ -383,6 +387,11 @@ public class StateApplier(
|
|||
ChangeCustomize(actors, state.ModelData.Customize);
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
ChangeArmor(actors, slot, state.ModelData.Armor(slot), !state.Sources[slot, false].IsIpc(), state.ModelData.IsHatVisible());
|
||||
foreach (var slot in BonusExtensions.AllFlags)
|
||||
{
|
||||
var item = state.ModelData.BonusItem(slot);
|
||||
ChangeBonusItem(actors, slot, item.ModelId, item.Variant);
|
||||
}
|
||||
|
||||
var mainhandActors = state.ModelData.MainhandType != state.BaseData.MainhandType ? actors.OnlyGPose() : actors;
|
||||
ChangeMainhand(mainhandActors, state.ModelData.Item(EquipSlot.MainHand), state.ModelData.Stain(EquipSlot.MainHand));
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public class StateEditor(
|
|||
var @new = state.ModelData.Parameters[flag];
|
||||
var actors = Applier.ChangeParameters(state, flag, settings.Source.RequiresChange());
|
||||
Glamourer.Log.Verbose(
|
||||
$"Set {flag} crest in state {state.Identifier.Incognito(null)} from {old} to {@new}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
$"Set {flag} in state {state.Identifier.Incognito(null)} from {old} to {@new}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
StateChanged.Invoke(StateChangeType.Parameter, settings.Source, state, actors, (old, @new, flag));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ public readonly record struct StateIndex(int Value) : IEqualityOperators<StateIn
|
|||
CustomizeParameterFlag.HairSpecular => new StateIndex(ParamHairSpecular),
|
||||
CustomizeParameterFlag.HairHighlight => new StateIndex(ParamHairHighlight),
|
||||
CustomizeParameterFlag.LeftEye => new StateIndex(ParamLeftEye),
|
||||
CustomizeParameterFlag.LeftScleraIntensity => new StateIndex(ParamLeftScleraIntensity),
|
||||
CustomizeParameterFlag.RightEye => new StateIndex(ParamRightEye),
|
||||
CustomizeParameterFlag.RightScleraIntensity => new StateIndex(ParamRightScleraIntensity),
|
||||
CustomizeParameterFlag.FeatureColor => new StateIndex(ParamFeatureColor),
|
||||
CustomizeParameterFlag.FacePaintUvMultiplier => new StateIndex(ParamFacePaintUvMultiplier),
|
||||
CustomizeParameterFlag.FacePaintUvOffset => new StateIndex(ParamFacePaintUvOffset),
|
||||
|
|
@ -199,8 +201,10 @@ public readonly record struct StateIndex(int Value) : IEqualityOperators<StateIn
|
|||
public const int ParamHairSpecular = ParamHairDiffuse + 1;
|
||||
public const int ParamHairHighlight = ParamHairSpecular + 1;
|
||||
public const int ParamLeftEye = ParamHairHighlight + 1;
|
||||
public const int ParamRightEye = ParamLeftEye + 1;
|
||||
public const int ParamFeatureColor = ParamRightEye + 1;
|
||||
public const int ParamLeftScleraIntensity = ParamLeftEye + 1;
|
||||
public const int ParamRightEye = ParamLeftScleraIntensity + 1;
|
||||
public const int ParamRightScleraIntensity = ParamRightEye + 1;
|
||||
public const int ParamFeatureColor = ParamRightScleraIntensity + 1;
|
||||
public const int ParamFacePaintUvMultiplier = ParamFeatureColor + 1;
|
||||
public const int ParamFacePaintUvOffset = ParamFacePaintUvMultiplier + 1;
|
||||
public const int ParamDecalColor = ParamFacePaintUvOffset + 1;
|
||||
|
|
@ -309,7 +313,9 @@ public readonly record struct StateIndex(int Value) : IEqualityOperators<StateIn
|
|||
ParamHairSpecular => CustomizeParameterFlag.HairSpecular,
|
||||
ParamHairHighlight => CustomizeParameterFlag.HairHighlight,
|
||||
ParamLeftEye => CustomizeParameterFlag.LeftEye,
|
||||
ParamLeftScleraIntensity => CustomizeParameterFlag.LeftScleraIntensity,
|
||||
ParamRightEye => CustomizeParameterFlag.RightEye,
|
||||
ParamRightScleraIntensity => CustomizeParameterFlag.RightScleraIntensity,
|
||||
ParamFeatureColor => CustomizeParameterFlag.FeatureColor,
|
||||
ParamFacePaintUvMultiplier => CustomizeParameterFlag.FacePaintUvMultiplier,
|
||||
ParamFacePaintUvOffset => CustomizeParameterFlag.FacePaintUvOffset,
|
||||
|
|
@ -320,103 +326,6 @@ public readonly record struct StateIndex(int Value) : IEqualityOperators<StateIn
|
|||
_ => -1,
|
||||
};
|
||||
|
||||
public object? GetValue(in DesignData data)
|
||||
{
|
||||
return Value switch
|
||||
{
|
||||
EquipHead => data.Item(EquipSlot.Head),
|
||||
EquipBody => data.Item(EquipSlot.Body),
|
||||
EquipHands => data.Item(EquipSlot.Hands),
|
||||
EquipLegs => data.Item(EquipSlot.Legs),
|
||||
EquipFeet => data.Item(EquipSlot.Feet),
|
||||
EquipEars => data.Item(EquipSlot.Ears),
|
||||
EquipNeck => data.Item(EquipSlot.Neck),
|
||||
EquipWrist => data.Item(EquipSlot.Wrists),
|
||||
EquipRFinger => data.Item(EquipSlot.RFinger),
|
||||
EquipLFinger => data.Item(EquipSlot.LFinger),
|
||||
EquipMainhand => data.Item(EquipSlot.MainHand),
|
||||
EquipOffhand => data.Item(EquipSlot.OffHand),
|
||||
|
||||
StainHead => data.Stain(EquipSlot.Head),
|
||||
StainBody => data.Stain(EquipSlot.Body),
|
||||
StainHands => data.Stain(EquipSlot.Hands),
|
||||
StainLegs => data.Stain(EquipSlot.Legs),
|
||||
StainFeet => data.Stain(EquipSlot.Feet),
|
||||
StainEars => data.Stain(EquipSlot.Ears),
|
||||
StainNeck => data.Stain(EquipSlot.Neck),
|
||||
StainWrist => data.Stain(EquipSlot.Wrists),
|
||||
StainRFinger => data.Stain(EquipSlot.RFinger),
|
||||
StainLFinger => data.Stain(EquipSlot.LFinger),
|
||||
StainMainhand => data.Stain(EquipSlot.MainHand),
|
||||
StainOffhand => data.Stain(EquipSlot.OffHand),
|
||||
|
||||
CustomizeRace => data.Customize[CustomizeIndex.Race],
|
||||
CustomizeGender => data.Customize[CustomizeIndex.Gender],
|
||||
CustomizeBodyType => data.Customize[CustomizeIndex.BodyType],
|
||||
CustomizeHeight => data.Customize[CustomizeIndex.Height],
|
||||
CustomizeClan => data.Customize[CustomizeIndex.Clan],
|
||||
CustomizeFace => data.Customize[CustomizeIndex.Face],
|
||||
CustomizeHairstyle => data.Customize[CustomizeIndex.Hairstyle],
|
||||
CustomizeHighlights => data.Customize[CustomizeIndex.Highlights],
|
||||
CustomizeSkinColor => data.Customize[CustomizeIndex.SkinColor],
|
||||
CustomizeEyeColorRight => data.Customize[CustomizeIndex.EyeColorRight],
|
||||
CustomizeHairColor => data.Customize[CustomizeIndex.HairColor],
|
||||
CustomizeHighlightsColor => data.Customize[CustomizeIndex.HighlightsColor],
|
||||
CustomizeFacialFeature1 => data.Customize[CustomizeIndex.FacialFeature1],
|
||||
CustomizeFacialFeature2 => data.Customize[CustomizeIndex.FacialFeature2],
|
||||
CustomizeFacialFeature3 => data.Customize[CustomizeIndex.FacialFeature3],
|
||||
CustomizeFacialFeature4 => data.Customize[CustomizeIndex.FacialFeature4],
|
||||
CustomizeFacialFeature5 => data.Customize[CustomizeIndex.FacialFeature5],
|
||||
CustomizeFacialFeature6 => data.Customize[CustomizeIndex.FacialFeature6],
|
||||
CustomizeFacialFeature7 => data.Customize[CustomizeIndex.FacialFeature7],
|
||||
CustomizeLegacyTattoo => data.Customize[CustomizeIndex.LegacyTattoo],
|
||||
CustomizeTattooColor => data.Customize[CustomizeIndex.TattooColor],
|
||||
CustomizeEyebrows => data.Customize[CustomizeIndex.Eyebrows],
|
||||
CustomizeEyeColorLeft => data.Customize[CustomizeIndex.EyeColorLeft],
|
||||
CustomizeEyeShape => data.Customize[CustomizeIndex.EyeShape],
|
||||
CustomizeSmallIris => data.Customize[CustomizeIndex.SmallIris],
|
||||
CustomizeNose => data.Customize[CustomizeIndex.Nose],
|
||||
CustomizeJaw => data.Customize[CustomizeIndex.Jaw],
|
||||
CustomizeMouth => data.Customize[CustomizeIndex.Mouth],
|
||||
CustomizeLipstick => data.Customize[CustomizeIndex.Lipstick],
|
||||
CustomizeLipColor => data.Customize[CustomizeIndex.LipColor],
|
||||
CustomizeMuscleMass => data.Customize[CustomizeIndex.MuscleMass],
|
||||
CustomizeTailShape => data.Customize[CustomizeIndex.TailShape],
|
||||
CustomizeBustSize => data.Customize[CustomizeIndex.BustSize],
|
||||
CustomizeFacePaint => data.Customize[CustomizeIndex.FacePaint],
|
||||
CustomizeFacePaintReversed => data.Customize[CustomizeIndex.FacePaintReversed],
|
||||
CustomizeFacePaintColor => data.Customize[CustomizeIndex.FacePaintColor],
|
||||
|
||||
MetaWetness => data.GetMeta(MetaIndex.Wetness),
|
||||
MetaHatState => data.GetMeta(MetaIndex.HatState),
|
||||
MetaVisorState => data.GetMeta(MetaIndex.VisorState),
|
||||
MetaWeaponState => data.GetMeta(MetaIndex.WeaponState),
|
||||
MetaModelId => data.ModelId,
|
||||
|
||||
CrestHead => data.Crest(CrestFlag.Head),
|
||||
CrestBody => data.Crest(CrestFlag.Body),
|
||||
CrestOffhand => data.Crest(CrestFlag.OffHand),
|
||||
|
||||
ParamSkinDiffuse => data.Parameters[CustomizeParameterFlag.SkinDiffuse],
|
||||
ParamMuscleTone => data.Parameters[CustomizeParameterFlag.MuscleTone],
|
||||
ParamSkinSpecular => data.Parameters[CustomizeParameterFlag.SkinSpecular],
|
||||
ParamLipDiffuse => data.Parameters[CustomizeParameterFlag.LipDiffuse],
|
||||
ParamHairDiffuse => data.Parameters[CustomizeParameterFlag.HairDiffuse],
|
||||
ParamHairSpecular => data.Parameters[CustomizeParameterFlag.HairSpecular],
|
||||
ParamHairHighlight => data.Parameters[CustomizeParameterFlag.HairHighlight],
|
||||
ParamLeftEye => data.Parameters[CustomizeParameterFlag.LeftEye],
|
||||
ParamRightEye => data.Parameters[CustomizeParameterFlag.RightEye],
|
||||
ParamFeatureColor => data.Parameters[CustomizeParameterFlag.FeatureColor],
|
||||
ParamFacePaintUvMultiplier => data.Parameters[CustomizeParameterFlag.FacePaintUvMultiplier],
|
||||
ParamFacePaintUvOffset => data.Parameters[CustomizeParameterFlag.FacePaintUvOffset],
|
||||
ParamDecalColor => data.Parameters[CustomizeParameterFlag.DecalColor],
|
||||
|
||||
BonusItemGlasses => data.BonusItem(BonusItemFlag.Glasses),
|
||||
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetName(EquipFlag flag)
|
||||
{
|
||||
var slot = flag.ToSlot(out var stain);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8928015f38f951810a9a6fbb44fb4a0cb9a712dd
|
||||
Subproject commit 491b61916951b7192bb2354d725363340ea153b5
|
||||
Loading…
Add table
Add a link
Reference in a new issue