mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-29 20:03:45 +01:00
303 lines
16 KiB
C#
303 lines
16 KiB
C#
using FFXIVClientStructs.FFXIV.Shader;
|
|
|
|
namespace Glamourer.GameData;
|
|
|
|
public struct CustomizeParameterData
|
|
{
|
|
public Vector4 DecalColor;
|
|
public Vector4 LipDiffuse;
|
|
public Vector3 SkinDiffuse;
|
|
public Vector3 SkinSpecular;
|
|
public Vector3 HairDiffuse;
|
|
public Vector3 HairSpecular;
|
|
public Vector3 HairHighlight;
|
|
public Vector3 LeftEye;
|
|
public float LeftLimbalIntensity;
|
|
public Vector3 RightEye;
|
|
public float RightLimbalIntensity;
|
|
public Vector3 FeatureColor;
|
|
public float FacePaintUvMultiplier;
|
|
public float FacePaintUvOffset;
|
|
public float MuscleTone;
|
|
|
|
public CustomizeParameterValue this[CustomizeParameterFlag flag]
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
readonly get
|
|
{
|
|
return flag switch
|
|
{
|
|
CustomizeParameterFlag.SkinDiffuse => new CustomizeParameterValue(SkinDiffuse),
|
|
CustomizeParameterFlag.MuscleTone => new CustomizeParameterValue(MuscleTone),
|
|
CustomizeParameterFlag.SkinSpecular => new CustomizeParameterValue(SkinSpecular),
|
|
CustomizeParameterFlag.LipDiffuse => new CustomizeParameterValue(LipDiffuse),
|
|
CustomizeParameterFlag.HairDiffuse => new CustomizeParameterValue(HairDiffuse),
|
|
CustomizeParameterFlag.HairSpecular => new CustomizeParameterValue(HairSpecular),
|
|
CustomizeParameterFlag.HairHighlight => new CustomizeParameterValue(HairHighlight),
|
|
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(LeftEye),
|
|
CustomizeParameterFlag.LeftLimbalIntensity => new CustomizeParameterValue(LeftLimbalIntensity),
|
|
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(RightEye),
|
|
CustomizeParameterFlag.RightLimbalIntensity => new CustomizeParameterValue(RightLimbalIntensity),
|
|
CustomizeParameterFlag.FeatureColor => new CustomizeParameterValue(FeatureColor),
|
|
CustomizeParameterFlag.DecalColor => new CustomizeParameterValue(DecalColor),
|
|
CustomizeParameterFlag.FacePaintUvMultiplier => new CustomizeParameterValue(FacePaintUvMultiplier),
|
|
CustomizeParameterFlag.FacePaintUvOffset => new CustomizeParameterValue(FacePaintUvOffset),
|
|
_ => CustomizeParameterValue.Zero,
|
|
};
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
set => Set(flag, value);
|
|
}
|
|
|
|
public bool Set(CustomizeParameterFlag flag, CustomizeParameterValue value)
|
|
{
|
|
return flag switch
|
|
{
|
|
CustomizeParameterFlag.SkinDiffuse => SetIfDifferent(ref SkinDiffuse, value.InternalTriple),
|
|
CustomizeParameterFlag.MuscleTone => SetIfDifferent(ref MuscleTone, value.Single),
|
|
CustomizeParameterFlag.SkinSpecular => SetIfDifferent(ref SkinSpecular, value.InternalTriple),
|
|
CustomizeParameterFlag.LipDiffuse => SetIfDifferent(ref LipDiffuse, value.InternalQuadruple),
|
|
CustomizeParameterFlag.HairDiffuse => SetIfDifferent(ref HairDiffuse, value.InternalTriple),
|
|
CustomizeParameterFlag.HairSpecular => SetIfDifferent(ref HairSpecular, value.InternalTriple),
|
|
CustomizeParameterFlag.HairHighlight => SetIfDifferent(ref HairHighlight, value.InternalTriple),
|
|
CustomizeParameterFlag.LeftEye => SetIfDifferent(ref LeftEye, value.InternalTriple),
|
|
CustomizeParameterFlag.LeftLimbalIntensity => SetIfDifferent(ref LeftLimbalIntensity, value.Single),
|
|
CustomizeParameterFlag.RightEye => SetIfDifferent(ref RightEye, value.InternalTriple),
|
|
CustomizeParameterFlag.RightLimbalIntensity => SetIfDifferent(ref RightLimbalIntensity, value.Single),
|
|
CustomizeParameterFlag.FeatureColor => SetIfDifferent(ref FeatureColor, value.InternalTriple),
|
|
CustomizeParameterFlag.DecalColor => SetIfDifferent(ref DecalColor, value.InternalQuadruple),
|
|
CustomizeParameterFlag.FacePaintUvMultiplier => SetIfDifferent(ref FacePaintUvMultiplier, value.Single),
|
|
CustomizeParameterFlag.FacePaintUvOffset => SetIfDifferent(ref FacePaintUvOffset, value.Single),
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
public readonly void Apply(ref CustomizeParameter parameters, CustomizeParameterFlag flags = CustomizeParameterExtensions.All)
|
|
{
|
|
parameters.SkinColor = (flags & (CustomizeParameterFlag.SkinDiffuse | CustomizeParameterFlag.MuscleTone)) switch
|
|
{
|
|
0 => parameters.SkinColor,
|
|
CustomizeParameterFlag.SkinDiffuse => new CustomizeParameterValue(SkinDiffuse, parameters.SkinColor.W).XivQuadruple,
|
|
CustomizeParameterFlag.MuscleTone => parameters.SkinColor with { W = MuscleTone },
|
|
_ => new CustomizeParameterValue(SkinDiffuse, MuscleTone).XivQuadruple,
|
|
};
|
|
|
|
parameters.LeftColor = (flags & (CustomizeParameterFlag.LeftEye | CustomizeParameterFlag.LeftLimbalIntensity)) switch
|
|
{
|
|
0 => parameters.LeftColor,
|
|
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(LeftEye, parameters.LeftColor.W).XivQuadruple,
|
|
CustomizeParameterFlag.LeftLimbalIntensity => parameters.LeftColor with { W = LeftLimbalIntensity },
|
|
_ => new CustomizeParameterValue(LeftEye, LeftLimbalIntensity).XivQuadruple,
|
|
};
|
|
|
|
parameters.RightColor = (flags & (CustomizeParameterFlag.RightEye | CustomizeParameterFlag.RightLimbalIntensity)) switch
|
|
{
|
|
0 => parameters.RightColor,
|
|
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(RightEye, parameters.RightColor.W).XivQuadruple,
|
|
CustomizeParameterFlag.RightLimbalIntensity => parameters.RightColor with { W = RightLimbalIntensity },
|
|
_ => new CustomizeParameterValue(RightEye, RightLimbalIntensity).XivQuadruple,
|
|
};
|
|
|
|
if (flags.HasFlag(CustomizeParameterFlag.SkinSpecular))
|
|
parameters.SkinFresnelValue0 = new CustomizeParameterValue(SkinSpecular).XivQuadruple;
|
|
if (flags.HasFlag(CustomizeParameterFlag.HairDiffuse))
|
|
{
|
|
// Vector3 is 0x10 byte for some reason.
|
|
var triple = new CustomizeParameterValue(HairDiffuse).XivTriple;
|
|
parameters.MainColor.X = triple.X;
|
|
parameters.MainColor.Y = triple.Y;
|
|
parameters.MainColor.Z = triple.Z;
|
|
}
|
|
|
|
if (flags.HasFlag(CustomizeParameterFlag.HairSpecular))
|
|
parameters.HairFresnelValue0 = new CustomizeParameterValue(HairSpecular).XivTriple;
|
|
if (flags.HasFlag(CustomizeParameterFlag.HairHighlight))
|
|
{
|
|
// Vector3 is 0x10 byte for some reason.
|
|
var triple = new CustomizeParameterValue(HairHighlight).XivTriple;
|
|
parameters.MeshColor.X = triple.X;
|
|
parameters.MeshColor.Y = triple.Y;
|
|
parameters.MeshColor.Z = triple.Z;
|
|
}
|
|
|
|
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))
|
|
parameters.OptionColor = new CustomizeParameterValue(FeatureColor).XivTriple;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
public readonly void Apply(ref DecalParameters parameters, CustomizeParameterFlag flags = CustomizeParameterExtensions.All)
|
|
{
|
|
if (flags.HasFlag(CustomizeParameterFlag.DecalColor))
|
|
parameters.Color = new CustomizeParameterValue(DecalColor).XivQuadruple;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
public readonly void ApplySingle(ref CustomizeParameter parameters, CustomizeParameterFlag flag)
|
|
{
|
|
switch (flag)
|
|
{
|
|
case CustomizeParameterFlag.SkinDiffuse:
|
|
parameters.SkinColor = new CustomizeParameterValue(SkinDiffuse, parameters.SkinColor.W).XivQuadruple;
|
|
break;
|
|
case CustomizeParameterFlag.MuscleTone:
|
|
parameters.SkinColor.W = MuscleTone;
|
|
break;
|
|
case CustomizeParameterFlag.SkinSpecular:
|
|
parameters.SkinFresnelValue0 = new CustomizeParameterValue(SkinSpecular).XivQuadruple;
|
|
break;
|
|
case CustomizeParameterFlag.LipDiffuse:
|
|
parameters.LipColor = new CustomizeParameterValue(LipDiffuse).XivQuadruple;
|
|
break;
|
|
case CustomizeParameterFlag.HairDiffuse:
|
|
// Vector3 is 0x10 byte for some reason.
|
|
var triple1 = new CustomizeParameterValue(HairDiffuse).XivTriple;
|
|
parameters.MainColor.X = triple1.X;
|
|
parameters.MainColor.Y = triple1.Y;
|
|
parameters.MainColor.Z = triple1.Z;
|
|
break;
|
|
case CustomizeParameterFlag.HairSpecular:
|
|
parameters.HairFresnelValue0 = new CustomizeParameterValue(HairSpecular).XivTriple;
|
|
break;
|
|
case CustomizeParameterFlag.HairHighlight:
|
|
// Vector3 is 0x10 byte for some reason.
|
|
var triple2 = new CustomizeParameterValue(HairHighlight).XivTriple;
|
|
parameters.MeshColor.X = triple2.X;
|
|
parameters.MeshColor.Y = triple2.Y;
|
|
parameters.MeshColor.Z = triple2.Z;
|
|
break;
|
|
case CustomizeParameterFlag.LeftEye:
|
|
parameters.LeftColor = new CustomizeParameterValue(LeftEye, parameters.LeftColor.W).XivQuadruple;
|
|
break;
|
|
case CustomizeParameterFlag.RightEye:
|
|
parameters.RightColor = new CustomizeParameterValue(RightEye, parameters.RightColor.W).XivQuadruple;
|
|
break;
|
|
case CustomizeParameterFlag.FeatureColor:
|
|
parameters.OptionColor = new CustomizeParameterValue(FeatureColor).XivTriple;
|
|
break;
|
|
case CustomizeParameterFlag.FacePaintUvMultiplier:
|
|
GetUvMultiplierWrite(ref parameters) = FacePaintUvMultiplier;
|
|
break;
|
|
case CustomizeParameterFlag.FacePaintUvOffset:
|
|
GetUvOffsetWrite(ref parameters) = FacePaintUvOffset;
|
|
break;
|
|
case CustomizeParameterFlag.LeftLimbalIntensity:
|
|
parameters.LeftColor.W = LeftLimbalIntensity;
|
|
break;
|
|
case CustomizeParameterFlag.RightLimbalIntensity:
|
|
parameters.RightColor.W = RightLimbalIntensity;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static CustomizeParameterData FromParameters(in CustomizeParameter parameter, in DecalParameters decal)
|
|
=> new()
|
|
{
|
|
FacePaintUvOffset = GetUvOffset(parameter),
|
|
FacePaintUvMultiplier = GetUvMultiplier(parameter),
|
|
MuscleTone = parameter.SkinColor.W,
|
|
SkinDiffuse = new CustomizeParameterValue(parameter.SkinColor).InternalTriple,
|
|
SkinSpecular = new CustomizeParameterValue(parameter.SkinFresnelValue0).InternalTriple,
|
|
LipDiffuse = new CustomizeParameterValue(parameter.LipColor).InternalQuadruple,
|
|
HairDiffuse = new CustomizeParameterValue(parameter.MainColor).InternalTriple,
|
|
HairSpecular = new CustomizeParameterValue(parameter.HairFresnelValue0).InternalTriple,
|
|
HairHighlight = new CustomizeParameterValue(parameter.MeshColor).InternalTriple,
|
|
LeftEye = new CustomizeParameterValue(parameter.LeftColor).InternalTriple,
|
|
LeftLimbalIntensity = new CustomizeParameterValue(parameter.LeftColor.W).Single,
|
|
RightEye = new CustomizeParameterValue(parameter.RightColor).InternalTriple,
|
|
RightLimbalIntensity = new CustomizeParameterValue(parameter.RightColor.W).Single,
|
|
FeatureColor = new CustomizeParameterValue(parameter.OptionColor).InternalTriple,
|
|
DecalColor = FromParameter(decal),
|
|
};
|
|
|
|
public static CustomizeParameterValue FromParameter(in CustomizeParameter parameter, CustomizeParameterFlag flag)
|
|
=> flag switch
|
|
{
|
|
CustomizeParameterFlag.SkinDiffuse => new CustomizeParameterValue(parameter.SkinColor),
|
|
CustomizeParameterFlag.MuscleTone => new CustomizeParameterValue(parameter.SkinColor.W),
|
|
CustomizeParameterFlag.SkinSpecular => new CustomizeParameterValue(parameter.SkinFresnelValue0),
|
|
CustomizeParameterFlag.LipDiffuse => new CustomizeParameterValue(parameter.LipColor),
|
|
CustomizeParameterFlag.HairDiffuse => new CustomizeParameterValue(parameter.MainColor),
|
|
CustomizeParameterFlag.HairSpecular => new CustomizeParameterValue(parameter.HairFresnelValue0),
|
|
CustomizeParameterFlag.HairHighlight => new CustomizeParameterValue(parameter.MeshColor),
|
|
CustomizeParameterFlag.LeftEye => new CustomizeParameterValue(parameter.LeftColor),
|
|
CustomizeParameterFlag.RightEye => new CustomizeParameterValue(parameter.RightColor),
|
|
CustomizeParameterFlag.FeatureColor => new CustomizeParameterValue(parameter.OptionColor),
|
|
CustomizeParameterFlag.FacePaintUvMultiplier => new CustomizeParameterValue(GetUvMultiplier(parameter)),
|
|
CustomizeParameterFlag.FacePaintUvOffset => new CustomizeParameterValue(GetUvOffset(parameter)),
|
|
_ => CustomizeParameterValue.Zero,
|
|
};
|
|
|
|
public static Vector4 FromParameter(in DecalParameters parameter)
|
|
=> new CustomizeParameterValue(parameter.Color).InternalQuadruple;
|
|
|
|
private static bool SetIfDifferent(ref Vector3 val, Vector3 @new)
|
|
{
|
|
if (@new == val)
|
|
return false;
|
|
|
|
val = @new;
|
|
return true;
|
|
}
|
|
|
|
private static bool SetIfDifferent(ref float val, float @new)
|
|
{
|
|
if (@new == val)
|
|
return false;
|
|
|
|
val = @new;
|
|
return true;
|
|
}
|
|
|
|
private static bool SetIfDifferent(ref Vector4 val, Vector4 @new)
|
|
{
|
|
if (@new == val)
|
|
return false;
|
|
|
|
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];
|
|
}
|
|
}
|
|
}
|