diff --git a/ShapekeyMaster/CategorySlotHandler.cs b/ShapekeyMaster/CategorySlotHandler.cs index e003412..cfdf246 100644 --- a/ShapekeyMaster/CategorySlotHandler.cs +++ b/ShapekeyMaster/CategorySlotHandler.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; namespace ShapeKeyMaster { @@ -44,6 +45,8 @@ internal class SlotChecker internal static bool CheckIfSlotDisableApplies(ShapeKeyEntry entry, Maid maid) { + var allSlots = (DisableWhenEquipped[])Enum.GetValues(typeof(DisableWhenEquipped)); + #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug("Running slot check..."); #endif @@ -54,7 +57,7 @@ internal static bool CheckIfSlotDisableApplies(ShapeKeyEntry entry, Maid maid) ShapeKeyMaster.pluginLogger.LogDebug("WhenAll"); #endif //When all is equipped disable key - foreach (var slot in Enum.GetValues(typeof(DisableWhenEquipped)).Cast()) + foreach (var slot in allSlots) { #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug($"Checking {slot}"); @@ -83,10 +86,17 @@ internal static bool CheckIfSlotDisableApplies(ShapeKeyEntry entry, Maid maid) #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug($"Checking {menu}"); #endif + // support for * wildcard + string pattern = menu.Contains("*") + ? "^" + Regex.Escape(menu).Replace("\\*", ".*") + "$" + : Regex.Escape(menu); + + Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); + var bodySkins = maid.body0 .FetchGoSlot() .Select(tbody => tbody) - .Where(str => str.m_mp != null && str.m_mp.strFileName.Contains(menu, StringComparison.OrdinalIgnoreCase)) + .Where(slot => slot?.m_mp?.strFileName != null && regex.IsMatch(slot.m_mp.strFileName)) .ToArray(); if (!bodySkins.Any()) @@ -107,7 +117,7 @@ internal static bool CheckIfSlotDisableApplies(ShapeKeyEntry entry, Maid maid) #endif //When any is equipped disable key - foreach (var slot in Enum.GetValues(typeof(DisableWhenEquipped)).Cast()) + foreach (var slot in allSlots) { #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug($"Checking {slot}"); @@ -127,10 +137,19 @@ internal static bool CheckIfSlotDisableApplies(ShapeKeyEntry entry, Maid maid) #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug($"Checking {menu}"); #endif + // support for * wildcard + string pattern = menu.Contains("*") + ? "^" + Regex.Escape(menu).Replace("\\*", ".*") + "$" + : Regex.Escape(menu); + + Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); + var bodySkins = maid.body0 .FetchGoSlot() .Select(tbody => tbody) - .Where(str => str.m_mp != null && str.m_mp.strFileName.Contains(menu, StringComparison.OrdinalIgnoreCase)); + .Where(slot => slot?.m_mp?.strFileName != null && regex.IsMatch(slot.m_mp.strFileName)) + .ToArray(); + if (bodySkins.Any(skin => maid.body0.GetMask(skin.SlotId))) { diff --git a/ShapekeyMaster/HarmonyPatchers.cs b/ShapekeyMaster/HarmonyPatchers.cs index 1fc905c..67c0edd 100644 --- a/ShapekeyMaster/HarmonyPatchers.cs +++ b/ShapekeyMaster/HarmonyPatchers.cs @@ -23,6 +23,8 @@ internal class HarmonyPatchers private static float[] _previousBlends; + private static Dictionary _ignoreFlag = new Dictionary(); + [HarmonyPatch(typeof(TMorph), MethodType.Constructor, typeof(TBodySkin))] [HarmonyPostfix] private static void NotifyOfLoad(ref TMorph __instance) @@ -121,14 +123,50 @@ private static void VerifyBlendValuesBeforeSet(ref TMorph __instance) __instance.BlendValues[index] = 0; __instance.BlendValuesBackup[index] = 0; } - else if (shapeKeyEntry.ConditionalsToggle && __instance.bodyskin != null && __instance.bodyskin.body && __instance.bodyskin.body.maid && SlotChecker.CheckIfSlotDisableApplies(shapeKeyEntry, __instance.bodyskin.body.maid)) + else if (shapeKeyEntry.ConditionalsToggle && __instance.bodyskin != null && __instance.bodyskin.body && __instance.bodyskin.body.maid) { #if (DEBUG) ShapeKeyMaster.pluginLogger.LogDebug($"Applying Conditional State @ {__instance.bodyskin.body.maid.status.fullNameJpStyle} :: {__instance.Category} ::: {shapeKeyEntry.EntryName} :::: {shapeKeyEntry.ShapeKey}"); #endif - __instance.BlendValues[index] = shapeKeyEntry.DisabledDeform / 100; - __instance.BlendValuesBackup[index] = shapeKeyEntry.DisabledDeform / 100; + // When the condition is not met, skip the processing of shapekey, so other programs can use this shape key + if (SlotChecker.CheckIfSlotDisableApplies(shapeKeyEntry, __instance.bodyskin.body.maid)) + { + if (_ignoreFlag.ContainsKey(shapeKeyEntry) && _ignoreFlag[shapeKeyEntry] == true) + { + continue; + } + + __instance.BlendValues[index] = shapeKeyEntry.DisabledDeform / 100; + __instance.BlendValuesBackup[index] = shapeKeyEntry.DisabledDeform / 100; + + + // Check if values are approximately equal, because sometimes there will be problems with values not being applied + bool isBlendValueEqual = Math.Abs(__instance.BlendValues[index] - (shapeKeyEntry.DisabledDeform / 100)) < 0.01; + bool isBlendBackupEqual = Math.Abs(__instance.BlendValuesBackup[index] - (shapeKeyEntry.DisabledDeform / 100)) < 0.01; + + if (isBlendValueEqual && isBlendBackupEqual) + { + _ignoreFlag[shapeKeyEntry] = true; + } + } + else + { + _ignoreFlag[shapeKeyEntry] = false; + + if (shapeKeyEntry.AnimateWithExcitement && + YotogiLvls.Contains(SceneManager.GetActiveScene().name)) + { + var deform = shapeKeyEntry.CalculateExcitementDeformation(); + __instance.BlendValues[index] = deform / 100; + __instance.BlendValuesBackup[index] = deform / 100; + } + else + { + __instance.BlendValues[index] = shapeKeyEntry.Deform / 100; + __instance.BlendValuesBackup[index] = shapeKeyEntry.Deform / 100; + } + } } else if (shapeKeyEntry.AnimateWithExcitement && YotogiLvls.Contains(SceneManager.GetActiveScene().name)) {