using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using MikuDanceProject.Core; using MikuDanceProject.Mmd; using MikuDanceProject.Runtime; using Photon.Pun; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } internal static class IsExternalInit { } } namespace MikuDanceProject.Mmd { internal static class CoordinateConverter { public static Vector3 Position(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(0f - value.x, value.y, value.z); } public static Vector3 Normal(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(0f - value.x, value.y, value.z); } public static Quaternion Rotation(Quaternion value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(value.x, 0f - value.y, 0f - value.z, value.w); } } internal static class BinaryReaderExtensions { public static Vector2 ReadVector2(this BinaryReader reader) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2(reader.ReadSingle(), reader.ReadSingle()); } public static Vector3 ReadVector3(this BinaryReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } public static Vector4 ReadVector4(this BinaryReader reader) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } public static Quaternion ReadQuaternion(this BinaryReader reader) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } public static string ReadPmxString(this BinaryReader reader, Encoding encoding) { int num = reader.ReadInt32(); if (num <= 0) { return string.Empty; } byte[] bytes = reader.ReadBytes(num); return encoding.GetString(bytes); } public static string ReadFixedString(this BinaryReader reader, int byteCount, Encoding encoding) { byte[] array = reader.ReadBytes(byteCount); int num = Array.IndexOf(array, (byte)0); if (num < 0) { num = array.Length; } return encoding.GetString(array, 0, num).Trim(); } public static int ReadSizedIndex(this BinaryReader reader, int size, bool allowNegative = true) { return size switch { 1 => allowNegative ? ((int)reader.ReadSByte()) : ((int)reader.ReadByte()), 2 => allowNegative ? ((int)reader.ReadInt16()) : ((int)reader.ReadUInt16()), 4 => reader.ReadInt32(), _ => throw new InvalidDataException($"Unsupported PMX index size: {size}."), }; } } internal sealed class PmxModel { public string ModelName { get; init; } = string.Empty; public List Vertices { get; } = new List(); public List Indices { get; } = new List(); public List Textures { get; } = new List(); public List Materials { get; } = new List(); public List Bones { get; } = new List(); public List Morphs { get; } = new List(); } internal sealed class PmxVertex { public Vector3 Position { get; init; } public Vector3 Normal { get; init; } public Vector2 Uv { get; init; } public BoneWeight BoneWeight { get; init; } } internal sealed class PmxMaterial { public string Name { get; init; } = string.Empty; public Color Diffuse { get; init; } = Color.white; public int TextureIndex { get; init; } public int IndexCount { get; init; } } internal sealed class PmxBone { public string NameLocal { get; init; } = string.Empty; public string NameUniversal { get; init; } = string.Empty; public int ParentIndex { get; init; } public Vector3 Position { get; init; } public PmxIkDefinition? IkDefinition { get; init; } public string DisplayName { get { if (!string.IsNullOrWhiteSpace(NameLocal)) { return NameLocal; } return NameUniversal; } } } internal sealed class PmxIkDefinition { public int TargetBoneIndex { get; init; } public int LoopCount { get; init; } public float LimitRadian { get; init; } public List Links { get; } = new List(); } internal sealed class PmxIkLink { public int BoneIndex { get; init; } public bool HasAngleLimit { get; init; } public Vector3 MinimumAngle { get; init; } public Vector3 MaximumAngle { get; init; } } internal sealed class PmxMorph { public string NameLocal { get; init; } = string.Empty; public string NameUniversal { get; init; } = string.Empty; public byte MorphType { get; init; } public List VertexOffsets { get; } = new List(); public List GroupOffsets { get; } = new List(); public string DisplayName { get { if (!string.IsNullOrWhiteSpace(NameLocal)) { return NameLocal; } return NameUniversal; } } } internal sealed class PmxVertexMorphOffset { public int VertexIndex { get; init; } public Vector3 PositionOffset { get; init; } } internal sealed class PmxGroupMorphOffset { public int MorphIndex { get; init; } public float Weight { get; init; } } internal sealed class VmdMotion { public string ModelName { get; init; } = string.Empty; public List BoneFrames { get; } = new List(); public List MorphFrames { get; } = new List(); } internal sealed class VmdBoneFrame { public string BoneName { get; init; } = string.Empty; public uint FrameIndex { get; init; } public Vector3 Position { get; init; } public Quaternion Rotation { get; init; } } internal sealed class VmdMorphFrame { public string MorphName { get; init; } = string.Empty; public uint FrameIndex { get; init; } public float Weight { get; init; } } internal static class VmdReader { private const int HeaderByteCount = 30; private const int ModelNameByteCount = 20; private const int BoneNameByteCount = 15; private const int MorphNameByteCount = 15; private const int BoneFramePayloadByteCount = 96; private const int BoneFrameByteCount = 111; public static VmdMotion Read(string filePath) { using FileStream input = File.OpenRead(filePath); using BinaryReader reader = new BinaryReader(input); return Read(reader, includeBoneFrames: true); } public static VmdMotion Read(byte[] bytes) { using MemoryStream input = new MemoryStream(bytes, writable: false); using BinaryReader reader = new BinaryReader(input); return Read(reader, includeBoneFrames: true); } public static VmdMotion ReadMorphOnly(byte[] bytes) { using MemoryStream input = new MemoryStream(bytes, writable: false); using BinaryReader reader = new BinaryReader(input); return Read(reader, includeBoneFrames: false); } private static VmdMotion Read(BinaryReader reader, bool includeBoneFrames) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) string text = Encoding.ASCII.GetString(reader.ReadBytes(30)).TrimEnd('\0', ' '); if (!text.StartsWith("Vocaloid Motion Data", StringComparison.Ordinal)) { throw new InvalidDataException("Unexpected VMD header: " + text); } VmdMotion vmdMotion = new VmdMotion { ModelName = ReadShiftJisString(reader, 20) }; uint num = reader.ReadUInt32(); if (includeBoneFrames) { for (uint num2 = 0u; num2 < num; num2++) { string boneName = ReadShiftJisString(reader, 15); uint frameIndex = reader.ReadUInt32(); Vector3 position = CoordinateConverter.Position(reader.ReadVector3()); Quaternion rotation = CoordinateConverter.Rotation(reader.ReadQuaternion()); reader.ReadBytes(64); vmdMotion.BoneFrames.Add(new VmdBoneFrame { BoneName = boneName, FrameIndex = frameIndex, Position = position, Rotation = rotation }); } } else { checked { SkipBytes(reader, unchecked((long)num) * 111L); } } uint num3 = reader.ReadUInt32(); for (uint num4 = 0u; num4 < num3; num4++) { vmdMotion.MorphFrames.Add(new VmdMorphFrame { MorphName = ReadShiftJisString(reader, 15), FrameIndex = reader.ReadUInt32(), Weight = reader.ReadSingle() }); } return vmdMotion; } private static string ReadShiftJisString(BinaryReader reader, int byteCount) { return ShiftJisDecoder.Decode(reader.ReadBytes(byteCount)); } private static void SkipBytes(BinaryReader reader, long byteCount) { if (byteCount <= 0) { return; } Stream baseStream = reader.BaseStream; if (baseStream.CanSeek) { baseStream.Seek(byteCount, SeekOrigin.Current); return; } long num = byteCount; byte[] array = new byte[4096]; while (num > 0) { int count = (int)Math.Min(num, array.Length); int num2 = reader.Read(array, 0, count); if (num2 <= 0) { throw new EndOfStreamException("Unexpected end of stream while skipping VMD bone frames."); } num -= num2; } } } internal static class VmdAnimationBuilder { private static readonly HashSet IgnoredControlBones = new HashSet(StringComparer.Ordinal) { "全ての親", "センター", "グルーブ", "操作中心", "センター先", "Root", "Center", "Groove" }; public static AnimationClip BuildLegacyClip(VmdMotion motion, Transform animationRoot, IReadOnlyDictionary boneMap, SkinnedMeshRenderer renderer, out int matchedBoneCount, out int matchedMorphCount) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) matchedBoneCount = 0; matchedMorphCount = 0; AnimationClip val = new AnimationClip { name = (string.IsNullOrWhiteSpace(motion.ModelName) ? "MikuDanceMotion" : motion.ModelName), legacy = true, wrapMode = (WrapMode)2 }; foreach (IGrouping item in from frame in motion.BoneFrames where !string.IsNullOrWhiteSpace(frame.BoneName) group frame by frame.BoneName) { if (IgnoredControlBones.Contains(item.Key) || !boneMap.TryGetValue(item.Key, out Transform value)) { continue; } matchedBoneCount++; string text = BuildPath(animationRoot, value); VmdBoneFrame[] array = (from frame in item group frame by frame.FrameIndex into @group select @group.Last() into frame orderby frame.FrameIndex select frame).ToArray(); if (array.Length != 0) { Vector3 localPosition = value.localPosition; Quaternion localRotation = value.localRotation; AnimationCurve val2 = new AnimationCurve(); AnimationCurve val3 = new AnimationCurve(); AnimationCurve val4 = new AnimationCurve(); AnimationCurve val5 = new AnimationCurve(); AnimationCurve val6 = new AnimationCurve(); AnimationCurve val7 = new AnimationCurve(); AnimationCurve val8 = new AnimationCurve(); if (array[0].FrameIndex != 0) { AddTransformKey(0f, localPosition, localRotation, val2, val3, val4, val5, val6, val7, val8); } VmdBoneFrame[] array2 = array; foreach (VmdBoneFrame vmdBoneFrame in array2) { AddTransformKey((float)vmdBoneFrame.FrameIndex / 30f, localPosition + vmdBoneFrame.Position, localRotation * vmdBoneFrame.Rotation, val2, val3, val4, val5, val6, val7, val8); } MakeCurvesLinear(val2, val3, val4, val5, val6, val7, val8); val.SetCurve(text, typeof(Transform), "localPosition.x", val2); val.SetCurve(text, typeof(Transform), "localPosition.y", val3); val.SetCurve(text, typeof(Transform), "localPosition.z", val4); val.SetCurve(text, typeof(Transform), "localRotation.x", val5); val.SetCurve(text, typeof(Transform), "localRotation.y", val6); val.SetCurve(text, typeof(Transform), "localRotation.z", val7); val.SetCurve(text, typeof(Transform), "localRotation.w", val8); } } matchedMorphCount = BuildMorphCurves(motion, animationRoot, renderer, val, 0u); val.EnsureQuaternionContinuity(); return val; } public static AnimationClip? BuildMorphOnlyClip(VmdMotion motion, Transform animationRoot, SkinnedMeshRenderer renderer, uint trimStartFrame, out int matchedMorphCount) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown matchedMorphCount = 0; AnimationClip val = new AnimationClip { name = (string.IsNullOrWhiteSpace(motion.ModelName) ? "MikuMorphMotion" : (motion.ModelName + "_Morph")), legacy = true, wrapMode = (WrapMode)2 }; matchedMorphCount = BuildMorphCurves(motion, animationRoot, renderer, val, trimStartFrame); if (matchedMorphCount <= 0) { return null; } return val; } private static int BuildMorphCurves(VmdMotion motion, Transform animationRoot, SkinnedMeshRenderer renderer, AnimationClip clip, uint trimStartFrame) { //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown Mesh sharedMesh = renderer.sharedMesh; if ((Object)(object)sharedMesh == (Object)null || sharedMesh.blendShapeCount == 0) { return 0; } string text = BuildPath(animationRoot, ((Component)renderer).transform); Dictionary dictionary = (from @group in (from name in Enumerable.Range(0, sharedMesh.blendShapeCount).Select((Func)sharedMesh.GetBlendShapeName) where !string.IsNullOrWhiteSpace(name) select name).GroupBy(NormalizeMorphNameForMatch, StringComparer.Ordinal) where !string.IsNullOrWhiteSpace(@group.Key) select @group).ToDictionary, string, string>((IGrouping group) => group.Key, (IGrouping group) => group.OrderBy((string name) => name.Length).ThenBy((string name) => name, StringComparer.Ordinal).First(), StringComparer.Ordinal); int num = 0; foreach (IGrouping item in from frame in motion.MorphFrames where !string.IsNullOrWhiteSpace(frame.MorphName) group frame by frame.MorphName) { string text2 = NormalizeMorphNameForMatch(item.Key); if (string.IsNullOrWhiteSpace(text2) || !dictionary.TryGetValue(text2, out var value)) { continue; } VmdMorphFrame[] array = (from frame in item group frame by frame.FrameIndex into @group select @group.Last() into frame where frame.FrameIndex >= trimStartFrame orderby frame.FrameIndex select frame).ToArray(); if (array.Length != 0) { AnimationCurve val = new AnimationCurve(); if (array[0].FrameIndex > trimStartFrame) { val.AddKey(0f, 0f); } VmdMorphFrame[] array2 = array; foreach (VmdMorphFrame vmdMorphFrame in array2) { val.AddKey((float)(vmdMorphFrame.FrameIndex - trimStartFrame) / 30f, vmdMorphFrame.Weight * 100f); } MakeCurvesLinear(val); clip.SetCurve(text, typeof(SkinnedMeshRenderer), "blendShape." + value, val); num++; } } return num; } private static string NormalizeMorphNameForMatch(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } char[] array = new char[value.Length]; int num = 0; for (int i = 0; i < value.Length; i++) { char c = char.ToLowerInvariant(value[i]); if (!char.IsWhiteSpace(c) && c != '_' && c != '-' && c != '.' && c != '/' && c != '\\' && c != '(' && c != ')' && c != '[' && c != ']' && c != '・') { array[num++] = c; } } if (num == 0) { return string.Empty; } string text = new string(array, 0, num); int j; for (j = 0; j < text.Length && char.IsDigit(text[j]); j++) { } if (j <= 0 || j >= text.Length) { return text; } return text.Substring(j); } internal static string NormalizeMorphNameForDiagnostics(string value) { return NormalizeMorphNameForMatch(value); } private static void AddTransformKey(float time, Vector3 position, Quaternion rotation, AnimationCurve posX, AnimationCurve posY, AnimationCurve posZ, AnimationCurve rotX, AnimationCurve rotY, AnimationCurve rotZ, AnimationCurve rotW) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) posX.AddKey(time, position.x); posY.AddKey(time, position.y); posZ.AddKey(time, position.z); rotX.AddKey(time, rotation.x); rotY.AddKey(time, rotation.y); rotZ.AddKey(time, rotation.z); rotW.AddKey(time, rotation.w); } private static void MakeCurvesLinear(params AnimationCurve[] curves) { foreach (AnimationCurve val in curves) { for (int j = 0; j < val.length; j++) { AnimationUtilityCompat.SetKeyLinear(val, j); } } } private static string BuildPath(Transform root, Transform target) { if ((Object)(object)target == (Object)(object)root) { return string.Empty; } Stack stack = new Stack(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { stack.Push(((Object)val).name); val = val.parent; } return string.Join("/", stack.ToArray()); } } internal static class AnimationUtilityCompat { public static void SetKeyLinear(AnimationCurve curve, int index) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (curve.length >= 2) { Keyframe val = curve[index]; int num = Mathf.Max(index - 1, 0); int num2 = Mathf.Min(index + 1, curve.length - 1); if (num != index) { Keyframe from = curve[num]; ((Keyframe)(ref val)).inTangent = CalculateTangent(from, val); } if (num2 != index) { Keyframe to = curve[num2]; ((Keyframe)(ref val)).outTangent = CalculateTangent(val, to); } curve.MoveKey(index, val); } } private static float CalculateTangent(Keyframe from, Keyframe to) { float num = ((Keyframe)(ref to)).time - ((Keyframe)(ref from)).time; if (Mathf.Abs(num) <= float.Epsilon) { return 0f; } return (((Keyframe)(ref to)).value - ((Keyframe)(ref from)).value) / num; } } internal static class ShiftJisDecoder { private const uint CodePageShiftJis = 932u; private static readonly bool IsWindowsPlatform = IsRunningOnWindows(); private static readonly bool CodePagesProviderRegistered = TryRegisterCodePagesProvider(); private static readonly Encoding? CachedShiftJisEncoding = CreateShiftJisEncoding(); public static string DiagnosticSummary { get { if (CachedShiftJisEncoding == null) { if (!IsWindowsPlatform) { return $"fallback-utf8-ascii(providerRegistered={CodePagesProviderRegistered})"; } return $"kernel32-cp932(providerRegistered={CodePagesProviderRegistered})"; } return $"{CachedShiftJisEncoding.WebName}(codePage={CachedShiftJisEncoding.CodePage}, providerRegistered={CodePagesProviderRegistered})"; } } public static string Decode(byte[] bytes) { int num = Array.IndexOf(bytes, (byte)0); if (num < 0) { num = bytes.Length; } if (num == 0) { return string.Empty; } if (CachedShiftJisEncoding != null) { try { return CachedShiftJisEncoding.GetString(bytes, 0, num); } catch { } } if (TryDecodeWithWindowsCodePage(bytes, num, out string value)) { return value; } try { return Encoding.UTF8.GetString(bytes, 0, num); } catch { return Encoding.ASCII.GetString(bytes, 0, num); } } private static Encoding? CreateShiftJisEncoding() { _ = CodePagesProviderRegistered; Encoding encoding = TryGetEncoding(932); if (encoding != null) { return encoding; } encoding = TryGetEncoding("shift_jis"); if (encoding != null) { return encoding; } encoding = TryGetEncoding("shift-jis"); if (encoding != null) { return encoding; } return TryGetEncoding("cp932"); } private static Encoding? TryGetEncoding(int codePage) { try { return Encoding.GetEncoding(codePage); } catch { return null; } } private static Encoding? TryGetEncoding(string name) { try { return Encoding.GetEncoding(name); } catch { return null; } } private static bool TryDecodeWithWindowsCodePage(byte[] bytes, int length, out string value) { value = string.Empty; if (!IsWindowsPlatform || length <= 0) { return false; } try { int num = MultiByteToWideCharCount(932u, 0u, bytes, length, IntPtr.Zero, 0); if (num <= 0) { return false; } char[] array = new char[num]; int num2 = MultiByteToWideCharChars(932u, 0u, bytes, length, array, array.Length); if (num2 <= 0) { return false; } value = new string(array, 0, num2); return true; } catch (DllNotFoundException) { return false; } catch (EntryPointNotFoundException) { return false; } catch (BadImageFormatException) { return false; } } private static bool TryRegisterCodePagesProvider() { try { Type type = ResolveCodePagesProviderType(); if (type == null) { return false; } object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null, null); if (obj == null) { return false; } MethodInfo methodInfo = typeof(Encoding).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => string.Equals(method.Name, "RegisterProvider", StringComparison.Ordinal) && method.GetParameters().Length == 1); if (methodInfo == null) { return false; } methodInfo.Invoke(null, new object[1] { obj }); return true; } catch { return false; } } private static Type? ResolveCodePagesProviderType() { Type type = Type.GetType("System.Text.CodePagesEncodingProvider, System.Text.Encoding.CodePages", throwOnError: false); if (type != null) { return type; } try { type = Assembly.Load("System.Text.Encoding.CodePages").GetType("System.Text.CodePagesEncodingProvider", throwOnError: false); if (type != null) { return type; } } catch { } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("System.Text.CodePagesEncodingProvider", throwOnError: false); if (type != null) { return type; } } return null; } private static bool IsRunningOnWindows() { PlatformID platform = Environment.OSVersion.Platform; if ((uint)platform <= 3u) { return true; } return false; } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "MultiByteToWideChar", SetLastError = true)] private static extern int MultiByteToWideCharCount(uint codePage, uint flags, byte[] multiByteString, int byteCount, IntPtr wideCharBuffer, int wideCharCount); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "MultiByteToWideChar", SetLastError = true)] private static extern int MultiByteToWideCharChars(uint codePage, uint flags, byte[] multiByteString, int byteCount, [Out] char[] wideCharBuffer, int wideCharCount); } } namespace MikuDanceProject.Runtime { internal sealed class DanceController : MonoBehaviour { private sealed class RuntimeLightingMaterialSnapshot { private readonly Dictionary _colors = new Dictionary(); private RuntimeLightingMaterialSnapshot() { } public static RuntimeLightingMaterialSnapshot Capture(Material material, IEnumerable propertyNames) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) RuntimeLightingMaterialSnapshot runtimeLightingMaterialSnapshot = new RuntimeLightingMaterialSnapshot(); foreach (string propertyName in propertyNames) { if (material.HasProperty(propertyName)) { runtimeLightingMaterialSnapshot._colors[propertyName] = material.GetColor(propertyName); } } return runtimeLightingMaterialSnapshot; } public bool TryGetColor(string propertyName, out Color color) { return _colors.TryGetValue(propertyName, out color); } } private readonly struct PlacementPose { public Vector3 Position { get; } public Vector3 Forward { get; } public string Source { get; } private PlacementPose(Vector3 position, Vector3 forward, string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Position = position; Forward = forward; Source = source; } public static PlacementPose Create(Vector3 position, Vector3 forward, string source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new PlacementPose(position, forward, source); } } [CompilerGenerated] private sealed class d__234 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Animator <>2__current; private int <>l__initialThreadId; public DanceController <>4__this; private int 5__2; Animator IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__234(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; DanceController danceController = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_007f; } <>1__state = -1; if (danceController._activeAnimators == null || danceController._activeAnimators.Length == 0) { return false; } 5__2 = 0; goto IL_008f; IL_007f: 5__2++; goto IL_008f; IL_008f: if (5__2 < danceController._activeAnimators.Length) { Animator val = danceController._activeAnimators[5__2]; if (!((Object)(object)val == (Object)null) && val != danceController._activeAnimator && !((Object)(object)val.runtimeAnimatorController == (Object)null)) { <>2__current = val; <>1__state = 1; return true; } goto IL_007f; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__234 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new d__234(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__109 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public DanceController <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__109(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; DanceController danceController = <>4__this; if (num != 0) { return false; } <>1__state = -1; if (danceController._config == null || danceController._logger == null || danceController._isLoading || danceController._loadedPrefab != null) { return false; } danceController._isLoading = true; string text = danceController._config.ResolveUnityBundlePath(); float realtimeSinceStartup = Time.realtimeSinceStartup; danceController.LogVerbose("Starting Unity asset bundle load. bundlePath='" + text + "'."); try { if (!File.Exists(text)) { danceController._logger.LogError((object)("Required Unity asset bundle file was not found: '" + text + "'.")); return false; } danceController._loadedPrefab = danceController._unityBundleLoader.Load(text, danceController._logger); Object.DontDestroyOnLoad((Object)(object)danceController._loadedPrefab.Template); danceController.LogVerbose($"Using Unity asset bundle dancer source '{text}'. loadDuration={Time.realtimeSinceStartup - realtimeSinceStartup:0.###}s."); } catch (Exception arg) { danceController._logger.LogError((object)$"Failed to load Unity asset bundle dancer source '{text}': {arg}"); } finally { danceController._isLoading = false; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float GroundProbeStartHeight = 80f; private const float GroundProbeDistance = 200f; private const float PlayerGroundProbeStartHeight = 1.25f; private const float PlayerGroundProbeMaxRise = 0.6f; private const float PlayerGroundProbePreferredMaxDrop = 0.9f; private const float PlayerGroundProbeFallbackMaxDrop = 1.25f; private const float PlayerGroundProbeSearchRadius = 3f; private const float PlayerColliderFootPadding = 0.05f; private const float RuntimeRefreshInterval = 0.25f; private const float OfflinePauseTimeScaleThreshold = 0.001f; private const float DistancePauseThresholdMeters = 100f; private const float AudioMinDistanceMeters = 1f; private const float LegacyMotionTrimStartFrame = 0f; private const float LegacyMotionFrameRate = 30f; private const float AudioFadeDurationSeconds = 0.35f; private const float AudioRestartLeadTimeSeconds = 0.05f; private const float AudioDriftCorrectionThresholdSeconds = 0.35f; private const float AudioHardResyncThresholdSeconds = 1.25f; private const float SavePlacementHoldDurationSeconds = 3f; private static readonly bool EnableVerboseRuntimeLogs = false; private static readonly string[] NativeFacialClipTokens = new string[21] { "face", "facial", "expression", "morph", "blend", "blendshape", "viseme", "mouth", "lip", "eye", "brow", "smile", "blink", "表情", "脸", "口", "目", "眉", "モーフ", "フェイス", "表情" }; private const string ShadowBlobObjectName = "MikuShadowBlob"; private const int ShadowBlobTextureSize = 64; private const float ShadowBlobOpacity = 0.38f; private const float ShadowBlobWorldLift = 0.025f; private const float ShadowBlobWidthFactor = 0.34f; private const float ShadowBlobDepthFactor = 0.24f; private const float ShadowBlobMinWorldWidth = 0.85f; private const float ShadowBlobMaxWorldWidth = 2.4f; private const float ShadowBlobMinWorldDepth = 0.65f; private const float ShadowBlobMaxWorldDepth = 1.8f; private static readonly string[] PreferredPivotBoneTokens = new string[12] { "hips", "pelvis", "hip", "cf_j_hips", "j_bip_c_hips", "j_bip_c_pelvis", "腰", "下半身", "骨盤", "センター", "center", "centre" }; private static readonly string[] LightingSensitiveShaderTokens = new string[6] { "lit", "toon", "mmd", "standard", "outline", "cel" }; private static readonly string[] LightingNeutralShaderTokens = new string[3] { "unlit", "sprites/default", "sprite" }; private static readonly string[] LightingSensitiveMaterialProperties = new string[12] { "_Ambient", "_IndirectLightMinColor", "_CelShadeMidPoint", "_CelShadeSoftness", "_ReceiveShadowMappingAmount", "_ShadowMapColor", "_SpecularHighlights", "_EnvironmentReflections", "_Metallic", "_Smoothness", "_Glossiness", "_SpecColor" }; private static readonly string[] RuntimeLightingExposureColorProperties = new string[5] { "_BaseColor", "_Color", "_TintColor", "_MainColor", "_LitColor" }; private const BindingFlags InstanceBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags StaticBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private const string DancerObjectName = "MikuDanceDisplay"; private const string WrappedModelRootName = "MikuLobbyModel"; private static readonly DancePlaybackMetadata LegacyPlaybackMetadata = DancePlaybackMetadata.CreateDefault(); private static readonly Vector3 AirportDisplayPosition = new Vector3(-16.78f, 2.55f, 64.85f); private static readonly Vector3 AirportDisplayForward = Vector3.right; private static readonly Vector3[] PlayerGroundProbeSampleOffsets = BuildPlayerGroundSampleOffsets(); private static readonly Type? CharacterType = FindGameType("Character"); private static readonly Type? PlayerType = FindGameType("Player"); private static readonly Type? MenuWindowType = FindGameType("MenuWindow"); private static readonly FieldInfo? LocalCharacterField = CharacterType?.GetField("localCharacter", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? LocalPlayerField = PlayerType?.GetField("localPlayer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? AllActiveWindowsField = MenuWindowType?.GetField("AllActiveWindows", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo? CharacterCenterProperty = CharacterType?.GetProperty("Center", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo? CharacterVirtualCenterProperty = CharacterType?.GetProperty("VirtualCenter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo? PlayerCharacterProperty = PlayerType?.GetProperty("character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? PlayerCharacterField = PlayerType?.GetField("character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly PropertyInfo? MenuWindowIsOpenProperty = MenuWindowType?.GetProperty("isOpen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private readonly UnityAssetBundleLoader _unityBundleLoader = new UnityAssetBundleLoader(); private DancePluginConfig? _config; private ManualLogSource? _logger; private LoadedDancePrefab? _loadedPrefab; private GameObject? _activeDancer; private Animator? _activeAnimator; private Animator[] _activeAnimators = Array.Empty(); private Animation? _activeAnimation; private AudioSource? _activeAudioSource; private AnimationClip? _activePrimaryAnimatorClip; private readonly List _runtimeLightingStabilizedMaterials = new List(); private readonly Dictionary _runtimeLightingMaterialSnapshots = new Dictionary(); private PlacementPose _activePlacement; private bool _hasActivePlacement; private bool _isLoading; private float _nextRefreshTime; private string? _lastSceneName; private bool _loggedSceneHint; private bool _lastAudioEnabledState; private bool _audioRetrySuppressed; private bool _isPausedForOfflineMenu; private bool _isPausedForDistance; private bool _audioPausedForPlaybackPause; private AudioSource? _fadingAudioSource; private float _audioFadeStartTime; private float _audioFadeDuration; private float _audioFadeTargetVolume; private int _animatorSegmentLoopIndex; private int _lastAnimatorLoopIndex = -1; private int _lastMorphLoopIndex = -1; private GameObject? _activeShadowBlob; private bool _hasAppliedPlacementConfiguration; private float _appliedModelScale; private bool _hasResolvedPlacementPivot; private Vector3 _resolvedPlacementPivotLocalPosition; private bool _hasCachedRuntimeComponents; private GameObject? _cachedRuntimeComponentRoot; private RuntimeAnimatorController? _cachedAnimatorController; private bool _hasNativeFacialAnimationControl; private float _placementHotkeyPressedAt = -1f; private bool _placementHotkeyHoldConsumed; private KeyCode _lastObservedSpawnModelKey; private bool _pendingRuntimeLightingRefresh; private bool _lastAppliedStabilizeModelLighting; private float _lastAppliedLightingExposureCompensation = -1f; private static Mesh? s_shadowBlobMesh; private static Texture2D? s_shadowBlobTexture; private static Material? s_shadowBlobMaterial; public void Initialize(DancePluginConfig config, ManualLogSource logger) { _config = config; _logger = logger; _lastAudioEnabledState = config.EnableAudio.Value; _lastAppliedStabilizeModelLighting = config.StabilizeModelLighting.Value; _lastAppliedLightingExposureCompensation = config.ResolvedLightingExposureCompensation; config.StabilizeModelLighting.SettingChanged += HandleRuntimeLightingConfigChanged; config.LightingExposureCompensation.SettingChanged += HandleRuntimeLightingConfigChanged; } private void Start() { ((MonoBehaviour)this).StartCoroutine(LoadAssetsRoutine()); } private void OnDestroy() { if (_config != null) { _config.StabilizeModelLighting.SettingChanged -= HandleRuntimeLightingConfigChanged; _config.LightingExposureCompensation.SettingChanged -= HandleRuntimeLightingConfigChanged; } DestroyActiveDancer("Dance controller destroyed."); DestroyRuntimeLightingStabilizedMaterials(); _unityBundleLoader.UnloadRetainedBundle(); } private void Update() { if (_config == null || _logger == null) { return; } TrackSceneTransitions(); if (!_config.ModEnabled.Value) { if ((Object)(object)_activeDancer != (Object)null) { DestroyActiveDancer("Model hidden because ModEnabled=False."); } _hasActivePlacement = false; ResetPlacementHotkeyState(); return; } EnsureAirportLobbyDisplay(); ProcessSpawnHotkey(); MaintainSynchronizedLoopPlayback(); UpdateActiveAudioFade(); RefreshRuntimeLightingIfConfigChanged(); if (Time.unscaledTime < _nextRefreshTime) { return; } _nextRefreshTime = Time.unscaledTime + 0.25f; if (!((Object)(object)_activeDancer == (Object)null)) { if (_hasActivePlacement && HasPlacementConfigurationChanged()) { ApplyPlacement(_activeDancer.transform, _activePlacement, _config, _loadedPrefab); UpdateShadowPresentation(_activeDancer); RecordAppliedPlacementConfiguration(); } RefreshLivePlayback(_activeDancer); } } private void LateUpdate() { if (_config != null && _logger != null) { MaintainMorphPlaybackAfterAnimator(); } } private void HandleRuntimeLightingConfigChanged(object? sender, EventArgs eventArgs) { _pendingRuntimeLightingRefresh = true; } [IteratorStateMachine(typeof(d__109))] private IEnumerator LoadAssetsRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__109(0) { <>4__this = this }; } private void TrackSceneTransitions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.Equals(name, _lastSceneName, StringComparison.Ordinal)) { _lastSceneName = name; _loggedSceneHint = false; _nextRefreshTime = 0f; if ((Object)(object)_activeDancer != (Object)null) { DestroyActiveDancer("Scene changed to '" + name + "'. The model must be placed again in the new scene."); } _hasActivePlacement = false; _isPausedForOfflineMenu = false; _isPausedForDistance = false; _audioPausedForPlaybackPause = false; ResetPlacementHotkeyState(); } } private void EnsureAirportLobbyDisplay() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (_loadedPrefab == null || (Object)(object)_activeDancer != (Object)null || _hasActivePlacement) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (string.Equals(((Scene)(ref activeScene)).name, "Airport", StringComparison.OrdinalIgnoreCase)) { _activePlacement = ResolveAirportLobbyPlacement(); _hasActivePlacement = true; if (EnsureDancerInstance() && !((Object)(object)_activeDancer == (Object)null)) { ApplyPlacement(_activeDancer.transform, _activePlacement, _config, _loadedPrefab); UpdateShadowPresentation(_activeDancer); RecordAppliedPlacementConfiguration(); ConfigurePlayback(_activeDancer); string text = $"Spawned default Airport display model at {_activeDancer.transform.position}. "; Quaternion rotation = _activeDancer.transform.rotation; LogVerbose(text + $"rotation={((Quaternion)(ref rotation)).eulerAngles}, scale={_activeDancer.transform.localScale}."); } } } private void ProcessSpawnHotkey() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if (_config == null || _logger == null) { return; } if (!_loggedSceneHint) { _loggedSceneHint = true; string[] obj = new string[5] { "Placement hotkey ready in scene '", null, null, null, null }; Scene activeScene = SceneManager.GetActiveScene(); obj[1] = ((Scene)(ref activeScene)).name; obj[2] = "'. "; obj[3] = $"Tap {_config.SpawnModelKey.Value} to spawn or move the model to the local player's ground position. "; obj[4] = $"Hold it for {3f:0.#} seconds in Airport to save the lobby showcase position into the config file for future launches."; LogVerbose(string.Concat(obj)); } KeyCode value = _config.SpawnModelKey.Value; if (value != _lastObservedSpawnModelKey) { ResetPlacementHotkeyState(); _lastObservedSpawnModelKey = value; LogVerbose($"Updated placement hotkey binding to '{value}'. Tap/hold behavior now follows this key."); } if ((int)value == 0) { ResetPlacementHotkeyState(); return; } if (Input.GetKeyDown(value)) { _placementHotkeyPressedAt = Time.unscaledTime; _placementHotkeyHoldConsumed = false; } if (Input.GetKey(value)) { if (!_placementHotkeyHoldConsumed && _placementHotkeyPressedAt >= 0f && Time.unscaledTime - _placementHotkeyPressedAt >= 3f) { _placementHotkeyHoldConsumed = true; SaveCurrentAirportDisplayPlacement(); } } else if (Input.GetKeyUp(value)) { bool num = !_placementHotkeyHoldConsumed; ResetPlacementHotkeyState(); if (num) { SpawnOrMoveToCurrentPlayer(); } } } private void SpawnOrMoveToCurrentPlayer() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) if (_config == null || _logger == null) { return; } if (_loadedPrefab == null) { if (!_isLoading) { ((MonoBehaviour)this).StartCoroutine(LoadAssetsRoutine()); } _logger.LogWarning((object)(_isLoading ? "The Unity asset bundle is still loading. Try the placement hotkey again in a moment." : "The model resources are loading now. Press the placement hotkey again in a moment.")); return; } if (!TryResolveCurrentLocalPlayerPose(out Vector3 position, out Vector3 forward, out Transform ignoredRoot, out string source)) { _logger.LogWarning((object)"The local player transform is not available yet, so the model cannot be moved right now."); return; } Vector3 forward2 = ResolveFacingDirection(forward); _activePlacement = CreatePlayerGroundLockedPlacement(position, forward2, source, ignoredRoot); _hasActivePlacement = true; bool flag = EnsureDancerInstance(); if (!((Object)(object)_activeDancer == (Object)null)) { ApplyPlacement(_activeDancer.transform, _activePlacement, _config, _loadedPrefab); UpdateShadowPresentation(_activeDancer); RecordAppliedPlacementConfiguration(); if (flag) { ConfigurePlayback(_activeDancer); } else { RefreshLivePlayback(_activeDancer); } string[] obj = new string[7] { flag ? "Spawned" : "Moved", " display model in scene '", null, null, null, null, null }; Scene activeScene = SceneManager.GetActiveScene(); obj[2] = ((Scene)(ref activeScene)).name; obj[3] = "'. "; obj[4] = $"source={source}, playerPosition={position}, groundedPosition={_activePlacement.Position}, "; object arg = _activeDancer.transform.position; Quaternion rotation = _activeDancer.transform.rotation; obj[5] = $"modelPosition={arg}, modelRotation={((Quaternion)(ref rotation)).eulerAngles}, "; obj[6] = $"modelScale={_activeDancer.transform.localScale}."; LogVerbose(string.Concat(obj)); } } private void SaveCurrentAirportDisplayPlacement() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) if (_config == null || _logger == null) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (!string.Equals(((Scene)(ref activeScene)).name, "Airport", StringComparison.OrdinalIgnoreCase)) { _logger.LogWarning((object)$"Hold {_config.SpawnModelKey.Value} for {3f:0.#} seconds only in the Airport lobby to save the lobby showcase position."); return; } if (!TryResolveCurrentLocalPlayerPose(out Vector3 position, out Vector3 forward, out Transform ignoredRoot, out string source)) { _logger.LogWarning((object)"The local player transform is not available yet, so the Airport showcase position could not be saved."); return; } Vector3 forward2 = ResolveFacingDirection(forward); PlacementPose activePlacement = CreatePlayerGroundLockedPlacement(position, forward2, source + ".SavedAirportDisplay", ignoredRoot); _config.SaveAirportPlacement(activePlacement.Position, activePlacement.Forward); _activePlacement = activePlacement; _hasActivePlacement = true; bool flag = EnsureDancerInstance(); if ((Object)(object)_activeDancer != (Object)null) { ApplyPlacement(_activeDancer.transform, _activePlacement, _config, _loadedPrefab); UpdateShadowPresentation(_activeDancer); RecordAppliedPlacementConfiguration(); if (flag) { ConfigurePlayback(_activeDancer); } else { RefreshLivePlayback(_activeDancer); } } _logger.LogInfo((object)($"Saved Airport showcase placement to config. source={source}, groundedPosition={activePlacement.Position}, " + $"forward={activePlacement.Forward}, createdNow={flag}.")); } private bool EnsureDancerInstance() { if ((Object)(object)_activeDancer != (Object)null || _loadedPrefab == null) { return false; } _activeDancer = Object.Instantiate(_loadedPrefab.Template); ((Object)_activeDancer).name = "MikuDanceDisplay"; RemoveAllColliders(_activeDancer); ResetAudioPlaybackState(); ClearResolvedPlacementPivot(); CacheActiveRuntimeComponents(_activeDancer); LogVerbose("Using embedded Animator playback for '" + ((Object)_activeDancer).name + "'. " + $"preBakedMorphClipAvailable={(Object)(object)_loadedPrefab.MorphClip != (Object)null}."); NormalizeRendererMaterials(_activeDancer); ConfigureFacialExpressions(_activeDancer); _activeDancer.SetActive(true); return true; } private void DestroyActiveDancer(string reason) { if (!((Object)(object)_activeDancer == (Object)null)) { AudioSource activeAudioSource = _activeAudioSource; if ((Object)(object)activeAudioSource != (Object)null && activeAudioSource.isPlaying) { activeAudioSource.Stop(); } ClearActiveAudioFade(activeAudioSource); Object.Destroy((Object)(object)_activeDancer); _activeDancer = null; _activeShadowBlob = null; DestroyRuntimeLightingStabilizedMaterials(); ClearAppliedPlacementConfiguration(); ClearResolvedPlacementPivot(); ClearActiveRuntimeComponents(); ResetAudioPlaybackState(); LogVerbose(reason); } } private void ApplyPlacement(Transform dancerTransform, PlacementPose placement, DancePluginConfig config, LoadedDancePrefab? prefab) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) float resolvedModelScale = config.ResolvedModelScale; Quaternion val = Quaternion.LookRotation(ResolveFacingDirection(placement.Forward), Vector3.up); Vector3 val2 = ResolvePlacementPivotLocalPosition(dancerTransform, prefab) * resolvedModelScale; dancerTransform.localScale = Vector3.one * resolvedModelScale; dancerTransform.rotation = val; dancerTransform.position = placement.Position - val * val2; } private Vector3 ResolvePlacementPivotLocalPosition(Transform dancerTransform, LoadedDancePrefab? prefab) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (_hasResolvedPlacementPivot) { return _resolvedPlacementPivotLocalPosition; } float num = prefab?.LocalMinY ?? 0f; if (TryResolvePlacementPivotFromAnimator(dancerTransform, num, out var pivotLocalPosition)) { _resolvedPlacementPivotLocalPosition = pivotLocalPosition; _hasResolvedPlacementPivot = true; return pivotLocalPosition; } if (TryResolvePlacementPivotFromNamedBone(dancerTransform, num, out var pivotLocalPosition2)) { _resolvedPlacementPivotLocalPosition = pivotLocalPosition2; _hasResolvedPlacementPivot = true; return pivotLocalPosition2; } Vector3 result = (_resolvedPlacementPivotLocalPosition = ((prefab == null) ? new Vector3(0f, num, 0f) : new Vector3(prefab.LocalBoundsCenter.x, num, prefab.LocalBoundsCenter.z))); _hasResolvedPlacementPivot = true; return result; } private static PlacementPose CreateGroundLockedPlacement(Vector3 desiredPosition, Vector3 forward, string source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 position = desiredPosition; position.y = ResolveGroundYExact(desiredPosition, desiredPosition.y + 80f, 200f, float.PositiveInfinity); return PlacementPose.Create(position, forward, source); } private static PlacementPose CreatePlayerGroundLockedPlacement(Vector3 desiredPosition, Vector3 forward, string source, Transform? ignoredRoot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Vector3 position = desiredPosition; position.y = ResolveGroundYNearPlayer(desiredPosition, desiredPosition.y + 1.25f, 200f, desiredPosition.y + 0.6f, ignoredRoot); return PlacementPose.Create(position, forward, source); } private PlacementPose ResolveAirportLobbyPlacement() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (_config != null && _config.TryGetSavedAirportPlacement(out var position, out var forward)) { return CreateGroundLockedPlacement(position, forward, "AirportLobbyDisplay.Saved"); } return CreateGroundLockedPlacement(AirportDisplayPosition, AirportDisplayForward, "AirportLobbyDisplay.Default"); } private bool HasPlacementConfigurationChanged() { if (_config == null) { return false; } if (!_hasAppliedPlacementConfiguration) { return true; } return Mathf.Abs(_appliedModelScale - _config.ResolvedModelScale) > 0.0001f; } private void RecordAppliedPlacementConfiguration() { if (_config == null) { ClearAppliedPlacementConfiguration(); return; } _hasAppliedPlacementConfiguration = true; _appliedModelScale = _config.ResolvedModelScale; } private void ClearAppliedPlacementConfiguration() { _hasAppliedPlacementConfiguration = false; _appliedModelScale = 0f; } private void ClearResolvedPlacementPivot() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) _hasResolvedPlacementPivot = false; _resolvedPlacementPivotLocalPosition = Vector3.zero; } private void ResetPlacementHotkeyState() { _placementHotkeyPressedAt = -1f; _placementHotkeyHoldConsumed = false; } private bool TryResolvePlacementPivotFromAnimator(Transform dancerTransform, float pivotY, out Vector3 pivotLocalPosition) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Animator componentInChildren = ((Component)dancerTransform).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.isHuman) { try { Transform boneTransform = componentInChildren.GetBoneTransform((HumanBodyBones)0); if (TryBuildPlacementPivotFromBone(dancerTransform, boneTransform, pivotY, out pivotLocalPosition)) { LogVerbose($"Resolved placement pivot from humanoid hips bone '{((Object)boneTransform).name}' at local {pivotLocalPosition}."); return true; } } catch (Exception ex) { LogVerbose("Failed to resolve humanoid hips pivot: " + ex.Message); } } pivotLocalPosition = default(Vector3); return false; } private bool TryResolvePlacementPivotFromNamedBone(Transform dancerTransform, float pivotY, out Vector3 pivotLocalPosition) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Transform[] componentsInChildren = ((Component)dancerTransform).GetComponentsInChildren(true); Transform val = null; int num = int.MinValue; Transform[] array = componentsInChildren; foreach (Transform val2 in array) { if (!((Object)(object)val2 == (Object)null) && val2 != dancerTransform) { int num2 = ScorePlacementPivotCandidate(((Object)val2).name); if (num2 > num) { num = num2; val = val2; } } } if ((Object)(object)val != (Object)null && TryBuildPlacementPivotFromBone(dancerTransform, val, pivotY, out pivotLocalPosition)) { LogVerbose($"Resolved placement pivot from named bone '{((Object)val).name}' at local {pivotLocalPosition}."); return true; } pivotLocalPosition = default(Vector3); return false; } private static bool TryBuildPlacementPivotFromBone(Transform dancerTransform, Transform? pivotBone, float pivotY, out Vector3 pivotLocalPosition) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pivotBone == (Object)null) { pivotLocalPosition = default(Vector3); return false; } Vector3 val = dancerTransform.InverseTransformPoint(pivotBone.position); pivotLocalPosition = new Vector3(val.x, pivotY, val.z); return true; } private static int ScorePlacementPivotCandidate(string? name) { if (string.IsNullOrWhiteSpace(name)) { return int.MinValue; } string text = (name ?? string.Empty).Trim().ToLowerInvariant(); int num = int.MinValue; for (int i = 0; i < PreferredPivotBoneTokens.Length; i++) { string text2 = PreferredPivotBoneTokens[i]; if (string.Equals(text, text2, StringComparison.Ordinal)) { return 1000 - i; } if (text.IndexOf(text2, StringComparison.Ordinal) >= 0) { num = Mathf.Max(num, 500 - i); } } return num; } private static Vector3 ResolveFacingDirection(Vector3 forward) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(forward, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static bool TryResolveCurrentLocalPlayerPose(out Vector3 position, out Vector3 forward, out Transform? ignoredRoot, out string source) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (TryGetLocalCharacterObject(out object source2) && TryResolveCharacterPose(source2, "Character.localCharacter", out position, out forward, out ignoredRoot, out source)) { return true; } if (TryGetLocalPlayerCharacterObject(out object source3) && TryResolveCharacterPose(source3, "Player.localPlayer.character", out position, out forward, out ignoredRoot, out source)) { return true; } position = default(Vector3); forward = Vector3.forward; ignoredRoot = null; source = string.Empty; return false; } private static float ResolveGroundYExact(Vector3 desiredPosition, float startY, float maxDistance, float maxAcceptedY, Transform? ignoredRoot = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) Transform ignoredRoot2 = ignoredRoot; RaycastHit[] array = Physics.RaycastAll(new Vector3(desiredPosition.x, startY, desiredPosition.z), Vector3.down, maxDistance, -1, (QueryTriggerInteraction)1); if (array.Length == 0) { return desiredPosition.y; } RaycastHit[] array2 = (from hit in array where (Object)(object)((RaycastHit)(ref hit)).collider != (Object)null where ((RaycastHit)(ref hit)).normal.y > 0.35f where !ShouldIgnoreGroundHit(hit, ignoredRoot2) select hit).ToArray(); if (array2.Length == 0) { return desiredPosition.y; } if (!float.IsPositiveInfinity(maxAcceptedY)) { RaycastHit val = (from hit in array2 where ((RaycastHit)(ref hit)).point.y <= maxAcceptedY orderby ((RaycastHit)(ref hit)).point.y descending, ((RaycastHit)(ref hit)).distance select hit).FirstOrDefault(); if ((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) { return ((RaycastHit)(ref val)).point.y; } return desiredPosition.y; } RaycastHit val2 = (from hit in array2 orderby ((RaycastHit)(ref hit)).point.y descending, ((RaycastHit)(ref hit)).distance select hit).FirstOrDefault(); if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null)) { return ((RaycastHit)(ref val2)).point.y; } return desiredPosition.y; } private static float ResolveGroundYNearPlayer(Vector3 desiredPosition, float startY, float maxDistance, float maxAcceptedY, Transform? ignoredRoot) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) GroundSampleCandidate? groundSampleCandidate = null; GroundSampleCandidate? groundSampleCandidate2 = null; for (int i = 0; i < PlayerGroundProbeSampleOffsets.Length; i++) { GroundSampleCandidate? groundSampleCandidate3 = TryResolveGroundCandidate(desiredPosition + PlayerGroundProbeSampleOffsets[i], startY, maxDistance, maxAcceptedY, ignoredRoot); if (groundSampleCandidate3.HasValue) { if (!groundSampleCandidate2.HasValue || groundSampleCandidate3.Value.IsBetterThan(groundSampleCandidate2.Value)) { groundSampleCandidate2 = groundSampleCandidate3; } if (!(desiredPosition.y - groundSampleCandidate3.Value.Y > 0.9f) && (!groundSampleCandidate.HasValue || groundSampleCandidate3.Value.IsBetterThan(groundSampleCandidate.Value))) { groundSampleCandidate = groundSampleCandidate3; } } } if (groundSampleCandidate.HasValue) { return groundSampleCandidate.Value.Y; } if (groundSampleCandidate2.HasValue && desiredPosition.y - groundSampleCandidate2.Value.Y <= 1.25f) { return groundSampleCandidate2.Value.Y; } return desiredPosition.y; } private static GroundSampleCandidate? TryResolveGroundCandidate(Vector3 desiredPosition, float startY, float maxDistance, float maxAcceptedY, Transform? ignoredRoot) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Transform ignoredRoot2 = ignoredRoot; RaycastHit[] array = Physics.RaycastAll(new Vector3(desiredPosition.x, startY, desiredPosition.z), Vector3.down, maxDistance, -1, (QueryTriggerInteraction)1); if (array.Length == 0) { return null; } GroundSampleCandidate[] array2 = (from hit in array where (Object)(object)((RaycastHit)(ref hit)).collider != (Object)null where ((RaycastHit)(ref hit)).normal.y > 0.35f where !ShouldIgnoreGroundHit(hit, ignoredRoot2) where ((RaycastHit)(ref hit)).point.y <= maxAcceptedY select new GroundSampleCandidate(((RaycastHit)(ref hit)).point.y, Mathf.Abs(desiredPosition.y - ((RaycastHit)(ref hit)).point.y), Vector2.Distance(new Vector2(desiredPosition.x, desiredPosition.z), new Vector2(((RaycastHit)(ref hit)).point.x, ((RaycastHit)(ref hit)).point.z)), ((RaycastHit)(ref hit)).distance) into hit orderby hit.VerticalDelta, hit.HorizontalDelta, hit.RaycastDistance select hit).ToArray(); if (array2.Length != 0) { return array2[0]; } return null; } private static bool TryGetLocalCharacterObject(out object source) { source = LocalCharacterField?.GetValue(null); return source != null; } private static bool TryGetLocalPlayerCharacterObject(out object source) { object obj = LocalPlayerField?.GetValue(null); if (obj == null) { source = null; return false; } source = PlayerCharacterProperty?.GetValue(obj, null) ?? PlayerCharacterField?.GetValue(obj); return source != null; } private static bool TryResolveCharacterPose(object source, string sourceName, out Vector3 position, out Vector3 forward, out Transform? ignoredRoot, out string resolvedSource) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) resolvedSource = sourceName; if (!TryExtractTransform(source, out Transform transform)) { position = default(Vector3); forward = Vector3.forward; ignoredRoot = null; return false; } ignoredRoot = transform; position = transform.position; Vector3 vector2; if (TryExtractVector3(CharacterCenterProperty?.GetValue(source, null), out var vector)) { position = new Vector3(vector.x, position.y, vector.z); resolvedSource = sourceName + ".CenterXZ"; } else if (TryExtractVector3(CharacterVirtualCenterProperty?.GetValue(source, null), out vector2)) { position = new Vector3(vector2.x, position.y, vector2.z); resolvedSource = sourceName + ".VirtualCenterXZ"; } position = new Vector3(position.x, ResolveCharacterFootY(transform, position.y), position.z); resolvedSource += ".FootY"; forward = ResolvePreferredPlayerForward(transform, position, out string source2); resolvedSource = resolvedSource + "." + source2; return true; } private static float ResolveCharacterFootY(Transform root, float fallbackY) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) bool flag = false; float num = float.PositiveInfinity; Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !val.isTrigger) { Bounds bounds = val.bounds; float y = ((Bounds)(ref bounds)).min.y; if (!float.IsNaN(y) && !float.IsInfinity(y)) { num = Mathf.Min(num, y); flag = true; } } } if (!flag) { return fallbackY; } return num + 0.05f; } private static bool ShouldIgnoreGroundHit(RaycastHit hit, Transform? ignoredRoot) { if ((Object)(object)ignoredRoot == (Object)null || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return false; } if (IsSameOrChildTransform(((Component)((RaycastHit)(ref hit)).collider).transform, ignoredRoot)) { return true; } Rigidbody attachedRigidbody = ((RaycastHit)(ref hit)).collider.attachedRigidbody; if ((Object)(object)attachedRigidbody != (Object)null) { return IsSameOrChildTransform(((Component)attachedRigidbody).transform, ignoredRoot); } return false; } private static bool IsSameOrChildTransform(Transform? candidate, Transform root) { if ((Object)(object)candidate != (Object)null) { if (!((Object)(object)candidate == (Object)(object)root)) { return candidate.IsChildOf(root); } return true; } return false; } private static Vector3[] BuildPlayerGroundSampleOffsets() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) Vector2[] obj = new Vector2[8] { new Vector2(1f, 0f), new Vector2(-1f, 0f), new Vector2(0f, 1f), new Vector2(0f, -1f), default(Vector2), default(Vector2), default(Vector2), default(Vector2) }; Vector2 val = new Vector2(1f, 1f); obj[4] = ((Vector2)(ref val)).normalized; val = new Vector2(1f, -1f); obj[5] = ((Vector2)(ref val)).normalized; val = new Vector2(-1f, 1f); obj[6] = ((Vector2)(ref val)).normalized; val = new Vector2(-1f, -1f); obj[7] = ((Vector2)(ref val)).normalized; Vector2[] array = (Vector2[])(object)obj; float[] array2 = new float[6] { 0.35f, 0.7f, 1.1f, 1.6f, 2.2f, 3f }; List list = new List(1 + array.Length * array2.Length) { Vector3.zero }; float[] array3 = array2; foreach (float num in array3) { foreach (Vector2 val2 in array) { list.Add(new Vector3(val2.x * num, 0f, val2.y * num)); } } return list.ToArray(); } private static bool TryExtractTransform(object? source, out Transform transform) { Transform val = (Transform)((source is Transform) ? source : null); if (val == null) { Component val2 = (Component)((source is Component) ? source : null); if (val2 == null) { GameObject val3 = (GameObject)((source is GameObject) ? source : null); if (val3 != null) { transform = val3.transform; return true; } transform = null; return false; } transform = val2.transform; return (Object)(object)transform != (Object)null; } transform = val; return true; } private static bool TryExtractVector3(object? value, out Vector3 vector) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (value is Vector3 val) { vector = val; return true; } vector = default(Vector3); return false; } private static Vector3 ResolvePlanarForward(Transform transform) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(transform.forward, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static Vector3 ResolvePreferredPlayerForward(Transform playerRoot, Vector3 playerPosition, out string source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (TryResolveCameraPlanarForward(playerPosition, out Vector3 forward, out string source2)) { source = source2; return forward; } source = "TransformForward"; return ResolvePlanarForward(playerRoot); } private static bool TryResolveCameraPlanarForward(Vector3 playerPosition, out Vector3 forward, out string source) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) source = string.Empty; forward = Vector3.zero; Camera main = Camera.main; if (IsUsableGameplayCamera(main)) { Vector3 val = Vector3.ProjectOnPlane(((Component)main).transform.forward, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { forward = ((Vector3)(ref val)).normalized; source = "Camera:" + ((Object)main).name; return true; } } Camera val2 = null; float num = float.PositiveInfinity; Camera[] allCameras = Camera.allCameras; foreach (Camera val3 in allCameras) { if (!IsUsableGameplayCamera(val3)) { continue; } Vector3 val4 = Vector3.ProjectOnPlane(((Component)val3).transform.forward, Vector3.up); if (!(((Vector3)(ref val4)).sqrMagnitude <= 0.01f)) { float num2 = Vector3.Distance(((Component)val3).transform.position, playerPosition); if (!(num2 >= num)) { num = num2; val2 = val3; } } } if ((Object)(object)val2 == (Object)null) { return false; } Vector3 val5 = Vector3.ProjectOnPlane(((Component)val2).transform.forward, Vector3.up); forward = ((Vector3)(ref val5)).normalized; source = "Camera:" + ((Object)val2).name; return true; } private static bool IsUsableGameplayCamera(Camera? camera) { if ((Object)(object)camera != (Object)null && ((Behaviour)camera).enabled && ((Component)camera).gameObject.activeInHierarchy) { return !camera.orthographic; } return false; } private static Type? FindGameType(string typeName) { return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => string.Equals(assembly.GetName().Name, "Assembly-CSharp", StringComparison.Ordinal))?.GetType(typeName, throwOnError: false, ignoreCase: false); } private static void RemoveAllColliders(GameObject root) { Collider[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } } private void NormalizeRendererMaterials(GameObject root) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (_logger == null) { return; } bool flag = _config?.StabilizeModelLighting.Value ?? true; float num = _config?.ResolvedLightingExposureCompensation ?? 0.82f; Dictionary materialCache = new Dictionary(); int num2 = 0; Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { val.enabled = true; val.shadowCastingMode = (ShadowCastingMode)1; val.receiveShadows = true; val.allowOcclusionWhenDynamic = true; val.lightProbeUsage = (LightProbeUsage)1; val.reflectionProbeUsage = (ReflectionProbeUsage)1; int expectedMaterialCount = GetExpectedMaterialCount(val); if (expectedMaterialCount > 0) { Material[] array = val.sharedMaterials ?? Array.Empty(); if (array.Length != expectedMaterialCount || array.Any((Material material) => (Object)(object)material == (Object)null)) { val.sharedMaterials = BuildNormalizedRendererMaterialArray(array, expectedMaterialCount); LogVerbose($"Normalized runtime materials for '{((Object)val).name}'. subMeshes={expectedMaterialCount}, materials={val.sharedMaterials.Length}."); } } if (flag && TryBuildLightingStabilizedMaterialArray(val, val.sharedMaterials ?? Array.Empty(), materialCache, _runtimeLightingStabilizedMaterials, _runtimeLightingMaterialSnapshots, num, out Material[] stabilizedMaterials, out int newStabilizedMaterialCount)) { val.sharedMaterials = stabilizedMaterials; num2 += newStabilizedMaterialCount; } EnableShadowSupport(val.sharedMaterials); SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val2 != null) { val2.updateWhenOffscreen = true; if ((Object)(object)val2.sharedMesh != (Object)null) { Bounds bounds = val2.sharedMesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)val2).localBounds = bounds; } } } if (num2 > 0) { LogVerbose($"Applied runtime lighting stabilization to {num2} material(s). " + $"exposureCompensation={num:0.###}."); } RecordAppliedRuntimeLightingConfiguration(flag, num); } private static Material[] BuildNormalizedRendererMaterialArray(Material[] sharedMaterials, int expectedCount) { Material[] array = (Material[])(object)new Material[Mathf.Max(1, expectedCount)]; Material val = ((IEnumerable)sharedMaterials).FirstOrDefault((Func)((Material material) => (Object)(object)material != (Object)null)) ?? CreateFallbackRendererMaterial(); for (int i = 0; i < array.Length; i++) { Material val2 = ((i < sharedMaterials.Length) ? sharedMaterials[i] : null); if ((Object)(object)val2 != (Object)null) { array[i] = val2; val = val2; } else { array[i] = val; } } return array; } private static bool TryBuildLightingStabilizedMaterialArray(Renderer renderer, Material[] sharedMaterials, Dictionary materialCache, List runtimeMaterials, Dictionary runtimeMaterialSnapshots, float exposureCompensation, out Material[] stabilizedMaterials, out int newStabilizedMaterialCount) { stabilizedMaterials = sharedMaterials; newStabilizedMaterialCount = 0; if ((Object)(object)renderer == (Object)null || sharedMaterials == null || sharedMaterials.Length == 0) { return false; } Material[] array = null; for (int i = 0; i < sharedMaterials.Length; i++) { Material val = sharedMaterials[i]; if (!((Object)(object)val == (Object)null) && IsLightingSensitiveMaterial(val)) { if (!materialCache.TryGetValue(val, out Material value)) { value = (materialCache[val] = CreateLightingStabilizedMaterial(val, exposureCompensation, out RuntimeLightingMaterialSnapshot snapshot)); runtimeMaterials.Add(value); runtimeMaterialSnapshots[value] = snapshot; newStabilizedMaterialCount++; } if (array == null) { array = (Material[])sharedMaterials.Clone(); } array[i] = value; } } if (array == null) { return false; } stabilizedMaterials = array; return true; } private static bool IsLightingSensitiveMaterial(Material material) { if ((Object)(object)material == (Object)null || (Object)(object)material.shader == (Object)null) { return false; } string text = ((Object)material.shader).name ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return HasAnyMaterialProperty(material, LightingSensitiveMaterialProperties); } string lowerShaderName = text.ToLowerInvariant(); if (LightingNeutralShaderTokens.Any((string token) => lowerShaderName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0) && !lowerShaderName.Contains("toon")) { return false; } if (!LightingSensitiveShaderTokens.Any((string token) => lowerShaderName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)) { return HasAnyMaterialProperty(material, LightingSensitiveMaterialProperties); } return true; } private static Material CreateLightingStabilizedMaterial(Material sourceMaterial, float exposureCompensation, out RuntimeLightingMaterialSnapshot snapshot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(sourceMaterial) { name = (string.IsNullOrWhiteSpace(((Object)sourceMaterial).name) ? "MikuLightSafeMaterial" : (((Object)sourceMaterial).name + "_LightSafe")) }; float exposure = Mathf.Clamp(exposureCompensation, 0.4f, 1f); snapshot = RuntimeLightingMaterialSnapshot.Capture(val, RuntimeLightingExposureColorProperties); ApplyLightingExposure(val, snapshot, exposure); ClampColorPropertyMax(val, "_Ambient", 0.22f); ClampColorPropertyMax(val, "_IndirectLightMinColor", 0.06f); ClampColorPropertyMax(val, "_SpecColor", 0.18f); ClampColorPropertyMax(val, "_EmissionColor", 0.45f); SetFloatIfPresent(val, "_Metallic", 0f); ClampFloatPropertyMax(val, "_Smoothness", 0.18f); ClampFloatPropertyMax(val, "_Glossiness", 0.18f); SetFloatIfPresent(val, "_SpecularHighlights", 0f); SetFloatIfPresent(val, "_EnvironmentReflections", 0f); SetFloatIfPresent(val, "_ReceiveShadowMappingAmount", 0.9f); ClampFloatPropertyMin(val, "_ShadowLum", 1.35f); if (val.HasProperty("_ToonTone")) { Vector4 vector = val.GetVector("_ToonTone"); vector.y = Mathf.Min(vector.y, 0.42f); vector.z = Mathf.Min(vector.z, 0.45f); val.SetVector("_ToonTone", vector); } if (val.HasProperty("_SphereMapMode") && val.GetFloat("_SphereMapMode") > 1.5f) { val.SetFloat("_SphereMapMode", 1f); } val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4; return val; } private void RefreshRuntimeLightingIfConfigChanged() { if (_config == null) { return; } bool value = _config.StabilizeModelLighting.Value; float resolvedLightingExposureCompensation = _config.ResolvedLightingExposureCompensation; if (!_pendingRuntimeLightingRefresh && _lastAppliedStabilizeModelLighting == value && Mathf.Approximately(_lastAppliedLightingExposureCompensation, resolvedLightingExposureCompensation)) { return; } _pendingRuntimeLightingRefresh = false; if ((Object)(object)_activeDancer == (Object)null) { RecordAppliedRuntimeLightingConfiguration(value, resolvedLightingExposureCompensation); return; } if (value) { if (_runtimeLightingStabilizedMaterials.Count == 0) { NormalizeRendererMaterials(_activeDancer); LogVerbose("Runtime lighting stabilization enabled from config without respawning model. " + $"exposureCompensation={resolvedLightingExposureCompensation:0.###}."); return; } ApplyRuntimeLightingExposure(resolvedLightingExposureCompensation); } else { ApplyRuntimeLightingExposure(1f); } RecordAppliedRuntimeLightingConfiguration(value, resolvedLightingExposureCompensation); LogVerbose($"Applied live runtime lighting config. stabilizeLighting={value}, " + $"exposureCompensation={resolvedLightingExposureCompensation:0.###}, activeMaterials={_runtimeLightingStabilizedMaterials.Count}."); } private void ApplyRuntimeLightingExposure(float exposureCompensation) { float exposure = Mathf.Clamp(exposureCompensation, 0.4f, 1f); foreach (Material runtimeLightingStabilizedMaterial in _runtimeLightingStabilizedMaterials) { if (!((Object)(object)runtimeLightingStabilizedMaterial == (Object)null) && _runtimeLightingMaterialSnapshots.TryGetValue(runtimeLightingStabilizedMaterial, out RuntimeLightingMaterialSnapshot value)) { ApplyLightingExposure(runtimeLightingStabilizedMaterial, value, exposure); } } } private static void ApplyLightingExposure(Material material, RuntimeLightingMaterialSnapshot snapshot, float exposure) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) string[] runtimeLightingExposureColorProperties = RuntimeLightingExposureColorProperties; foreach (string text in runtimeLightingExposureColorProperties) { if (material.HasProperty(text) && snapshot.TryGetColor(text, out var color)) { material.SetColor(text, new Color(Mathf.Clamp01(color.r * exposure), Mathf.Clamp01(color.g * exposure), Mathf.Clamp01(color.b * exposure), color.a)); } } } private void RecordAppliedRuntimeLightingConfiguration(bool stabilizeLighting, float exposureCompensation) { _lastAppliedStabilizeModelLighting = stabilizeLighting; _lastAppliedLightingExposureCompensation = Mathf.Clamp(exposureCompensation, 0.4f, 1f); } private static bool HasAnyMaterialProperty(Material material, IEnumerable propertyNames) { return propertyNames.Any((Func)material.HasProperty); } private static void ScaleColorProperty(Material material, string propertyName, float multiplier) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyName)) { Color color = material.GetColor(propertyName); material.SetColor(propertyName, new Color(Mathf.Clamp01(color.r * multiplier), Mathf.Clamp01(color.g * multiplier), Mathf.Clamp01(color.b * multiplier), color.a)); } } private static void ClampColorPropertyMax(Material material, string propertyName, float maxChannel) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyName)) { maxChannel = Mathf.Clamp01(maxChannel); Color color = material.GetColor(propertyName); material.SetColor(propertyName, new Color(Mathf.Min(color.r, maxChannel), Mathf.Min(color.g, maxChannel), Mathf.Min(color.b, maxChannel), color.a)); } } private static void SetFloatIfPresent(Material material, string propertyName, float value) { if (material.HasProperty(propertyName)) { material.SetFloat(propertyName, value); } } private static void ClampFloatPropertyMax(Material material, string propertyName, float maxValue) { if (material.HasProperty(propertyName)) { material.SetFloat(propertyName, Mathf.Min(material.GetFloat(propertyName), maxValue)); } } private static void ClampFloatPropertyMin(Material material, string propertyName, float minValue) { if (material.HasProperty(propertyName)) { material.SetFloat(propertyName, Mathf.Max(material.GetFloat(propertyName), minValue)); } } private static Material CreateFallbackRendererMaterial() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown Shader val = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Legacy Shaders/Diffuse"); if (!((Object)(object)val != (Object)null)) { return null; } return new Material(val); } private void DestroyRuntimeLightingStabilizedMaterials() { if (_runtimeLightingStabilizedMaterials.Count == 0) { _runtimeLightingMaterialSnapshots.Clear(); return; } for (int i = 0; i < _runtimeLightingStabilizedMaterials.Count; i++) { Material val = _runtimeLightingStabilizedMaterials[i]; if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _runtimeLightingStabilizedMaterials.Clear(); _runtimeLightingMaterialSnapshots.Clear(); } private static int GetExpectedMaterialCount(Renderer renderer) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null && (Object)(object)val.sharedMesh != (Object)null) { return Mathf.Max(1, val.sharedMesh.subMeshCount); } MeshFilter val2 = default(MeshFilter); if (((Component)renderer).TryGetComponent(ref val2) && (Object)(object)val2.sharedMesh != (Object)null) { return Mathf.Max(1, val2.sharedMesh.subMeshCount); } Material[] sharedMaterials = renderer.sharedMaterials; return Mathf.Max(1, (sharedMaterials != null) ? sharedMaterials.Length : 0); } private void UpdateShadowPresentation(GameObject root) { Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)_activeShadowBlob != (Object)null) || !((Object)(object)((Component)val).gameObject == (Object)(object)_activeShadowBlob)) { val.enabled = true; val.shadowCastingMode = (ShadowCastingMode)1; val.receiveShadows = true; val.allowOcclusionWhenDynamic = true; val.lightProbeUsage = (LightProbeUsage)1; val.reflectionProbeUsage = (ReflectionProbeUsage)1; EnableShadowSupport(val.sharedMaterials); } } GameObject val2 = EnsureShadowBlob(root); if (!((Object)(object)val2 == (Object)null)) { ConfigureShadowBlobTransform(root.transform, val2.transform); } } private GameObject? EnsureShadowBlob(GameObject root) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if ((Object)(object)_activeShadowBlob != (Object)null && (Object)(object)_activeShadowBlob.transform.parent == (Object)(object)root.transform) { ConfigureShadowBlobRenderer(_activeShadowBlob.GetComponent()); return _activeShadowBlob; } Material orCreateShadowBlobMaterial = GetOrCreateShadowBlobMaterial(); if ((Object)(object)orCreateShadowBlobMaterial == (Object)null) { return null; } GameObject val = new GameObject("MikuShadowBlob") { hideFlags = (HideFlags)52 }; val.transform.SetParent(root.transform, false); val.layer = root.layer; val.AddComponent().sharedMesh = GetOrCreateShadowBlobMesh(); MeshRenderer obj = val.AddComponent(); ((Renderer)obj).sharedMaterial = orCreateShadowBlobMaterial; ConfigureShadowBlobRenderer(obj); _activeShadowBlob = val; LogVerbose("Created runtime shadow blob for '" + ((Object)root).name + "'."); return val; } private void ConfigureShadowBlobTransform(Transform rootTransform, Transform shadowTransform) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) float num = ResolveUniformScale(rootTransform.lossyScale); float num2 = Mathf.Max(1f, (_loadedPrefab?.LocalHeight ?? 1.8f) * num); float num3 = Mathf.Clamp(num2 * 0.34f, 0.85f, 2.4f); float num4 = Mathf.Clamp(num2 * 0.24f, 0.65f, 1.8f); Vector3 val = _loadedPrefab?.LocalBoundsCenter ?? Vector3.zero; float num5 = _loadedPrefab?.LocalMinY ?? 0f; shadowTransform.localPosition = new Vector3(val.x, num5 + 0.025f / num, val.z); shadowTransform.localRotation = Quaternion.Euler(-90f, 0f, 0f); shadowTransform.localScale = new Vector3(num3 / num, num4 / num, 1f); } private static void ConfigureShadowBlobRenderer(MeshRenderer? meshRenderer) { if (!((Object)(object)meshRenderer == (Object)null)) { ((Renderer)meshRenderer).enabled = true; ((Renderer)meshRenderer).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)meshRenderer).receiveShadows = false; ((Renderer)meshRenderer).allowOcclusionWhenDynamic = false; ((Renderer)meshRenderer).lightProbeUsage = (LightProbeUsage)0; ((Renderer)meshRenderer).reflectionProbeUsage = (ReflectionProbeUsage)0; } } private static float ResolveUniformScale(Vector3 lossyScale) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) return Mathf.Max(0.0001f, (Mathf.Abs(lossyScale.x) + Mathf.Abs(lossyScale.y) + Mathf.Abs(lossyScale.z)) / 3f); } private static void EnableShadowSupport(Material[]? materials) { if (materials != null) { for (int i = 0; i < materials.Length; i++) { EnableShadowSupport(materials[i]); } } } private static void EnableShadowSupport(Material? material) { if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_ReceiveShadows")) { material.SetFloat("_ReceiveShadows", 1f); } if (material.HasProperty("_CastShadows")) { material.SetFloat("_CastShadows", 1f); } material.SetShaderPassEnabled("ShadowCaster", true); } } private static Mesh GetOrCreateShadowBlobMesh() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_shadowBlobMesh != (Object)null) { return s_shadowBlobMesh; } Mesh val = new Mesh(); ((Object)val).name = "MikuShadowBlobMesh"; ((Object)val).hideFlags = (HideFlags)61; val.vertices = (Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, -0.5f, 0f), new Vector3(0.5f, -0.5f, 0f), new Vector3(-0.5f, 0.5f, 0f), new Vector3(0.5f, 0.5f, 0f) }; val.uv = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(1f, 1f) }; val.triangles = new int[6] { 0, 2, 1, 2, 3, 1 }; val.normals = (Vector3[])(object)new Vector3[4] { Vector3.forward, Vector3.forward, Vector3.forward, Vector3.forward }; val.bounds = new Bounds(Vector3.zero, new Vector3(1f, 1f, 0.01f)); return s_shadowBlobMesh = val; } private static Texture2D GetOrCreateShadowBlobTexture() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_shadowBlobTexture != (Object)null) { return s_shadowBlobTexture; } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false, true) { name = "MikuShadowBlobTexture", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = ((float)j + 0.5f) / 64f * 2f - 1f; float num2 = ((float)i + 0.5f) / 64f * 2f - 1f; float num3 = Mathf.Sqrt(num * num + num2 * num2); float num4 = Mathf.Clamp01(1f - num3); num4 = Mathf.SmoothStep(0f, 1f, num4); array[i * 64 + j] = new Color(0f, 0f, 0f, num4); } } val.SetPixels(array); val.Apply(false, true); s_shadowBlobTexture = val; return val; } private static Material? GetOrCreateShadowBlobMaterial() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_shadowBlobMaterial != (Object)null) { return s_shadowBlobMaterial; } Shader val = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Transparent") ?? Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Transparent/Diffuse"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { name = "MikuShadowBlobMaterial", hideFlags = (HideFlags)61 }; Texture2D orCreateShadowBlobTexture = GetOrCreateShadowBlobTexture(); Color val3 = default(Color); ((Color)(ref val3))..ctor(0f, 0f, 0f, 0.38f); if (val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", (Texture)(object)orCreateShadowBlobTexture); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)orCreateShadowBlobTexture); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val3); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val3); } if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_SrcBlend")) { val2.SetInt("_SrcBlend", 5); } if (val2.HasProperty("_DstBlend")) { val2.SetInt("_DstBlend", 10); } if (val2.HasProperty("_ZWrite")) { val2.SetInt("_ZWrite", 0); } if (val2.HasProperty("_Cull")) { val2.SetInt("_Cull", 0); } val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.DisableKeyword("_ALPHATEST_ON"); val2.renderQueue = 3000; s_shadowBlobMaterial = val2; return val2; } private void ConfigurePlayback(GameObject dancer) { CacheActiveRuntimeComponents(dancer); AudioSource activeAudioSource = _activeAudioSource; AudioClip val = ResolveAudioClip(activeAudioSource); Animator activeAnimator = _activeAnimator; if ((Object)(object)activeAnimator != (Object)null && (Object)(object)activeAnimator.runtimeAnimatorController != (Object)null) { ConfigureAudioSource(activeAudioSource, val); AnimationClip val2 = ResolveSynchronizedAnimatorClip(activeAnimator); float num = ResolveSynchronizedAnimatorSpeed(val2, val); bool num2 = HasNativeFacialAnimationControl(dancer); activeAnimator.cullingMode = (AnimatorCullingMode)0; activeAnimator.applyRootMotion = false; activeAnimator.updateMode = (AnimatorUpdateMode)0; activeAnimator.speed = num; activeAnimator.Rebind(); activeAnimator.Update(0f); StartAnimatorAtBeginning(activeAnimator, val2); if (num2) { StopRuntimeMorphPlayback(); } else { StartMorphPlayback(dancer); } ConfigureSecondaryNativeAnimators(val2, num); ApplyActiveAnimationPlaybackSpeed(val); bool flag = (Object)(object)activeAudioSource != (Object)null && (Object)(object)val != (Object)null && SynchronizeAudioWithAnimator(activeAnimator, activeAudioSource, val, val2, startIfNeeded: true, allowFadeOnStart: true, suppressFurtherRetries: true, logCorrections: false); string[] obj = new string[11] { "Animator configured for '", ((Object)dancer).name, "', controller='", ((Object)activeAnimator.runtimeAnimatorController).name, "', avatar='", null, null, null, null, null, null }; Avatar avatar = activeAnimator.avatar; obj[5] = ((avatar != null) ? ((Object)avatar).name : null) ?? "(none)"; obj[6] = "', "; obj[7] = string.Format("clip='{0}', clipLength={1:0.###}, ", ((val2 != null) ? ((Object)val2).name : null) ?? "(none)", (val2 != null) ? val2.length : 0f); obj[8] = string.Format("audioEnabled={0}, audioClip='{1}', audioLength={2:0.###}, ", _config?.EnableAudio.Value ?? false, ((val != null) ? ((Object)val).name : null) ?? "(none)", (val != null) ? val.length : 0f); obj[9] = $"audioSegmentStart={ResolveAudioSegmentStartSeconds(val2, val):0.###}, audioSegmentLength={ResolveAudioSegmentDuration(val2, val):0.###}, "; obj[10] = $"animatorSpeed={num:0.###}, audioVolume={_config?.ResolvedAudioVolume ?? 0f:0.###}, audioRange={_config?.ResolvedAudioRangeMeters ?? 0f:0.###}, audioStarted={flag}, audioIsPlaying={activeAudioSource != null && activeAudioSource.isPlaying}."; LogVerbose(string.Concat(obj)); return; } Animation activeAnimation = _activeAnimation; if ((Object)(object)activeAnimation != (Object)null && (Object)(object)_loadedPrefab?.Clip != (Object)null) { activeAnimation.cullingType = (AnimationCullingType)0; if ((Object)(object)activeAnimation.GetClip(((Object)_loadedPrefab.Clip).name) == (Object)null) { activeAnimation.AddClip(_loadedPrefab.Clip, ((Object)_loadedPrefab.Clip).name); } activeAnimation.clip = _loadedPrefab.Clip; activeAnimation.wrapMode = (WrapMode)2; activeAnimation.Stop(); activeAnimation.Rewind(); activeAnimation.Play(((Object)_loadedPrefab.Clip).name); ConfigureAudioSource(activeAudioSource, val); ApplyActiveAnimationPlaybackSpeed(val); if (HasNativeFacialAnimationControl(dancer)) { StopRuntimeMorphPlayback(); } StartAudioIfEnabled(activeAudioSource, val, _loadedPrefab.Clip, suppressFurtherRetries: true); LogVerbose($"Animation configured for '{((Object)dancer).name}', clip='{((Object)_loadedPrefab.Clip).name}', isPlaying={activeAnimation.isPlaying}."); } else if (HasNativeFacialAnimationControl(dancer)) { StopRuntimeMorphPlayback(); } else { StartMorphPlayback(dancer); } } private void ConfigureFacialExpressions(GameObject dancer) { CacheActiveRuntimeComponents(dancer); if (HasNativeFacialAnimationControl(dancer)) { MikuFacialExpressionController component = dancer.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; } StopRuntimeMorphPlayback(); LogVerbose("Skipping runtime facial expression playback for '" + ((Object)dancer).name + "' because Unity-native facial animation control was detected."); return; } if ((Object)(object)_loadedPrefab?.MorphClip != (Object)null) { MikuFacialExpressionController component2 = dancer.GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } LogVerbose("Skipping fallback facial expression controller for '" + ((Object)dancer).name + "' because a bundled morph clip is available."); return; } LoadedDancePrefab? loadedPrefab = _loadedPrefab; if (loadedPrefab != null && loadedPrefab.Source == LoadedPrefabSource.UnityAssetBundle && (Object)(object)_activeAnimator != (Object)null && (Object)(object)_activeAnimator.runtimeAnimatorController != (Object)null && (Object)(object)_activePrimaryAnimatorClip != (Object)null) { LogVerbose("Unity AssetBundle Animator clip '" + ((Object)_activePrimaryAnimatorClip).name + "' is active on '" + ((Object)dancer).name + "', but no morph bridge is available. Falling back to simplified facial controller."); } (dancer.GetComponent() ?? dancer.AddComponent()).Initialize(_activeAudioSource, _activeAnimator, _logger); } private void RefreshLivePlayback(GameObject dancer) { CacheActiveRuntimeComponents(dancer); Animator activeAnimator = _activeAnimator; AudioSource activeAudioSource = _activeAudioSource; AudioClip val = ResolveAudioClip(activeAudioSource); ConfigureAudioSource(activeAudioSource, val); HandleAudioToggleState(); if (HandlePlaybackPause(dancer, activeAnimator, activeAudioSource, val)) { return; } if ((Object)(object)activeAnimator != (Object)null && (Object)(object)activeAnimator.runtimeAnimatorController != (Object)null) { AnimationClip val2 = ResolveSynchronizedAnimatorClip(activeAnimator); activeAnimator.speed = ResolveSynchronizedAnimatorSpeed(val2, val); ForceAnimatorLayerWeights(activeAnimator, 1f); RefreshSecondaryNativeAnimators(activeAnimator, val2); ApplyActiveAnimationPlaybackSpeed(val); DancePluginConfig? config = _config; if (config != null && config.EnableAudio.Value && (Object)(object)activeAudioSource != (Object)null && (Object)(object)val != (Object)null && !_audioRetrySuppressed) { bool isPlaying = activeAudioSource.isPlaying; if (SynchronizeAudioWithAnimator(activeAnimator, activeAudioSource, val, val2, startIfNeeded: true, allowFadeOnStart: true, suppressFurtherRetries: true, logCorrections: false) && !isPlaying) { LogVerbose("Audio was enabled while the model was already active. Aligned synchronized playback with clip '" + ((Object)val).name + "'."); } } } else { DancePluginConfig? config2 = _config; if (config2 != null && config2.EnableAudio.Value && (Object)(object)activeAudioSource != (Object)null && (Object)(object)val != (Object)null && !activeAudioSource.isPlaying && !_audioRetrySuppressed) { StartAudioIfEnabled(activeAudioSource, val, _loadedPrefab?.Clip, suppressFurtherRetries: true); } } } private void HandleAudioToggleState() { bool flag = _config?.EnableAudio.Value ?? false; if (flag != _lastAudioEnabledState) { _audioRetrySuppressed = false; _lastAudioEnabledState = flag; } } private void ResetAudioPlaybackState() { _audioRetrySuppressed = false; _lastAudioEnabledState = _config?.EnableAudio.Value ?? false; _animatorSegmentLoopIndex = 0; _lastAnimatorLoopIndex = -1; _lastMorphLoopIndex = -1; _isPausedForOfflineMenu = false; _isPausedForDistance = false; _audioPausedForPlaybackPause = false; ClearActiveAudioFade(); } private void ConfigureAudioSource(AudioSource? audioSource, AudioClip? audioClip) { if (!((Object)(object)audioSource == (Object)null)) { if ((Object)(object)audioClip != (Object)null && (Object)(object)audioSource.clip == (Object)null) { audioSource.clip = audioClip; } audioSource.playOnAwake = false; audioSource.loop = false; DancePluginConfig? config = _config; audioSource.mute = config == null || !config.EnableAudio.Value; if (!IsActiveAudioFade(audioSource)) { audioSource.volume = _config?.ResolvedAudioVolume ?? 1f; } float maxDistance = Mathf.Max(1.01f, _config?.ResolvedAudioRangeMeters ?? 5f); audioSource.spatialBlend = 1f; audioSource.dopplerLevel = 0f; audioSource.priority = 32; audioSource.rolloffMode = (AudioRolloffMode)1; audioSource.minDistance = 1f; audioSource.maxDistance = maxDistance; audioSource.spread = 0f; DancePluginConfig? config2 = _config; if (config2 != null && config2.EnableAudio.Value) { RequestAudioClipLoad(audioClip); } DancePluginConfig? config3 = _config; if ((config3 == null || !config3.EnableAudio.Value) && audioSource.isPlaying) { ClearActiveAudioFade(audioSource); audioSource.Stop(); audioSource.time = 0f; } } } private bool StartAudioIfEnabled(AudioSource? audioSource, AudioClip? audioClip, AnimationClip? animationClip, bool suppressFurtherRetries) { DancePluginConfig? config = _config; if (config == null || !config.EnableAudio.Value || (Object)(object)audioSource == (Object)null || (Object)(object)audioClip == (Object)null) { if ((Object)(object)audioSource != (Object)null) { ClearActiveAudioFade(audioSource); audioSource.Stop(); audioSource.time = 0f; } _audioRetrySuppressed = false; return false; } float timeSeconds = ResolveAudioSegmentStartSeconds(animationClip, audioClip); float num = ResolveAudioSegmentDuration(animationClip, audioClip); if (num <= 0.01f) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Audio segment duration is invalid for clip '" + ((Object)audioClip).name + "'.")); } return false; } if (!EnsureAudioClipReadyForPlayback(audioClip, suppressFurtherRetries, "audio start")) { return false; } try { audioSource.clip = audioClip; audioSource.loop = false; SeekAudioToTime(audioSource, audioClip, timeSeconds); audioSource.volume = 0f; audioSource.Play(); BeginAudioFade(audioSource, Mathf.Min(0.35f, num * 0.5f)); } catch (Exception ex) { if (suppressFurtherRetries) { _audioRetrySuppressed = true; } ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Audio playback failed for clip '" + ((Object)audioClip).name + "': " + ex.Message)); } return false; } bool isPlaying = audioSource.isPlaying; if (!isPlaying && suppressFurtherRetries) { _audioRetrySuppressed = true; ManualLogSource? logger3 = _logger; if (logger3 == null) { return isPlaying; } logger3.LogWarning((object)("Audio playback could not start for clip '" + ((Object)audioClip).name + "'. Automatic retries are suppressed until audio is toggled again or the model is respawned.")); } return isPlaying; } private void MaintainSynchronizedLoopPlayback() { if ((Object)(object)_activeDancer == (Object)null || _isPausedForOfflineMenu || _isPausedForDistance) { return; } if (!((Object)(object)_activeAnimator == (Object)null)) { DancePluginConfig? config = _config; if (config == null || !config.EnableAudio.Value || !((Object)(object)_activeAudioSource == (Object)null)) { goto IL_0060; } } CacheActiveRuntimeComponents(_activeDancer); goto IL_0060; IL_0060: Animator activeAnimator = _activeAnimator; if ((Object)(object)activeAnimator == (Object)null || (Object)(object)activeAnimator.runtimeAnimatorController == (Object)null) { return; } AnimationClip val = ResolveSynchronizedAnimatorClip(activeAnimator); if ((Object)(object)val == (Object)null) { return; } MaintainAnimatorSegmentLoop(activeAnimator, val); DancePluginConfig? config2 = _config; if (config2 != null && config2.EnableAudio.Value) { AudioSource activeAudioSource = _activeAudioSource; AudioClip val2 = ResolveAudioClip(activeAudioSource); if (!((Object)(object)activeAudioSource == (Object)null) && !((Object)(object)val2 == (Object)null)) { SynchronizeAudioWithAnimator(activeAnimator, activeAudioSource, val2, val, startIfNeeded: true, allowFadeOnStart: true, suppressFurtherRetries: true, logCorrections: false); } } } private void MaintainMorphPlaybackAfterAnimator() { if ((Object)(object)_activeDancer == (Object)null || _isPausedForOfflineMenu || _isPausedForDistance) { return; } if ((Object)(object)_activeAnimator == (Object)null) { CacheActiveRuntimeComponents(_activeDancer); } Animator activeAnimator = _activeAnimator; if ((Object)(object)activeAnimator == (Object)null || (Object)(object)activeAnimator.runtimeAnimatorController == (Object)null) { return; } AnimationClip val = ResolveSynchronizedAnimatorClip(activeAnimator); if (!((Object)(object)val == (Object)null)) { if (_hasNativeFacialAnimationControl) { StopRuntimeMorphPlayback(); SynchronizeNativeFacialAnimatorsWithPrimary(activeAnimator, val); } else { SynchronizeMorphPlaybackWithAnimator(activeAnimator, val); } } } private void StartMorphPlayback(GameObject? dancer) { if ((Object)(object)dancer == (Object)null || (Object)(object)_loadedPrefab?.MorphClip == (Object)null) { return; } if (HasNativeFacialAnimationControl(dancer)) { StopRuntimeMorphPlayback(); return; } if (ShouldUseDirectMorphSampling()) { Animation activeAnimation = _activeAnimation; if ((Object)(object)activeAnimation != (Object)null && (Object)(object)activeAnimation.clip != (Object)null) { activeAnimation.Stop(((Object)activeAnimation.clip).name); } _activeAnimation = null; SampleMorphClip(_loadedPrefab.MorphClip, _activeAnimator, 0f); _lastMorphLoopIndex = -1; return; } GameObject val = ResolveMorphPlaybackHost(dancer); Animation val2 = (_activeAnimation = val.GetComponent() ?? val.AddComponent()); val2.cullingType = (AnimationCullingType)0; if ((Object)(object)val2.GetClip(((Object)_loadedPrefab.MorphClip).name) == (Object)null) { val2.AddClip(_loadedPrefab.MorphClip, ((Object)_loadedPrefab.MorphClip).name); } val2.clip = _loadedPrefab.MorphClip; val2.wrapMode = (WrapMode)2; val2.playAutomatically = false; val2.Stop(((Object)_loadedPrefab.MorphClip).name); val2.Rewind(((Object)_loadedPrefab.MorphClip).name); val2.Play(((Object)_loadedPrefab.MorphClip).name); AnimationState val3 = val2[((Object)_loadedPrefab.MorphClip).name]; if ((TrackedReference)(object)val3 != (TrackedReference)null) { val3.enabled = true; val3.weight = 1f; val3.wrapMode = (WrapMode)2; val3.time = 0f; if ((Object)(object)_activeAnimator != (Object)null && (Object)(object)_activeAnimator.runtimeAnimatorController != (Object)null && (Object)(object)_activePrimaryAnimatorClip != (Object)null) { val3.speed = 0f; val2.Sample(); } else { ApplyActiveAnimationPlaybackSpeed(ResolveAudioClip(_activeAudioSource)); } } _lastMorphLoopIndex = -1; } private void SynchronizeMorphPlaybackWithAnimator(Animator animator, AnimationClip? primaryClip) { AnimationClip val = _loadedPrefab?.MorphClip; GameObject val2 = _activeDancer ?? ((Component)animator).gameObject; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || val.length <= 0.01f) { return; } ResolveAnimatorSegmentProgress(animator, primaryClip, out var loopProgress, out var loopIndex); float num = Mathf.Clamp(loopProgress * val.length, 0f, Mathf.Max(0f, val.length - 0.0001f)); if (ShouldUseDirectMorphSampling()) { SampleMorphClip(val, animator, num); _lastMorphLoopIndex = loopIndex; return; } Animation activeAnimation = _activeAnimation; if ((Object)(object)activeAnimation == (Object)null || (Object)(object)activeAnimation.clip == (Object)null) { return; } string name = ((Object)activeAnimation.clip).name; AnimationState val3 = activeAnimation[name]; if (!((TrackedReference)(object)val3 == (TrackedReference)null)) { val3.enabled = true; val3.weight = 1f; val3.wrapMode = (WrapMode)2; val3.speed = 0f; if (_lastMorphLoopIndex >= 0 && loopIndex != _lastMorphLoopIndex) { activeAnimation.Stop(name); val3.time = 0f; activeAnimation.Play(name); } if (!activeAnimation.IsPlaying(name)) { activeAnimation.Play(name); } val3.time = num; activeAnimation.Sample(); _lastMorphLoopIndex = loopIndex; } } private void StopRuntimeMorphPlayback() { AnimationClip val = _loadedPrefab?.MorphClip; if ((Object)(object)val == (Object)null) { return; } Animation activeAnimation = _activeAnimation; if ((Object)(object)activeAnimation != (Object)null) { if ((Object)(object)activeAnimation.GetClip(((Object)val).name) != (Object)null) { activeAnimation.Stop(((Object)val).name); } if ((Object)(object)activeAnimation.clip != (Object)null && string.Equals(((Object)activeAnimation.clip).name, ((Object)val).name, StringComparison.Ordinal)) { activeAnimation.clip = null; } } _lastMorphLoopIndex = -1; } private GameObject ResolveMorphPlaybackHost(GameObject dancer) { if ((Object)(object)_activeAnimator != (Object)null) { return ((Component)_activeAnimator).gameObject; } Transform val = dancer.transform.Find("MikuLobbyModel"); if (!((Object)(object)val != (Object)null)) { return dancer; } return ((Component)val).gameObject; } private void SampleMorphClip(AnimationClip morphClip, Animator? animator, float timeSeconds) { GameObject activeDancer = _activeDancer; if (!((Object)(object)activeDancer == (Object)null)) { SampleMorphClipAtRoot(morphClip, activeDancer, timeSeconds); Transform val = activeDancer.transform.Find("MikuLobbyModel"); if ((Object)(object)val != (Object)null) { SampleMorphClipAtRoot(morphClip, ((Component)val).gameObject, timeSeconds); } GameObject val2 = (GameObject)(((Object)(object)animator != (Object)null) ? ((object)((Component)animator).gameObject) : ((object)ResolveMorphPlaybackHost(activeDancer))); if ((Object)(object)val2 != (Object)null) { SampleMorphClipAtRoot(morphClip, val2, timeSeconds); } } } private static void SampleMorphClipAtRoot(AnimationClip morphClip, GameObject root, float timeSeconds) { if (!((Object)(object)root == (Object)null)) { morphClip.SampleAnimation(root, timeSeconds); } } private void BeginAudioFade(AudioSource audioSource, float durationSeconds) { _fadingAudioSource = audioSource; _audioFadeStartTime = Time.unscaledTime; _audioFadeDuration = Mathf.Max(0.01f, durationSeconds); _audioFadeTargetVolume = _config?.ResolvedAudioVolume ?? 1f; audioSource.volume = 0f; } private void UpdateActiveAudioFade() { if ((Object)(object)_fadingAudioSource == (Object)null) { return; } DancePluginConfig? config = _config; if (config == null || !config.EnableAudio.Value || !_fadingAudioSource.isPlaying) { ClearActiveAudioFade(_fadingAudioSource); return; } float num = Mathf.Clamp01((Time.unscaledTime - _audioFadeStartTime) / _audioFadeDuration); _fadingAudioSource.volume = Mathf.Lerp(0f, _audioFadeTargetVolume, num); if (num >= 0.999f) { ClearActiveAudioFade(_fadingAudioSource); } } private bool IsActiveAudioFade(AudioSource? audioSource) { if ((Object)(object)audioSource != (Object)null) { return audioSource == _fadingAudioSource; } return false; } private void ClearActiveAudioFade(AudioSource? audioSource = null) { if (!((Object)(object)_fadingAudioSource == (Object)null) && (!((Object)(object)audioSource != (Object)null) || audioSource == _fadingAudioSource)) { if ((Object)(object)_fadingAudioSource != (Object)null) { _fadingAudioSource.volume = _config?.ResolvedAudioVolume ?? 1f; } _fadingAudioSource = null; _audioFadeStartTime = 0f; _audioFadeDuration = 0f; _audioFadeTargetVolume = 0f; } } private bool HandlePlaybackPause(GameObject dancer, Animator? animator, AudioSource? audioSource, AudioClip? audioClip) { bool flag = ShouldPauseForOfflineMenu(); float distanceMeters; bool flag2 = ShouldPauseForDistance(dancer, out distanceMeters); bool flag3 = _isPausedForOfflineMenu || _isPausedForDistance; _isPausedForOfflineMenu = flag; _isPausedForDistance = flag2; if (_isPausedForOfflineMenu || _isPausedForDistance) { if (!flag3) { _audioPausedForPlaybackPause = (Object)(object)audioSource != (Object)null && audioSource.isPlaying; if (_audioPausedForPlaybackPause) { ClearActiveAudioFade(audioSource); audioSource.Pause(); } if (flag && flag2) { LogVerbose($"Paused dancer playback because the offline menu is open and the local player is {distanceMeters:0.##}m away."); } else if (flag) { LogVerbose("Paused dancer playback because the offline menu is open."); } else { LogVerbose($"Paused dancer playback because the local player is {distanceMeters:0.##}m away, beyond the {100f:0.##}m optimization range."); } } SetPlaybackPausedState(animator, audioClip, paused: true); return true; } if (!flag3) { return false; } if (_audioPausedForPlaybackPause) { DancePluginConfig? config = _config; if (config != null && config.EnableAudio.Value && (Object)(object)audioSource != (Object)null && (Object)(object)audioClip != (Object)null) { audioSource.UnPause(); } } _audioPausedForPlaybackPause = false; SetPlaybackPausedState(animator, audioClip, paused: false); LogVerbose($"Resumed dancer playback because the local player is within {100f:0.##}m and no offline pause condition is active."); return false; } private void LogVerbose(string message) { if (EnableVerboseRuntimeLogs) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)message); } } } private bool ShouldPauseForDistance(GameObject dancer, out float distanceMeters) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) distanceMeters = 0f; if (!TryResolveCurrentLocalPlayerPose(out Vector3 position, out Vector3 _, out Transform _, out string _)) { return false; } Vector3 val = (_hasActivePlacement ? _activePlacement.Position : dancer.transform.position); distanceMeters = Vector3.Distance(position, val); return distanceMeters > 100f; } private void SetPlaybackPausedState(Animator? animator, AudioClip? audioClip, bool paused) { if ((Object)(object)animator != (Object)null) { animator.speed = (paused ? 0f : ResolveSynchronizedAnimatorSpeed(_activePrimaryAnimatorClip, audioClip)); ForceAnimatorLayerWeights(animator, 1f); } foreach (Animator item in EnumerateSecondaryAnimators()) { item.speed = (paused ? 0f : ResolveSynchronizedAnimatorSpeed(ResolveAnimatorPlaybackClip(item), audioClip)); ForceAnimatorLayerWeights(item, 1f); } if (ShouldUseDirectMorphSampling()) { return; } Animation activeAnimation = _activeAnimation; if ((Object)(object)activeAnimation == (Object)null || (Object)(object)activeAnimation.clip == (Object)null) { return; } AnimationState val = activeAnimation[((Object)activeAnimation.clip).name]; if (!((TrackedReference)(object)val == (TrackedReference)null)) { if (ShouldSynchronizeMorphWithAnimator()) { val.speed = 0f; } else { val.speed = (paused ? 0f : ResolveDesiredActiveAnimationSpeed(audioClip)); } } } private static bool ShouldPauseForOfflineMenu() { if (!PhotonNetwork.OfflineMode) { return false; } if (Time.timeScale <= 0.001f) { return true; } if (!(AllActiveWindowsField?.GetValue(null) is IEnumerable enumerable)) { return false; } bool flag = default(bool); foreach (object item in enumerable) { if (item != null) { object obj = MenuWindowIsOpenProperty?.GetValue(item, null); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } } return false; } private static AudioClip? ResolveAudioClip(AudioSource? audioSource) { if ((Object)(object)audioSource == (Object)null) { return null; } if ((Object)(object)audioSource.clip != (Object)null) { return audioSource.clip; } AudioResource resource = audioSource.resource; return (AudioClip?)(object)((resource is AudioClip) ? resource : null); } private void CacheActiveRuntimeComponents(GameObject? dancer) { if ((Object)(object)dancer == (Object)null) { ClearActiveRuntimeComponents(); return; } if (!_hasCachedRuntimeComponents || _cachedRuntimeComponentRoot != dancer) { _cachedRuntimeComponentRoot = dancer; _hasCachedRuntimeComponents = true; _activeAnimators = (from animator in dancer.GetComponentsInChildren(true) where (Object)(object)animator != (Object)null select animator).ToArray(); _activeAnimator = ResolvePrimaryRuntimeAnimator(_activeAnimators); _activeAnimation = dancer.GetComponentInChildren(true); _activeAudioSource = dancer.GetComponentInChildren(true); _cachedAnimatorController = null; _activePrimaryAnimatorClip = null; } RefreshCachedPrimaryAnimatorClip(); RefreshNativeFacialAnimationDetection(dancer); } private void ClearActiveRuntimeComponents() { _activeAnimator = null; _activeAnimators = Array.Empty(); _activeAnimation = null; _activeAudioSource = null; _activePrimaryAnimatorClip = null; _activeShadowBlob = null; _hasCachedRuntimeComponents = false; _cachedRuntimeComponentRoot = null; _cachedAnimatorController = null; _hasNativeFacialAnimationControl = false; } private void RefreshCachedPrimaryAnimatorClip() { Animator activeAnimator = _activeAnimator; RuntimeAnimatorController val = ((activeAnimator != null) ? activeAnimator.runtimeAnimatorController : null); if (val != _cachedAnimatorController) { _cachedAnimatorController = val; _activePrimaryAnimatorClip = (((Object)(object)activeAnimator != (Object)null && (Object)(object)val != (Object)null) ? ResolvePrimaryAnimatorClip(activeAnimator) : null); } } private static AnimationClip? ResolvePrimaryAnimatorClip(Animator animator) { RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController; AnimationClip[] array = ((runtimeAnimatorController != null) ? runtimeAnimatorController.animationClips : null); if (array == null || array.Length == 0) { return null; } AnimationClip result = null; float num = float.MinValue; foreach (AnimationClip val in array) { if (!((Object)(object)val == (Object)null) && !(val.length <= num)) { result = val; num = val.length; } } return result; } private static Animator? ResolvePrimaryRuntimeAnimator(IEnumerable animators) { return animators?.Where((Animator animator) => (Object)(object)animator != (Object)null).OrderBy(delegate(Animator animator) { RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController; return ((Object)(object)runtimeAnimatorController == (Object)null) ? 2 : (IsLikelyNativeFacialController(runtimeAnimatorController) ? 1 : 0); }).ThenByDescending(delegate(Animator animator) { AnimationClip? obj = ResolvePrimaryAnimatorClip(animator); return (obj == null) ? 0f : obj.length; }) .FirstOrDefault(); } private AnimationClip? ResolveSynchronizedAnimatorClip(Animator animator) { AnimationClip val = TryResolveCurrentAnimatorClip(animator); if ((Object)(object)val != (Object)null) { _activePrimaryAnimatorClip = val; return val; } RefreshCachedPrimaryAnimatorClip(); return _activePrimaryAnimatorClip; } private static AnimationClip? TryResolveCurrentAnimatorClip(Animator animator) { if ((Object)(object)animator == (Object)null) { return null; } try { AnimatorClipInfo[] currentAnimatorClipInfo = animator.GetCurrentAnimatorClipInfo(0); if (currentAnimatorClipInfo != null && currentAnimatorClipInfo.Length != 0) { AnimationClip val = currentAnimatorClipInfo.Select((AnimatorClipInfo info) => ((AnimatorClipInfo)(ref info)).clip).FirstOrDefault((Func)((AnimationClip clip) => (Object)(object)clip != (Object)null && clip.length > 0.01f)); if ((Object)(object)val != (Object)null) { return val; } } } catch { } try { AnimatorClipInfo[] nextAnimatorClipInfo = animator.GetNextAnimatorClipInfo(0); if (nextAnimatorClipInfo != null && nextAnimatorClipInfo.Length != 0) { AnimationClip val2 = nextAnimatorClipInfo.Select((AnimatorClipInfo info) => ((AnimatorClipInfo)(ref info)).clip).FirstOrDefault((Func)((AnimationClip clip) => (Object)(object)clip != (Object)null && clip.length > 0.01f)); if ((Object)(object)val2 != (Object)null) { return val2; } } } catch { } return null; } private void ApplyActiveAnimationPlaybackSpeed(AudioClip? audioClip) { if (ShouldUseDirectMorphSampling() || ShouldSynchronizeMorphWithAnimator()) { return; } Animation activeAnimation = _activeAnimation; AnimationClip val = ((activeAnimation != null) ? activeAnimation.clip : null); if (!((Object)(object)activeAnimation == (Object)null) && !((Object)(object)val == (Object)null)) { AnimationState val2 = activeAnimation[((Object)val).name]; if (!((TrackedReference)(object)val2 == (TrackedReference)null)) { val2.speed = ResolveDesiredActiveAnimationSpeed(audioClip); } } } private float ResolveDesiredActiveAnimationSpeed(AudioClip? audioClip) { Animation? activeAnimation = _activeAnimation; AnimationClip val = ((activeAnimation != null) ? activeAnimation.clip : null); if ((Object)(object)val == (Object)null || val.length <= 0.01f) { return 1f; } if ((Object)(object)_activeAnimator != (Object)null && (Object)(object)_activeAnimator.runtimeAnimatorController != (Object)null && (Object)(object)_activePrimaryAnimatorClip != (Object)null) { float targetLoopDurationSeconds = ResolveTargetLoopDurationSeconds(_activePrimaryAnimatorClip, audioClip); return ResolveAnimationPlaybackSpeed(val, targetLoopDurationSeconds); } float targetLoopDurationSeconds2 = ResolveTargetLoopDurationSeconds(val, audioClip); return ResolveAnimationPlaybackSpeed(val, targetLoopDurationSeconds2); } private bool SynchronizeAudioWithAnimator(Animator animator, AudioSource audioSource, AudioClip audioClip, AnimationClip? primaryClip, bool startIfNeeded, bool allowFadeOnStart, bool suppressFurtherRetries, bool logCorrections) { if (!TryResolveAnimatorAudioPosition(animator, primaryClip, audioClip, out var expectedAudioTime, out var animatorLoopIndex, out var segmentDuration)) { return false; } bool flag = _lastAnimatorLoopIndex >= 0 && animatorLoopIndex != _lastAnimatorLoopIndex; _lastAnimatorLoopIndex = animatorLoopIndex; if (!audioSource.isPlaying) { if (!startIfNeeded) { return false; } return StartAudioAtTime(audioSource, audioClip, expectedAudioTime, segmentDuration, allowFadeOnStart, suppressFurtherRetries, flag ? "animator loop restart" : "audio start"); } if (flag) { return StartAudioAtTime(audioSource, audioClip, expectedAudioTime, segmentDuration, allowFadeOnStart, suppressFurtherRetries, "animator loop restart"); } float num = Mathf.Clamp(audioSource.time, 0f, Mathf.Max(0f, audioClip.length - 0.01f)); float num2 = Mathf.Abs(num - expectedAudioTime); if (num2 < 1.25f) { if (logCorrections && num2 >= 0.35f) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)("Leaving minor audio drift uncorrected for '" + ((Object)audioClip).name + "' to avoid audible seek stutter. " + $"expected={expectedAudioTime:0.###}, current={num:0.###}, drift={num2:0.###}, loop={animatorLoopIndex}.")); } } return true; } if (logCorrections) { ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogInfo((object)($"Correcting audio drift for '{((Object)audioClip).name}'. expected={expectedAudioTime:0.###}, current={num:0.###}, " + $"drift={num2:0.###}, loop={animatorLoopIndex}.")); } } return StartAudioAtTime(audioSource, audioClip, expectedAudioTime, segmentDuration, fadeIn: false, suppressFurtherRetries, "hard resync"); } private bool TryResolveAnimatorAudioPosition(Animator animator, AnimationClip? primaryClip, AudioClip? audioClip, out float expectedAudioTime, out int animatorLoopIndex, out float segmentDuration) { expectedAudioTime = 0f; animatorLoopIndex = 0; segmentDuration = 0f; if ((Object)(object)audioClip == (Object)null || audioClip.length <= 0.01f) { return false; } float num = ResolveAudioSegmentStartSeconds(primaryClip, audioClip); segmentDuration = ResolveAudioSegmentDuration(primaryClip, audioClip); if (segmentDuration <= 0.01f) { return false; } ResolveAnimatorSegmentProgress(animator, primaryClip, out var loopProgress, out animatorLoopIndex); float num2 = Mathf.Min(audioClip.length, num + segmentDuration); expectedAudioTime = Mathf.Lerp(num, num2, loopProgress); expectedAudioTime = Mathf.Clamp(expectedAudioTime, num, Mathf.Max(num, num2 - 0.01f)); return true; } private bool StartAudioAtTime(AudioSource audioSource, AudioClip audioClip, float startTime, float segmentDuration, bool fadeIn, bool suppressFurtherRetries, string logReason) { if (!EnsureAudioClipReadyForPlayback(audioClip, suppressFurtherRetries, logReason)) { return false; } try { ClearActiveAudioFade(audioSource); audioSource.Stop(); audioSource.clip = audioClip; audioSource.loop = false; SeekAudioToTime(audioSource, audioClip, startTime); audioSource.volume = (fadeIn ? 0f : (_config?.ResolvedAudioVolume ?? 1f)); audioSource.Play(); if (fadeIn) { BeginAudioFade(audioSource, Mathf.Min(0.35f, segmentDuration * 0.5f)); } } catch (Exception ex) { if (suppressFurtherRetries) { _audioRetrySuppressed = true; } ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Audio playback failed for clip '" + ((Object)audioClip).name + "' during " + logReason + ": " + ex.Message)); } return false; } bool isPlaying = audioSource.isPlaying; if (!isPlaying && suppressFurtherRetries) { _audioRetrySuppressed = true; ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Audio playback could not start for clip '" + ((Object)audioClip).name + "' during " + logReason + ". Automatic retries are suppressed until audio is toggled again or the model is respawned.")); } } return isPlaying; } private void RequestAudioClipLoad(AudioClip? audioClip) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)audioClip == (Object)null) { return; } try { if ((int)audioClip.loadState == 0) { audioClip.LoadAudioData(); } } catch (Exception ex) { LogVerbose("Failed to request audio clip load for '" + ((Object)audioClip).name + "': " + ex.Message); } } private bool EnsureAudioClipReadyForPlayback(AudioClip audioClip, bool suppressFurtherRetries, string logReason) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if ((Object)(object)audioClip == (Object)null) { return false; } RequestAudioClipLoad(audioClip); AudioDataLoadState loadState = audioClip.loadState; if ((int)loadState == 2) { return true; } if ((int)loadState == 3) { if (suppressFurtherRetries) { _audioRetrySuppressed = true; } ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Audio clip '" + ((Object)audioClip).name + "' failed to load during " + logReason + ".")); } return false; } LogVerbose("Audio clip '" + ((Object)audioClip).name + "' is still loading during " + logReason + ". Playback will retry automatically."); return false; } private static void SeekAudioToTime(AudioSource audioSource, AudioClip audioClip, float timeSeconds) { float num = Mathf.Clamp(timeSeconds, 0f, Mathf.Max(0f, audioClip.length - 0.01f)); int num2 = Mathf.Max(0, audioClip.samples - 1); if (audioClip.frequency > 0 && num2 > 0) { try { int timeSamples = Mathf.Clamp(Mathf.RoundToInt(num * (float)audioClip.frequency), 0, num2); audioSource.timeSamples = timeSamples; return; } catch { } } audioSource.time = num; } private float ResolveSynchronizedAnimatorSpeed(AnimationClip? animationClip, AudioClip? audioClip) { if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return 1f; } if (ShouldPreserveOriginalAnimatorTiming(animationClip)) { return 1f; } if ((Object)(object)audioClip == (Object)null || audioClip.length <= 0.01f) { return 1f; } float num = ResolveMotionSegmentDurationSeconds(animationClip); float num2 = ResolveAudioSegmentDuration(animationClip, audioClip); if (num2 <= 0.01f || num <= 0.01f) { return 1f; } return Mathf.Clamp(num / num2, 0.25f, 4f); } private bool ShouldPreserveOriginalAnimatorTiming(AnimationClip? animationClip) { if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return true; } DancePlaybackMetadata dancePlaybackMetadata = ResolvePlaybackMetadata(); float num = dancePlaybackMetadata.ResolveMotionStartSeconds(animationClip.length); float num2 = dancePlaybackMetadata.ResolveMotionEndSeconds(animationClip.length); if (num <= 0.01f) { return num2 >= animationClip.length - 0.01f; } return false; } private float ResolveAudioSegmentStartSeconds(AnimationClip? animationClip, AudioClip? audioClip) { if ((Object)(object)audioClip == (Object)null || audioClip.length <= 0.01f) { return 0f; } return Mathf.Clamp(ResolvePlaybackMetadata().ResolveAudioSegmentStartSeconds(), 0f, Mathf.Max(0f, audioClip.length - 0.01f)); } private float ResolveAudioSegmentDuration(AnimationClip? animationClip, AudioClip? audioClip) { if ((Object)(object)audioClip == (Object)null || audioClip.length <= 0.01f) { return 0f; } return ResolvePlaybackMetadata().ResolveAudioSegmentDurationSeconds(ResolveMotionSegmentDurationSeconds(animationClip), audioClip.length); } private float ResolveTargetLoopDurationSeconds(AnimationClip? animationClip, AudioClip? audioClip) { if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return 0f; } if ((Object)(object)audioClip == (Object)null) { return ResolveMotionSegmentDurationSeconds(animationClip); } float num = ResolveAudioSegmentDuration(animationClip, audioClip); if (!(num > 0.01f)) { return ResolveMotionSegmentDurationSeconds(animationClip); } return num; } private static float ResolveAnimationPlaybackSpeed(AnimationClip animationClip, float targetLoopDurationSeconds) { if (animationClip.length <= 0.01f || targetLoopDurationSeconds <= 0.01f) { return 1f; } return Mathf.Clamp(animationClip.length / targetLoopDurationSeconds, 0.25f, 4f); } private DancePlaybackMetadata ResolvePlaybackMetadata() { DancePlaybackMetadata dancePlaybackMetadata = _loadedPrefab?.PlaybackMetadata; if (dancePlaybackMetadata != null) { return dancePlaybackMetadata; } LegacyPlaybackMetadata.SourceFrameRate = 30f; LegacyPlaybackMetadata.MotionStartFrame = Mathf.RoundToInt(0f); LegacyPlaybackMetadata.HasMotionEndFrame = false; LegacyPlaybackMetadata.MotionEndFrame = 0; LegacyPlaybackMetadata.AudioSegmentStartSeconds = 0f; LegacyPlaybackMetadata.AudioSegmentDurationSeconds = 0f; return LegacyPlaybackMetadata; } private float ResolveMotionSegmentStartSeconds(AnimationClip? animationClip) { if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return 0f; } return ResolvePlaybackMetadata().ResolveMotionStartSeconds(animationClip.length); } private float ResolveMotionSegmentDurationSeconds(AnimationClip? animationClip) { if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return 0f; } return ResolvePlaybackMetadata().ResolveMotionSegmentDurationSeconds(animationClip.length); } private bool TryResolveMotionSegmentNormalizedRange(AnimationClip? animationClip, out float startNormalized, out float durationNormalized, out float durationSeconds) { startNormalized = 0f; durationNormalized = 1f; durationSeconds = 0f; if ((Object)(object)animationClip == (Object)null || animationClip.length <= 0.01f) { return false; } DancePlaybackMetadata dancePlaybackMetadata = ResolvePlaybackMetadata(); float num = dancePlaybackMetadata.ResolveMotionStartSeconds(animationClip.length); float num2 = dancePlaybackMetadata.ResolveMotionEndSeconds(animationClip.length); durationSeconds = Mathf.Max(0f, num2 - num); if (durationSeconds <= 0.01f) { durationSeconds = animationClip.length; return false; } if (num <= 0.01f && num2 >= animationClip.length - 0.01f) { return false; } startNormalized = Mathf.Clamp01(num / animationClip.length); durationNormalized = Mathf.Clamp(durationSeconds / animationClip.length, 0.0001f, 1f); return true; } private void ResolveAnimatorSegmentProgress(Animator animator, AnimationClip? primaryClip, out float loopProgress, out int loopIndex) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) loopProgress = 0f; loopIndex = 0; AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); float num = Mathf.Max(0f, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime); if (!TryResolveMotionSegmentNormalizedRange(primaryClip, out var startNormalized, out var durationNormalized, out var _)) { loopIndex = Mathf.Max(0, Mathf.FloorToInt(num)); loopProgress = Mathf.Repeat(num, 1f); } else if (num <= startNormalized + 0.0001f) { loopProgress = 0f; loopIndex = Mathf.Max(0, _animatorSegmentLoopIndex); } else { float num2 = Mathf.Repeat(Mathf.Max(0f, num - startNormalized), durationNormalized); loopProgress = ((durationNormalized > 0.0001f) ? Mathf.Clamp01(num2 / durationNormalized) : 0f); loopIndex = Mathf.Max(0, _animatorSegmentLoopIndex); } } private void MaintainAnimatorSegmentLoop(Animator animator, AnimationClip? primaryClip) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)animator == (Object)null || (Object)(object)primaryClip == (Object)null || primaryClip.length <= 0.01f) { return; } if (!TryResolveMotionSegmentNormalizedRange(primaryClip, out var startNormalized, out var durationNormalized, out var _)) { AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).loop && !((Motion)primaryClip).isLooping) { float num = Mathf.Max(0f, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime); if (!(num < 0.9999f)) { _animatorSegmentLoopIndex += Mathf.Max(1, Mathf.FloorToInt(num)); animator.Play(0, 0, 0f); animator.Update(0f); } } return; } AnimatorStateInfo currentAnimatorStateInfo2 = animator.GetCurrentAnimatorStateInfo(0); float num2 = Mathf.Max(0f, ((AnimatorStateInfo)(ref currentAnimatorStateInfo2)).normalizedTime); if (num2 + 0.0001f < startNormalized) { animator.Play(0, 0, startNormalized); animator.Update(0f); return; } float num3 = Mathf.Max(0f, num2 - startNormalized); if (!(num3 < durationNormalized - 0.0001f)) { int num4 = Mathf.Max(1, Mathf.FloorToInt(num3 / durationNormalized)); _animatorSegmentLoopIndex += num4; float num5 = Mathf.Repeat(num3, durationNormalized); float num6 = startNormalized + num5; if (!(Mathf.Abs(num6 - num2) <= 0.0001f)) { animator.Play(0, 0, num6); animator.Update(0f); } } } private void StartAnimatorAtBeginning(Animator animator, AnimationClip? primaryClip) { _animatorSegmentLoopIndex = 0; _lastAnimatorLoopIndex = -1; _lastMorphLoopIndex = -1; float num = 0f; if ((Object)(object)primaryClip != (Object)null && primaryClip.length > 0.01f) { num = Mathf.Clamp01(ResolveMotionSegmentStartSeconds(primaryClip) / primaryClip.length); } animator.Play(0, 0, num); animator.Update(0f); } private bool ShouldUseDirectMorphSampling() { return ShouldSynchronizeMorphWithAnimator(); } [IteratorStateMachine(typeof(d__234))] private IEnumerable EnumerateSecondaryAnimators() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__234(-2) { <>4__this = this }; } private bool ShouldSynchronizeMorphWithAnimator() { if ((Object)(object)_loadedPrefab?.MorphClip != (Object)null && !_hasNativeFacialAnimationControl && (Object)(object)_activeAnimator != (Object)null && (Object)(object)_activeAnimator.runtimeAnimatorController != (Object)null) { return (Object)(object)_activePrimaryAnimatorClip != (Object)null; } return false; } private void ConfigureSecondaryNativeAnimators(AnimationClip? primaryClip, float animationSpeed) { foreach (Animator item in EnumerateSecondaryAnimators()) { item.cullingMode = (AnimatorCullingMode)0; item.applyRootMotion = false; item.updateMode = (AnimatorUpdateMode)0; item.speed = animationSpeed; ForceAnimatorLayerWeights(item, 1f); item.Rebind(); item.Update(0f); AnimationClip targetClip = ResolveAnimatorPlaybackClip(item); float num = ResolveClipStartNormalized(primaryClip, targetClip); item.Play(0, 0, num); item.Update(0f); } } private void RefreshSecondaryNativeAnimators(Animator primaryAnimator, AnimationClip? primaryClip) { if (_hasNativeFacialAnimationControl) { SynchronizeNativeFacialAnimatorsWithPrimary(primaryAnimator, primaryClip); } } private void SynchronizeNativeFacialAnimatorsWithPrimary(Animator primaryAnimator, AnimationClip? primaryClip) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)primaryAnimator == (Object)null) { return; } ResolveAnimatorSegmentProgress(primaryAnimator, primaryClip, out var loopProgress, out var _); foreach (Animator item in EnumerateSecondaryAnimators()) { AnimationClip val = ResolveAnimatorPlaybackClip(item); if (!((Object)(object)val == (Object)null) && !(val.length <= 0.01f)) { item.cullingMode = (AnimatorCullingMode)0; item.applyRootMotion = false; item.updateMode = (AnimatorUpdateMode)0; item.speed = primaryAnimator.speed; ForceAnimatorLayerWeights(item, 1f); float num = Mathf.Clamp01(loopProgress); AnimatorStateInfo currentAnimatorStateInfo = item.GetCurrentAnimatorStateInfo(0); float num2 = Mathf.Max(0f, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime); float num3 = Mathf.Abs(Mathf.DeltaAngle(Mathf.Repeat(num2, 1f) * 360f, num * 360f)) / 360f; if ((!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).loop && !((Motion)val).isLooping && num2 >= 0.999f && num <= 0.98f) || !(num3 <= 0.02f) || !(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length > 0f)) { item.Play(0, 0, num); item.Update(0f); } } } } private static AnimationClip? ResolveAnimatorPlaybackClip(Animator animator) { if ((Object)(object)animator == (Object)null) { return null; } return TryResolveCurrentAnimatorClip(animator) ?? ResolvePrimaryAnimatorClip(animator); } private float ResolveClipStartNormalized(AnimationClip? timingReferenceClip, AnimationClip? targetClip) { if ((Object)(object)targetClip == (Object)null || targetClip.length <= 0.01f) { return 0f; } return Mathf.Clamp01((((Object)(object)timingReferenceClip != (Object)null) ? Mathf.Max(0f, ResolveMotionSegmentStartSeconds(timingReferenceClip)) : 0f) / targetClip.length); } private static void ForceAnimatorLayerWeights(Animator animator, float weight) { if (!((Object)(object)animator == (Object)null)) { for (int i = 0; i < animator.layerCount; i++) { animator.SetLayerWeight(i, weight); } } } private bool HasNativeFacialAnimationControl(GameObject? dancer) { if ((Object)(object)dancer == (Object)null) { return false; } if (_hasCachedRuntimeComponents && _cachedRuntimeComponentRoot == dancer) { return _hasNativeFacialAnimationControl; } return DetectNativeFacialAnimationControl(dancer); } private void RefreshNativeFacialAnimationDetection(GameObject? dancer) { bool flag = DetectNativeFacialAnimationControl(dancer); if (_hasNativeFacialAnimationControl != flag) { LogVerbose($"Native facial animation detection changed: {flag}."); } _hasNativeFacialAnimationControl = flag; } private bool DetectNativeFacialAnimationControl(GameObject? dancer) { if ((Object)(object)dancer == (Object)null) { return false; } Animator[] array = (from animator in dancer.GetComponentsInChildren(true) where (Object)(object)animator != (Object)null && (Object)(object)animator.runtimeAnimatorController != (Object)null select animator).ToArray(); if (array.Length > 1) { return true; } for (int i = 0; i < array.Length; i++) { RuntimeAnimatorController runtimeAnimatorController = array[i].runtimeAnimatorController; if (!((Object)(object)runtimeAnimatorController == (Object)null) && IsLikelyNativeFacialController(runtimeAnimatorController)) { return true; } } return false; } private static bool IsLikelyNativeFacialController(RuntimeAnimatorController controller) { if ((Object)(object)controller == (Object)null) { return false; } if (ContainsFacialToken(((Object)controller).name)) { return true; } AnimationClip[] animationClips = controller.animationClips; if (animationClips == null || animationClips.Length == 0) { return false; } foreach (AnimationClip val in animationClips) { if (!((Object)(object)val == (Object)null) && ContainsFacialToken(((Object)val).name)) { return true; } } return false; } private static bool ContainsFacialToken(string? value) { string text = value ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return false; } for (int i = 0; i < NativeFacialClipTokens.Length; i++) { string value2 = NativeFacialClipTokens[i]; if (!string.IsNullOrEmpty(value2) && text.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } } internal readonly struct GroundSampleCandidate { public float Y { get; } public float VerticalDelta { get; } public float HorizontalDelta { get; } public float RaycastDistance { get; } public GroundSampleCandidate(float y, float verticalDelta, float horizontalDelta, float raycastDistance) { Y = y; VerticalDelta = verticalDelta; HorizontalDelta = horizontalDelta; RaycastDistance = raycastDistance; } public bool IsBetterThan(GroundSampleCandidate other) { if (VerticalDelta < other.VerticalDelta - 0.001f) { return true; } if (Mathf.Abs(VerticalDelta - other.VerticalDelta) > 0.001f) { return false; } if (HorizontalDelta < other.HorizontalDelta - 0.001f) { return true; } if (Mathf.Abs(HorizontalDelta - other.HorizontalDelta) > 0.001f) { return false; } return RaycastDistance < other.RaycastDistance; } } internal static class DancePhysicsConfigurator { private static readonly string[] HairPatterns = new string[8] { "ツインテ", "テール", "髪", "前髪", "横髪", "後髪", "おさげ", "ahoge" }; private static readonly string[] SkirtPatterns = new string[6] { "スカート", "skirt", "裾", "ひら", "リボン", "ネクタイ" }; public static void Apply(GameObject instanceRoot) { Transform[] componentsInChildren = instanceRoot.GetComponentsInChildren(true); AttachDynamicBones(componentsInChildren, HairPatterns, ConfigureHair); AttachDynamicBones(componentsInChildren, SkirtPatterns, ConfigureSkirt); } private static void AttachDynamicBones(IEnumerable transforms, IReadOnlyList patterns, Action configure) { IReadOnlyList patterns2 = patterns; Transform[] array = (from transform in transforms where transform.childCount > 0 where ContainsPattern(((Object)transform).name, patterns2) where !AncestorMatches(transform, patterns2) select transform).ToArray(); foreach (Transform val in array) { DynamicBone val2 = ((Component)val).gameObject.GetComponent() ?? ((Component)val).gameObject.AddComponent(); val2.m_Root = val; configure(val2); val2.SetupParticles(); } } private static void ConfigureHair(DynamicBone dynamicBone) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) dynamicBone.m_Damping = 0.12f; dynamicBone.m_Elasticity = 0.08f; dynamicBone.m_Stiffness = 0.12f; dynamicBone.m_Inert = 0.35f; dynamicBone.m_Friction = 0.03f; dynamicBone.m_Radius = 0.02f; dynamicBone.m_EndLength = 0.05f; dynamicBone.m_Gravity = new Vector3(0f, -0.12f, 0f); dynamicBone.m_Force = new Vector3(0f, 0f, 0.02f); } private static void ConfigureSkirt(DynamicBone dynamicBone) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) dynamicBone.m_Damping = 0.18f; dynamicBone.m_Elasticity = 0.04f; dynamicBone.m_Stiffness = 0.2f; dynamicBone.m_Inert = 0.22f; dynamicBone.m_Friction = 0.04f; dynamicBone.m_Radius = 0.03f; dynamicBone.m_EndLength = 0.03f; dynamicBone.m_Gravity = new Vector3(0f, -0.22f, 0f); dynamicBone.m_Force = Vector3.zero; } private static bool ContainsPattern(string name, IReadOnlyList patterns) { string name2 = name; return patterns.Any((string pattern) => name2.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0); } private static bool AncestorMatches(Transform transform, IReadOnlyList patterns) { Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { if (ContainsPattern(((Object)parent).name, patterns)) { return true; } parent = parent.parent; } return false; } } [Serializable] internal sealed class DancePlaybackMetadata { public float SourceFrameRate = 30f; public int MotionStartFrame; public bool HasMotionEndFrame; public int MotionEndFrame; public float AudioSegmentStartSeconds; public float AudioSegmentDurationSeconds; public static DancePlaybackMetadata CreateDefault() { return new DancePlaybackMetadata { SourceFrameRate = 30f, MotionStartFrame = 0, HasMotionEndFrame = false, MotionEndFrame = 0, AudioSegmentStartSeconds = 0f, AudioSegmentDurationSeconds = 0f }; } public float ResolveAudioSegmentStartSeconds() { return Mathf.Max(0f, AudioSegmentStartSeconds); } public float ResolveMotionStartSeconds(float animationClipLength) { float num = Mathf.Max(0f, animationClipLength); float num2 = ((SourceFrameRate > 0.01f) ? SourceFrameRate : 30f); return Mathf.Clamp(Mathf.Max(0f, (float)MotionStartFrame) / num2, 0f, num); } public float ResolveMotionEndSeconds(float animationClipLength) { float num = Mathf.Max(0f, animationClipLength); float num2 = ResolveMotionStartSeconds(num); if (!HasMotionEndFrame || MotionEndFrame <= MotionStartFrame) { return num; } float num3 = ((SourceFrameRate > 0.01f) ? SourceFrameRate : 30f); return Mathf.Clamp((float)Mathf.Max(MotionStartFrame, MotionEndFrame) / num3, num2, num); } public float ResolveMotionSegmentDurationSeconds(float animationClipLength) { float num = Mathf.Max(0f, animationClipLength); float num2 = ResolveMotionStartSeconds(num); float num3 = ResolveMotionEndSeconds(num); float num4 = Mathf.Max(0f, num3 - num2); if (!(num4 > 0.01f)) { return num; } return num4; } public float ResolveAudioSegmentDurationSeconds(float animationClipLength, float audioClipLength) { float num = ResolveAudioSegmentStartSeconds(); float num2 = Mathf.Max(0f, audioClipLength - num); float num3 = Mathf.Max(0f, AudioSegmentDurationSeconds); if (num3 > 0.01f) { return Mathf.Min(num3, num2); } if (animationClipLength > 0.01f) { return Mathf.Min(animationClipLength, num2); } return num2; } } internal sealed class LoadedDancePrefab { public GameObject Template { get; } public AnimationClip? Clip { get; } public AnimationClip? MorphClip { get; } public DancePlaybackMetadata? PlaybackMetadata { get; } public float LocalMinY { get; } public float LocalHeight { get; } public Vector3 LocalBoundsCenter { get; } public LoadedPrefabSource Source { get; } public LoadedDancePrefab(GameObject template, AnimationClip? clip, AnimationClip? morphClip, DancePlaybackMetadata? playbackMetadata, float localMinY, float localHeight, Vector3 localBoundsCenter, LoadedPrefabSource source) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Template = template; Clip = clip; MorphClip = morphClip; PlaybackMetadata = playbackMetadata; LocalMinY = localMinY; LocalHeight = localHeight; LocalBoundsCenter = localBoundsCenter; Source = source; } } internal enum LoadedPrefabSource { UnityAssetBundle = 1 } internal sealed class MikuFacialExpressionController : MonoBehaviour { private readonly struct BlendShapeBinding { public SkinnedMeshRenderer Renderer { get; } public int Index { get; } public string Name { get; } public BlendShapeBinding(SkinnedMeshRenderer renderer, int index, string name) { Renderer = renderer; Index = index; Name = name; } } private readonly struct FacialShapeGroup { public string Key { get; } public string[] ExactAliases { get; } public string[] PartialAliases { get; } public FacialShapeGroup(string key, string[] exactAliases, string[] partialAliases) { Key = key; ExactAliases = exactAliases; PartialAliases = partialAliases; } public bool Matches(string rawName, string normalizedName) { for (int i = 0; i < ExactAliases.Length; i++) { string text = NormalizeName(ExactAliases[i]); if (string.Equals(rawName, ExactAliases[i], StringComparison.OrdinalIgnoreCase) || string.Equals(normalizedName, text, StringComparison.Ordinal) || (!string.IsNullOrWhiteSpace(text) && normalizedName.EndsWith(text, StringComparison.Ordinal))) { return true; } } for (int j = 0; j < PartialAliases.Length; j++) { string value = NormalizeName(PartialAliases[j]); if (!string.IsNullOrWhiteSpace(value) && normalizedName.IndexOf(value, StringComparison.Ordinal) >= 0) { return true; } } return false; } } private readonly struct BoneCandidate { public Transform Transform { get; } public int Score { get; } public BoneCandidate(Transform transform, int score) { Transform = transform; Score = score; } } private readonly struct BonePoseBinding { public Transform Transform { get; } public Vector3 ClosedLocalPosition { get; } public Quaternion ClosedLocalRotation { get; } public BonePoseBinding(Transform transform, Vector3 closedLocalPosition, Quaternion closedLocalRotation) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Transform = transform; ClosedLocalPosition = closedLocalPosition; ClosedLocalRotation = closedLocalRotation; } } private static readonly bool EnableVerboseFacialLogs = false; private const string MouthAGroupKey = "MouthA"; private const string MouthIGroupKey = "MouthI"; private const string MouthUGroupKey = "MouthU"; private const string MouthEGroupKey = "MouthE"; private const string MouthOGroupKey = "MouthO"; private const string SmileGroupKey = "Smile"; private static readonly string[] MouthShapePriority = new string[5] { "MouthA", "MouthI", "MouthU", "MouthE", "MouthO" }; private static readonly FacialShapeGroup[] ManagedShapeGroups = new FacialShapeGroup[6] { new FacialShapeGroup("MouthA", new string[5] { "あ", "あ2", "a", "aa", "A" }, new string[7] { "moutha", "mouthaa", "phonemea", "visemeaa", "vaa", "jawopen", "mouthopen" }), new FacialShapeGroup("MouthI", new string[3] { "い", "i", "I" }, new string[4] { "mouthi", "phonemei", "visemeih", "vih" }), new FacialShapeGroup("MouthU", new string[3] { "う", "u", "U" }, new string[4] { "mouthu", "phonemeu", "visemeou", "vou" }), new FacialShapeGroup("MouthE", new string[3] { "え", "e", "E" }, new string[4] { "mouthe", "phonemee", "visemee", "ve" }), new FacialShapeGroup("MouthO", new string[3] { "お", "o", "O" }, new string[5] { "moutho", "phonemeo", "visemeoh", "voh", "mouthround" }), new FacialShapeGroup("Smile", new string[4] { "笑い", "smile", "Smile", "口角上げ" }, new string[4] { "warai", "happy", "grin", "mouthsmile" }) }; private static readonly string[] JawBoneTokens = new string[6] { "jaw", "chin", "顎", "あご", "下顎", "下あご" }; private static readonly string[] LipBoneTokens = new string[5] { "mouth", "lip", "口", "くち", "唇" }; private static readonly string[] ExcludedBoneTokens = new string[12] { "eye", "瞳", "眉", "brow", "nose", "鼻", "hair", "髪", "ear", "耳", "cheek", "頬" }; private const float SmileWeight = 10f; private const float MinimumMouthWeight = 4f; private const float MouthWeightSmoothing = 10f; private const float AudioAmplitudeScale = 28f; private const float JawOpenAngleDegrees = 10f; private const float JawOpenOffsetMeters = 0.005f; private const float LipOpenOffsetMeters = 0.0035f; private const int LoggedBlendShapeNamesPerRenderer = 12; private const float BlendShapeWeightChangeEpsilon = 0.1f; private readonly Dictionary> _bindingsByGroupKey = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly List _jawBindings = new List(); private readonly List _lipBindings = new List(); private readonly float[] _audioSamples = new float[256]; private AudioSource? _audioSource; private Animator? _animator; private ManualLogSource? _logger; private bool _initialized; private float _currentMouthWeight; private string? _lastPrimaryShapeGroupKey; private string? _appliedPrimaryShapeGroupKey; private float _appliedPrimaryShapeWeight; private bool _smileWeightApplied; public void Initialize(AudioSource? audioSource, Animator? animator, ManualLogSource? logger) { ((Behaviour)this).enabled = true; _audioSource = audioSource; _animator = animator; _logger = logger; _bindingsByGroupKey.Clear(); _jawBindings.Clear(); _lipBindings.Clear(); ResetAppliedManagedShapeState(); List list = new List(); SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { Mesh sharedMesh = val.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { continue; } List list2 = new List(Mathf.Min(sharedMesh.blendShapeCount, 12)); for (int j = 0; j < sharedMesh.blendShapeCount; j++) { string blendShapeName = sharedMesh.GetBlendShapeName(j); if (list2.Count < 12) { list2.Add(string.IsNullOrWhiteSpace(blendShapeName) ? $"#{j}" : blendShapeName); } if (!string.IsNullOrWhiteSpace(blendShapeName) && TryResolveManagedShapeGroup(blendShapeName, out string groupKey)) { if (!_bindingsByGroupKey.TryGetValue(groupKey, out List value)) { value = new List(); _bindingsByGroupKey.Add(groupKey, value); } value.Add(new BlendShapeBinding(val, j, blendShapeName)); } } list.Add(string.Format("{0}:{1}[{2}{3}]", ((Object)val).name, sharedMesh.blendShapeCount, string.Join(", ", list2), (sharedMesh.blendShapeCount > list2.Count) ? ", ..." : string.Empty)); } DiscoverBoneBindings(); _initialized = true; if (_bindingsByGroupKey.Count == 0 && _jawBindings.Count == 0 && _lipBindings.Count == 0) { ((Behaviour)this).enabled = false; LogVerbose("Facial expression controller disabled because no supported blendshapes or mouth bones were found on the loaded model. Skinned renderers: " + ((list.Count == 0) ? "(none)" : string.Join(" | ", list)) + "."); return; } string text = ((_bindingsByGroupKey.Count == 0) ? "(none)" : string.Join(", ", _bindingsByGroupKey.Keys.OrderBy((string name) => name, StringComparer.OrdinalIgnoreCase))); string text2 = ((_jawBindings.Count == 0) ? "(none)" : string.Join(", ", _jawBindings.Select((BonePoseBinding binding) => ((Object)binding.Transform).name))); string text3 = ((_lipBindings.Count == 0) ? "(none)" : string.Join(", ", _lipBindings.Select((BonePoseBinding binding) => ((Object)binding.Transform).name))); LogVerbose("Facial expression controller initialized. blendshapeGroups=[" + text + "], jawBones=[" + text2 + "], lipBones=[" + text3 + "], skinnedRenderers=" + ((list.Count == 0) ? "(none)" : string.Join(" | ", list)) + "."); ResetManagedWeights(); ApplySmileWeight(); } private void LateUpdate() { if (_initialized) { float mouthWeight = ResolveMouthWeight(); string text = ResolvePrimaryMouthShapeGroupKey(mouthWeight); UpdateManagedWeights(text, mouthWeight); ApplySmileWeight(); ApplyBoneMouthPose(mouthWeight); _lastPrimaryShapeGroupKey = text; } } private float ResolveMouthWeight() { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) float num = 0f; if ((Object)(object)_audioSource != (Object)null && (Object)(object)_audioSource.clip != (Object)null && _audioSource.isPlaying) { try { _audioSource.GetOutputData(_audioSamples, 0); float num2 = 0f; for (int i = 0; i < _audioSamples.Length; i++) { num2 += _audioSamples[i] * _audioSamples[i]; } num = Mathf.Clamp(Mathf.Sqrt(num2 / (float)_audioSamples.Length) * 28f * 100f, 0f, 100f); } catch (Exception ex) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Facial expression audio sampling failed: " + ex.Message)); } } } else if ((Object)(object)_animator != (Object)null && (Object)(object)_animator.runtimeAnimatorController != (Object)null) { AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0); num = Mathf.Clamp01(Mathf.Sin(Mathf.Repeat(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime, 1f) * (float)Math.PI * 8f) * 0.5f + 0.5f) * 18f; } _currentMouthWeight = Mathf.Lerp(_currentMouthWeight, num, Time.deltaTime * 10f); return _currentMouthWeight; } private string? ResolvePrimaryMouthShapeGroupKey(float mouthWeight) { if (mouthWeight <= 4f) { return null; } float num = 0f; if ((Object)(object)_audioSource != (Object)null && (Object)(object)_audioSource.clip != (Object)null) { num = _audioSource.time; } else if ((Object)(object)_animator != (Object)null) { num = Time.time; } string[] array = (Mathf.Abs(Mathf.FloorToInt(num * 7f)) % 5) switch { 0 => new string[2] { "MouthA", "MouthO" }, 1 => new string[2] { "MouthI", "MouthE" }, 2 => new string[2] { "MouthU", "MouthO" }, 3 => new string[2] { "MouthE", "MouthI" }, _ => new string[2] { "MouthO", "MouthA" }, }; foreach (string text in array) { if (_bindingsByGroupKey.ContainsKey(text)) { return text; } } array = MouthShapePriority; foreach (string text2 in array) { if (_bindingsByGroupKey.ContainsKey(text2)) { return text2; } } return _lastPrimaryShapeGroupKey; } private void ResetManagedWeights() { foreach (List value in _bindingsByGroupKey.Values) { foreach (BlendShapeBinding item in value) { item.Renderer.SetBlendShapeWeight(item.Index, 0f); } } } private void ApplySmileWeight() { if (!_smileWeightApplied && _bindingsByGroupKey.ContainsKey("Smile")) { ApplyWeight("Smile", 10f); _smileWeightApplied = true; } } private void ApplyWeight(string groupKey, float weight) { if (_bindingsByGroupKey.TryGetValue(groupKey, out List value)) { for (int i = 0; i < value.Count; i++) { value[i].Renderer.SetBlendShapeWeight(value[i].Index, weight); } } } private void UpdateManagedWeights(string? primaryShapeGroupKey, float mouthWeight) { string text = ((!string.IsNullOrWhiteSpace(primaryShapeGroupKey) && mouthWeight > 4f) ? primaryShapeGroupKey : null); float num = ((text == null) ? 0f : mouthWeight); if (!string.IsNullOrWhiteSpace(_appliedPrimaryShapeGroupKey) && !string.Equals(_appliedPrimaryShapeGroupKey, text, StringComparison.OrdinalIgnoreCase)) { ApplyWeight(_appliedPrimaryShapeGroupKey, 0f); _appliedPrimaryShapeGroupKey = null; _appliedPrimaryShapeWeight = 0f; } if (string.IsNullOrWhiteSpace(text)) { if (!string.IsNullOrWhiteSpace(_appliedPrimaryShapeGroupKey) && _appliedPrimaryShapeWeight > 0.001f) { ApplyWeight(_appliedPrimaryShapeGroupKey, 0f); } _appliedPrimaryShapeGroupKey = null; _appliedPrimaryShapeWeight = 0f; } else if (!string.Equals(_appliedPrimaryShapeGroupKey, text, StringComparison.OrdinalIgnoreCase) || Mathf.Abs(_appliedPrimaryShapeWeight - num) > 0.1f) { ApplyWeight(text, num); _appliedPrimaryShapeGroupKey = text; _appliedPrimaryShapeWeight = num; } } private void ResetAppliedManagedShapeState() { _appliedPrimaryShapeGroupKey = null; _appliedPrimaryShapeWeight = 0f; _smileWeightApplied = false; } private void ApplyBoneMouthPose(float mouthWeight) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01((mouthWeight - 4f) / 96f); for (int i = 0; i < _jawBindings.Count; i++) { BonePoseBinding bonePoseBinding = _jawBindings[i]; bonePoseBinding.Transform.localRotation = bonePoseBinding.ClosedLocalRotation * Quaternion.Euler(-10f * num, 0f, 0f); bonePoseBinding.Transform.localPosition = bonePoseBinding.ClosedLocalPosition + ResolveLocalDownDirection(bonePoseBinding.Transform) * (0.005f * num); } for (int j = 0; j < _lipBindings.Count; j++) { BonePoseBinding bonePoseBinding2 = _lipBindings[j]; bonePoseBinding2.Transform.localRotation = bonePoseBinding2.ClosedLocalRotation; bonePoseBinding2.Transform.localPosition = bonePoseBinding2.ClosedLocalPosition + ResolveLocalDownDirection(bonePoseBinding2.Transform) * (0.0035f * num); } } private void DiscoverBoneBindings() { HashSet hashSet = new HashSet(); AddTopBoneBindings(_jawBindings, JawBoneTokens, hashSet, 2); foreach (BonePoseBinding jawBinding in _jawBindings) { hashSet.Add(jawBinding.Transform); } AddTopBoneBindings(_lipBindings, LipBoneTokens, hashSet, 2); } private void AddTopBoneBindings(ICollection destination, IEnumerable tokens, ISet excludedTransforms, int maxCount) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) ISet excludedTransforms2 = excludedTransforms; IEnumerable tokens2 = tokens; BoneCandidate[] array = (from candidate in ((Component)this).GetComponentsInChildren(true) where (Object)(object)candidate != (Object)(object)((Component)this).transform where !excludedTransforms2.Contains(candidate) select new BoneCandidate(candidate, ScoreBoneCandidate(((Object)candidate).name, tokens2)) into candidate where candidate.Score > 0 orderby candidate.Score descending, ((Object)candidate.Transform).name.Length select candidate).ThenBy((BoneCandidate candidate) => ((Object)candidate.Transform).name, StringComparer.OrdinalIgnoreCase).Take(maxCount).ToArray(); for (int i = 0; i < array.Length; i++) { destination.Add(new BonePoseBinding(array[i].Transform, array[i].Transform.localPosition, array[i].Transform.localRotation)); } } private void LogVerbose(string message) { if (EnableVerboseFacialLogs) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)message); } } } private static int ScoreBoneCandidate(string candidateName, IEnumerable tokens) { string normalizedName = NormalizeName(candidateName); if (string.IsNullOrWhiteSpace(normalizedName)) { return 0; } if (ExcludedBoneTokens.Any((string token) => normalizedName.IndexOf(NormalizeName(token), StringComparison.Ordinal) >= 0)) { return 0; } int num = 0; foreach (string token in tokens) { string text = NormalizeName(token); if (normalizedName == text) { num = Mathf.Max(num, 300); } else if (normalizedName.EndsWith(text, StringComparison.Ordinal)) { num = Mathf.Max(num, 220); } else if (normalizedName.IndexOf(text, StringComparison.Ordinal) >= 0) { num = Mathf.Max(num, 160); } } return num; } private static bool TryResolveManagedShapeGroup(string blendShapeName, out string groupKey) { string normalizedName = NormalizeName(blendShapeName); for (int i = 0; i < ManagedShapeGroups.Length; i++) { if (ManagedShapeGroups[i].Matches(blendShapeName, normalizedName)) { groupKey = ManagedShapeGroups[i].Key; return true; } } groupKey = string.Empty; return false; } private static string NormalizeName(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } char[] array = new char[value.Length]; int num = 0; for (int i = 0; i < value.Length; i++) { char c = char.ToLowerInvariant(value[i]); if (!char.IsWhiteSpace(c) && c != '_' && c != '-' && c != '.' && c != '/' && c != '\\' && c != '(' && c != ')' && c != '[' && c != ']' && c != '・') { array[num++] = c; } } if (num == 0) { return string.Empty; } string text = new string(array, 0, num); int j; for (j = 0; j < text.Length && char.IsDigit(text[j]); j++) { } if (j <= 0 || j >= text.Length) { return text; } return text.Substring(j); } private static Vector3 ResolveLocalDownDirection(Transform transform) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)transform.parent == (Object)null) { return Vector3.down; } Vector3 val = transform.parent.InverseTransformDirection(Vector3.down); if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) { return Vector3.down; } return ((Vector3)(ref val)).normalized; } } internal sealed class UnityAssetBundleLoader { private readonly struct TextureSlotInfo { public static readonly TextureSlotInfo Empty = new TextureSlotInfo(null, Vector2.one, Vector2.zero); public Texture? Texture { get; } public Vector2 Scale { get; } public Vector2 Offset { get; } public TextureSlotInfo(Texture? texture, Vector2 scale, Vector2 offset) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Texture = texture; Scale = scale; Offset = offset; } } private const string PreferredPrefabAssetName = "assets/codexbuild/mikulobby.prefab"; private const string PreferredMorphClipAssetName = "assets/codexbuild/mikulobbymorph.anim"; private const string PreferredPlaybackMetadataAssetName = "assets/codexbuild/mikulobbyplayback.json"; private const string PreferredRuntimeVmdAssetName = "assets/codexbuild/mikulobbymotion.vmd.bytes"; private static readonly IReadOnlyDictionary RuntimeVmdBoneAliases = CreateRuntimeVmdBoneAliases(); private static readonly bool EnableVerboseBundleLogs = false; private static readonly string[] FaceLikeTokens = new string[12] { "face", "head", "skin", "cheek", "blush", "mouth", "lip", "eye", "brow", "lash", "kao", "hada" }; private static readonly string[] SkinLikeTokens = new string[15] { "face", "skin", "hada", "body", "neck", "arm", "hand", "leg", "foot", "mune", "koshi", "momo", "shoulder", "thigh", "calf" }; private static readonly string[] TransparentTokens = new string[6] { "transparent", "trans", "fade", "glass", "decal", "alpha" }; private static readonly string[] CustomToonShaderTokens = new string[5] { "toon", "outline", "anime", "cel", "ramp" }; private static readonly string[] TexturePropertyCandidates = new string[12] { "_BaseMap", "_MainTex", "_BaseColorMap", "_BaseColorTexture", "_MainTexture", "_ShadeTexture", "_ShadeMultiplyTexture", "_UnlitTexture", "_ShadingGradeTexture", "_SphereAddTex", "_SphereTex", "_MatCap" }; private static readonly string[] ColorPropertyCandidates = new string[7] { "_BaseColor", "_Color", "_LitColor", "_MainColor", "_ShadeColor", "_SColor", "_TintColor" }; private static readonly string[] NormalPropertyCandidates = new string[2] { "_BumpMap", "_NormalMap" }; private static readonly string[] EmissionPropertyCandidates = new string[2] { "_EmissionMap", "_EmissiveMap" }; private static readonly string[] MetallicPropertyCandidates = new string[2] { "_MetallicGlossMap", "_MetallicSpecGlossMap" }; private static readonly string[] OcclusionPropertyCandidates = new string[1] { "_OcclusionMap" }; private static readonly string[] OptionalSurfaceTextureProperties = new string[5] { "_BumpMap", "_NormalMap", "_OcclusionMap", "_MetallicGlossMap", "_SpecGlossMap" }; private static readonly string[] EmissionTogglePropertyCandidates = new string[2] { "_UseEmission", "_EmissionEnabled" }; private AssetBundle? _retainedAssetBundle; public LoadedDancePrefab Load(string bundlePath, ManualLogSource logger) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Unknown result type (might be due to invalid IL or missing references) ValidateFile(bundlePath); UnloadRetainedBundle(); AssetBundle val = AssetBundle.LoadFromFile(bundlePath); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("AssetBundle.LoadFromFile returned null for '" + bundlePath + "'."); } bool flag = false; try { string[] allAssetNames = val.GetAllAssetNames(); LogVerbose(logger, "Inspecting Unity bundle '" + bundlePath + "'. Assets: " + string.Join(", ", allAssetNames)); GameObject val2 = LoadPreferredPrefab(val, allAssetNames, logger); AnimationClip val3 = LoadPreferredMorphClip(val, allAssetNames, logger); DancePlaybackMetadata dancePlaybackMetadata = LoadPreferredPlaybackMetadata(val, allAssetNames, logger); TextAsset val4 = LoadPreferredRuntimeVmdBytes(val, allAssetNames, logger); if ((Object)(object)val2 == (Object)null) { throw new InvalidOperationException("No GameObject asset was found in '" + bundlePath + "'. Assets: " + string.Join(", ", allAssetNames)); } GameObject val5 = Object.Instantiate(val2); ((Object)val5).name = ((Object)val2).name; ((Object)val5).hideFlags = (HideFlags)61; val5.SetActive(false); NormalizeRenderers(val5, logger); NormalizeAudioSources(val5, logger); AnimationClip val6 = (((Object)(object)val4 != (Object)null) ? BuildRuntimeVmdClip(val5, val4.bytes, logger) : null); Bounds val7 = CalculateRendererBounds(val5); int num = val5.GetComponentsInChildren(true).Length; int num2 = val5.GetComponentsInChildren(true).Length; int num3 = val5.GetComponentsInChildren(true).SelectMany((Renderer renderer) => renderer.sharedMaterials).Count((Material material) => (Object)(object)material != (Object)null); Animator componentInChildren = val5.GetComponentInChildren(true); Animation componentInChildren2 = val5.GetComponentInChildren(true); AudioSource[] componentsInChildren = val5.GetComponentsInChildren(true); if ((Object)(object)val3 == (Object)null) { logger.LogWarning((object)("The Unity bundle '" + bundlePath + "' does not contain a pre-baked facial AnimationClip. Runtime VMD morph decoding has been removed, so only the simplified fallback facial controller can be used.")); } object obj; if (componentInChildren == null) { obj = null; } else { RuntimeAnimatorController runtimeAnimatorController = componentInChildren.runtimeAnimatorController; obj = ((runtimeAnimatorController == null) ? null : (from clip in (from @group in runtimeAnimatorController.animationClips?.Where((AnimationClip clip) => (Object)(object)clip != (Object)null).GroupBy((AnimationClip clip) => ((Object)clip).name, StringComparer.Ordinal) select @group.First() into clip orderby clip.length descending select clip).Take(8) select $"{((Object)clip).name}({clip.length:0.###}s)")); } if (obj == null) { obj = Array.Empty(); } string text = string.Join(", ", (IEnumerable)obj); string arg = string.Join(", ", from @group in (from material in val5.GetComponentsInChildren(true).SelectMany((Renderer renderer) => renderer.sharedMaterials) where (Object)(object)material != (Object)null group material by (!((Object)(object)material.shader != (Object)null)) ? "(null)" : ((Object)material.shader).name into @group orderby @group.Count() descending select @group).Take(8) select $"{@group.Key} x{@group.Count()}"); string[] obj2 = new string[19] { "Loaded Unity bundle prefab '", ((Object)val2).name, "' from '", bundlePath, "'. ", $"renderers={num}, skinnedRenderers={num2}, materials={num3}, ", $"animator={(Object)(object)componentInChildren != (Object)null}, animation={(Object)(object)componentInChildren2 != (Object)null}, ", "controller='", null, null, null, null, null, null, null, null, null, null, null }; object obj3; if (componentInChildren == null) { obj3 = null; } else { RuntimeAnimatorController runtimeAnimatorController2 = componentInChildren.runtimeAnimatorController; obj3 = ((runtimeAnimatorController2 != null) ? ((Object)runtimeAnimatorController2).name : null); } if (obj3 == null) { obj3 = "(none)"; } obj2[8] = (string)obj3; obj2[9] = "', avatar='"; object obj4; if (componentInChildren == null) { obj4 = null; } else { Avatar avatar = componentInChildren.avatar; obj4 = ((avatar != null) ? ((Object)avatar).name : null); } if (obj4 == null) { obj4 = "(none)"; } obj2[10] = (string)obj4; obj2[11] = "', clips=["; obj2[12] = text; obj2[13] = "], "; obj2[14] = $"audioSources={componentsInChildren.Length}, "; obj2[15] = $"embeddedMorphClip={(Object)(object)val3 != (Object)null}, "; obj2[16] = $"runtimeVmdClip={(Object)(object)val6 != (Object)null}, "; obj2[17] = $"playbackMetadata={dancePlaybackMetadata != null}, "; obj2[18] = $"boundsCenter={((Bounds)(ref val7)).center}, boundsSize={((Bounds)(ref val7)).size}, shaders=[{arg}]"; LogVerbose(logger, string.Concat(obj2)); flag = true; _retainedAssetBundle = val; return new LoadedDancePrefab(val5, val6, val3, dancePlaybackMetadata, ((Bounds)(ref val7)).min.y, ((Bounds)(ref val7)).size.y, ((Bounds)(ref val7)).center, LoadedPrefabSource.UnityAssetBundle); } finally { if (!flag) { val.Unload(false); } } } public void UnloadRetainedBundle() { if (!((Object)(object)_retainedAssetBundle == (Object)null)) { _retainedAssetBundle.Unload(false); _retainedAssetBundle = null; } } private static GameObject? LoadPreferredPrefab(AssetBundle assetBundle, string[] assetNames, ManualLogSource logger) { string text = assetNames.FirstOrDefault((string name) => string.Equals(name, "assets/codexbuild/mikulobby.prefab", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/mikulobby.prefab", StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(text)) { GameObject val = assetBundle.LoadAsset(text); if ((Object)(object)val != (Object)null) { LogVerbose(logger, "Selected preferred bundle prefab asset '" + text + "'."); return val; } } return assetBundle.LoadAllAssets().OrderByDescending(HasPlayableAnimation).ThenByDescending(CountRenderers) .FirstOrDefault(); } private static AnimationClip? LoadPreferredMorphClip(AssetBundle assetBundle, string[] assetNames, ManualLogSource logger) { string text = assetNames.FirstOrDefault((string name) => string.Equals(name, "assets/codexbuild/mikulobbymorph.anim", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/mikulobbymorph.anim", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/mikulobbyfacial.anim", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/facialmorph.anim", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/facial.anim", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrWhiteSpace(text)) { return null; } AnimationClip val = assetBundle.LoadAsset(text); if ((Object)(object)val == (Object)null) { logger.LogWarning((object)("The bundle contains a facial clip asset entry '" + text + "', but it could not be loaded as an AnimationClip.")); return null; } try { AnimationClip val2 = Object.Instantiate(val); ((Object)val2).name = (string.IsNullOrWhiteSpace(((Object)val).name) ? "MikuLobbyMorph" : ((Object)val).name); val2.legacy = true; val2.wrapMode = (WrapMode)2; LogVerbose(logger, "Loaded pre-baked facial AnimationClip '" + text + "' from the Unity bundle. " + $"clip='{((Object)val2).name}', length={val2.length:0.###}, legacy={val2.legacy}."); return val2; } catch (Exception ex) { logger.LogWarning((object)("Failed to prepare pre-baked facial AnimationClip '" + text + "' for runtime playback: " + ex.Message)); return null; } } private static TextAsset? LoadPreferredRuntimeVmdBytes(AssetBundle assetBundle, string[] assetNames, ManualLogSource logger) { string text = assetNames.FirstOrDefault((string name) => string.Equals(name, "assets/codexbuild/mikulobbymotion.vmd.bytes", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/mikulobbymotion.vmd.bytes", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".vmd.bytes", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrWhiteSpace(text)) { return null; } TextAsset val = assetBundle.LoadAsset(text); if ((Object)(object)val == (Object)null || val.bytes == null || val.bytes.Length == 0) { logger.LogWarning((object)("The bundle contains runtime VMD asset entry '" + text + "', but it could not be loaded as non-empty bytes.")); return null; } LogVerbose(logger, $"Loaded runtime VMD bytes '{text}', bytes={val.bytes.Length}."); return val; } private static AnimationClip? BuildRuntimeVmdClip(GameObject templateRoot, byte[] vmdBytes, ManualLogSource logger) { if ((Object)(object)templateRoot == (Object)null || vmdBytes == null || vmdBytes.Length == 0) { return null; } try { VmdMotion vmdMotion = VmdReader.Read(vmdBytes); Transform transform = templateRoot.transform; Dictionary dictionary = BuildRuntimeBoneMap(transform); SkinnedMeshRenderer val = SelectPrimarySkinnedMeshRenderer(templateRoot); if ((Object)(object)val == (Object)null) { logger.LogWarning((object)"Runtime VMD motion was bundled, but no SkinnedMeshRenderer was available for clip generation."); return null; } ClearAnimatorControllers(templateRoot); Animation val2 = templateRoot.GetComponent() ?? templateRoot.AddComponent(); val2.cullingType = (AnimationCullingType)0; val2.playAutomatically = false; val2.wrapMode = (WrapMode)2; int matchedBoneCount; int matchedMorphCount; AnimationClip val3 = VmdAnimationBuilder.BuildLegacyClip(vmdMotion, transform, dictionary, val, out matchedBoneCount, out matchedMorphCount); if (matchedBoneCount <= 0) { logger.LogWarning((object)("Runtime VMD clip generation found no matching bones. " + $"animatedBones={vmdMotion.BoneFrames.Select((VmdBoneFrame frame) => frame.BoneName).Distinct().Count()}, availableBones={dictionary.Count}.")); return null; } ((Object)val3).name = (string.IsNullOrWhiteSpace(((Object)val3).name) ? "MikuLobbyRuntimeVmd" : ((Object)val3).name); if ((Object)(object)val2.GetClip(((Object)val3).name) == (Object)null) { val2.AddClip(val3, ((Object)val3).name); } val2.clip = val3; logger.LogInfo((object)($"Built runtime VMD AnimationClip '{((Object)val3).name}'. length={val3.length:0.###}, " + $"matchedBones={matchedBoneCount}, matchedMorphs={matchedMorphCount}, renderer='{((Object)val).name}', " + $"motionBoneFrames={vmdMotion.BoneFrames.Count}, motionMorphFrames={vmdMotion.MorphFrames.Count}.")); return val3; } catch (Exception arg) { logger.LogWarning((object)$"Failed to build runtime VMD AnimationClip from bundled bytes: {arg}"); return null; } } private static Dictionary BuildRuntimeBoneMap(Transform animationRoot) { Transform animationRoot2 = animationRoot; Transform[] source = (from transform in ((Component)animationRoot2).GetComponentsInChildren(true) where (Object)(object)transform != (Object)null && !string.IsNullOrWhiteSpace(((Object)transform).name) select transform).ToArray(); Dictionary dictionary = source.GroupBy((Transform transform) => ((Object)transform).name, StringComparer.Ordinal).ToDictionary, string, Transform>((IGrouping group) => group.Key, (IGrouping group) => group.OrderBy((Transform transform) => BuildPath(animationRoot2, transform).Length).First(), StringComparer.Ordinal); Dictionary dictionary2 = (from transform in source select new { Key = NormalizeRuntimeBoneName(((Object)transform).name), Transform = transform } into item where !string.IsNullOrWhiteSpace(item.Key) select item).GroupBy(item => item.Key, StringComparer.OrdinalIgnoreCase).ToDictionary(group => group.Key, group => (from item in @group select item.Transform into transform orderby BuildPath(animationRoot2, transform).Length select transform).First(), StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair runtimeVmdBoneAlias in RuntimeVmdBoneAliases) { if (dictionary.ContainsKey(runtimeVmdBoneAlias.Key)) { continue; } string[] value = runtimeVmdBoneAlias.Value; for (int i = 0; i < value.Length; i++) { string key = NormalizeRuntimeBoneName(value[i]); if (dictionary2.TryGetValue(key, out var value2)) { dictionary[runtimeVmdBoneAlias.Key] = value2; break; } } } return dictionary; } private static Dictionary CreateRuntimeVmdBoneAliases() { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); dictionary["センター"] = new string[1] { "Center" }; dictionary["上半身"] = new string[1] { "Torso" }; dictionary["上半身2"] = new string[2] { "Torso2", "Torso3" }; dictionary["下半身"] = new string[1] { "Waist" }; dictionary["首"] = new string[1] { "Neck" }; dictionary["頭"] = new string[1] { "Head" }; dictionary["両目"] = new string[1] { "Eyes" }; dictionary["右目"] = new string[1] { "RightEye" }; dictionary["左目"] = new string[1] { "LeftEye" }; dictionary["右肩"] = new string[1] { "RightShoulder" }; dictionary["左肩"] = new string[1] { "LeftShoulder" }; dictionary["右腕"] = new string[1] { "RightArm" }; dictionary["左腕"] = new string[1] { "LeftArm" }; dictionary["右ひじ"] = new string[1] { "RightElbow" }; dictionary["左ひじ"] = new string[1] { "LeftElbow" }; dictionary["右手首"] = new string[2] { "RightHandTwist", "RightHand" }; dictionary["左手首"] = new string[2] { "LeftHandTwist", "LeftHand" }; dictionary["右手先"] = new string[1] { "RightHandTip" }; dictionary["左手先"] = new string[1] { "LeftHandTip" }; dictionary["右腕捩"] = new string[1] { "RightArmTwist" }; dictionary["左腕捩"] = new string[1] { "LeftArmTwist" }; dictionary["右腕捩1"] = new string[2] { "RightArmTwist0", "RightArmTwist1" }; dictionary["右腕捩2"] = new string[2] { "RightArmTwist1", "RightArmTwist2" }; dictionary["左腕捩1"] = new string[2] { "LeftArmTwist0", "LeftArmTwist1" }; dictionary["左腕捩2"] = new string[2] { "LeftArmTwist1", "LeftArmTwist2" }; dictionary["右手捩"] = new string[1] { "RightHandTwist" }; dictionary["左手捩"] = new string[1] { "LeftHandTwist" }; dictionary["右手捩1"] = new string[2] { "RightHandTwist0", "RightHandTwist1" }; dictionary["右手捩2"] = new string[2] { "RightHandTwist1", "RightHandTwist2" }; dictionary["右手捩3"] = new string[2] { "RightHandTwist2", "RightHandTwist3" }; dictionary["右手捩4"] = new string[2] { "RightHandTwist3", "RightHandTwist4" }; dictionary["右手捩5"] = new string[1] { "RightHandTwist4" }; dictionary["左手捩1"] = new string[2] { "LeftHandTwist0", "LeftHandTwist1" }; dictionary["左手捩2"] = new string[2] { "LeftHandTwist1", "LeftHandTwist2" }; dictionary["左手捩3"] = new string[2] { "LeftHandTwist2", "LeftHandTwist3" }; dictionary["左手捩4"] = new string[2] { "LeftHandTwist3", "LeftHandTwist4" }; dictionary["左手捩5"] = new string[1] { "LeftHandTwist4" }; dictionary["右足"] = new string[1] { "RightHip" }; dictionary["左足"] = new string[1] { "LeftHip" }; dictionary["右ひざ"] = new string[1] { "RightKnee" }; dictionary["左ひざ"] = new string[1] { "LeftKnee" }; dictionary["右足首"] = new string[1] { "RightFoot" }; dictionary["左足首"] = new string[1] { "LeftFoot" }; dictionary["右つま先"] = new string[1] { "RightToe" }; dictionary["左つま先"] = new string[1] { "LeftToe" }; dictionary["右親指1"] = new string[2] { "RightThumb0", "RightThumb1" }; dictionary["右親指2"] = new string[2] { "RightThumb1", "RightThumb2" }; dictionary["右親指先"] = new string[1] { "RightThumbTip" }; dictionary["左親指1"] = new string[2] { "LeftThumb0", "LeftThumb1" }; dictionary["左親指2"] = new string[2] { "LeftThumb1", "LeftThumb2" }; dictionary["左親指先"] = new string[1] { "LeftThumbTip" }; dictionary["右人指1"] = new string[2] { "RightIndex1", "RightIndex0" }; dictionary["右人指2"] = new string[1] { "RightIndex2" }; dictionary["右人指3"] = new string[1] { "RightIndex3" }; dictionary["右人指先"] = new string[1] { "RightIndexTip" }; dictionary["左人指1"] = new string[2] { "LeftIndex1", "LeftIndex0" }; dictionary["左人指2"] = new string[1] { "LeftIndex2" }; dictionary["左人指3"] = new string[1] { "LeftIndex3" }; dictionary["左人指先"] = new string[1] { "LeftIndexTip" }; dictionary["右中指1"] = new string[2] { "RightMiddle1", "RightMiddle0" }; dictionary["右中指2"] = new string[1] { "RightMiddle2" }; dictionary["右中指3"] = new string[1] { "RightMiddle3" }; dictionary["右中指先"] = new string[1] { "RightMiddleTip" }; dictionary["左中指1"] = new string[2] { "LeftMiddle1", "LeftMiddle0" }; dictionary["左中指2"] = new string[1] { "LeftMiddle2" }; dictionary["左中指3"] = new string[1] { "LeftMiddle3" }; dictionary["左中指先"] = new string[1] { "LeftMiddleTip" }; dictionary["右薬指1"] = new string[2] { "RightRing1", "RightRing0" }; dictionary["右薬指2"] = new string[1] { "RightRing2" }; dictionary["右薬指3"] = new string[1] { "RightRing3" }; dictionary["右薬指先"] = new string[1] { "RightRingTip" }; dictionary["左薬指1"] = new string[2] { "LeftRing1", "LeftRing0" }; dictionary["左薬指2"] = new string[1] { "LeftRing2" }; dictionary["左薬指3"] = new string[1] { "LeftRing3" }; dictionary["左薬指先"] = new string[1] { "LeftRingTip" }; dictionary["右小指1"] = new string[2] { "RightPinky1", "RightPinky0" }; dictionary["右小指2"] = new string[1] { "RightPinky2" }; dictionary["右小指3"] = new string[1] { "RightPinky3" }; dictionary["右小指先"] = new string[1] { "RightPinkyTip" }; dictionary["左小指1"] = new string[2] { "LeftPinky1", "LeftPinky0" }; dictionary["左小指2"] = new string[1] { "LeftPinky2" }; dictionary["左小指3"] = new string[1] { "LeftPinky3" }; dictionary["左小指先"] = new string[1] { "LeftPinkyTip" }; return dictionary; } private static string NormalizeRuntimeBoneName(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } string text = value.Trim(); int num = text.IndexOf('.'); if (num >= 0 && num + 1 < text.Length) { text = text.Substring(num + 1); } text = text.TrimStart(new char[1] { '!' }); if (text.StartsWith("joint_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("joint_".Length); } else if (text.StartsWith("IK_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("IK_".Length); } char[] array = new char[text.Length]; int num2 = 0; foreach (char c in text) { if (char.IsLetterOrDigit(c)) { array[num2++] = char.ToLowerInvariant(c); } } if (num2 <= 0) { return string.Empty; } return new string(array, 0, num2); } private static SkinnedMeshRenderer? SelectPrimarySkinnedMeshRenderer(GameObject root) { return (from renderer in root.GetComponentsInChildren(true) where (Object)(object)renderer != (Object)null && (Object)(object)renderer.sharedMesh != (Object)null orderby renderer.sharedMesh.blendShapeCount descending, renderer.sharedMesh.vertexCount descending select renderer).FirstOrDefault(); } private static void ClearAnimatorControllers(GameObject root) { Animator[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Animator val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.runtimeAnimatorController = null; val.applyRootMotion = false; val.cullingMode = (AnimatorCullingMode)0; val.updateMode = (AnimatorUpdateMode)0; } } } private static string BuildPath(Transform root, Transform target) { if ((Object)(object)target == (Object)(object)root) { return string.Empty; } Stack stack = new Stack(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { stack.Push(((Object)val).name); val = val.parent; } return string.Join("/", stack.ToArray()); } private static DancePlaybackMetadata? LoadPreferredPlaybackMetadata(AssetBundle assetBundle, string[] assetNames, ManualLogSource logger) { string text = assetNames.FirstOrDefault((string name) => string.Equals(name, "assets/codexbuild/mikulobbyplayback.json", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/mikulobbyplayback.json", StringComparison.OrdinalIgnoreCase) || name.EndsWith("/playback.json", StringComparison.OrdinalIgnoreCase)); if (string.IsNullOrWhiteSpace(text)) { return null; } TextAsset val = assetBundle.LoadAsset(text); if ((Object)(object)val == (Object)null || string.IsNullOrWhiteSpace(val.text)) { logger.LogWarning((object)("The bundle contains playback metadata '" + text + "', but it could not be loaded as a TextAsset.")); return null; } try { DancePlaybackMetadata dancePlaybackMetadata = JsonUtility.FromJson(val.text); if (dancePlaybackMetadata == null) { logger.LogWarning((object)("Failed to deserialize playback metadata '" + text + "' from the Unity bundle.")); return null; } LogVerbose(logger, "Loaded playback metadata '" + text + "' from the Unity bundle. " + $"startFrame={dancePlaybackMetadata.MotionStartFrame}, hasEndFrame={dancePlaybackMetadata.HasMotionEndFrame}, endFrame={dancePlaybackMetadata.MotionEndFrame}, " + $"audioStart={dancePlaybackMetadata.AudioSegmentStartSeconds:0.###}, audioDuration={dancePlaybackMetadata.AudioSegmentDurationSeconds:0.###}, " + $"frameRate={dancePlaybackMetadata.SourceFrameRate:0.###}."); return dancePlaybackMetadata; } catch (Exception ex) { logger.LogWarning((object)("Failed to parse playback metadata '" + text + "': " + ex.Message)); return null; } } private static int HasPlayableAnimation(GameObject candidate) { Animator componentInChildren = candidate.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.runtimeAnimatorController != (Object)null) { return 2; } if ((Object)(object)candidate.GetComponentInChildren(true) != (Object)null) { return 1; } return 0; } private static int CountRenderers(GameObject candidate) { return candidate.GetComponentsInChildren(true).Length; } private static void NormalizeRenderers(GameObject root, ManualLogSource logger) { Shader val = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Legacy Shaders/Diffuse"); Transform[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = 0; } Renderer[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { val2.enabled = true; val2.shadowCastingMode = (ShadowCastingMode)1; val2.receiveShadows = true; val2.allowOcclusionWhenDynamic = true; val2.lightProbeUsage = (LightProbeUsage)1; val2.reflectionProbeUsage = (ReflectionProbeUsage)1; Material[] sharedMaterials = val2.sharedMaterials; int expectedMaterialCount = GetExpectedMaterialCount(val2); Material[] materials = AlignMaterialSlots(sharedMaterials, expectedMaterialCount); val2.sharedMaterials = NormalizeMaterials(val2, materials, val); LogVerbose(logger, "Renderer '" + ((Object)val2).name + "' normalized. type=" + ((object)val2).GetType().Name + ", " + $"mesh='{GetSharedMeshName(val2)}', subMeshes={expectedMaterialCount}, " + $"materialsBefore={sharedMaterials.Length}, materialsAfter={val2.sharedMaterials.Length}."); SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val2 is SkinnedMeshRenderer) ? val2 : null); if (val3 != null) { val3.updateWhenOffscreen = true; } } LogVerbose(logger, "Normalized Unity bundle renderers. fallback shader='" + (((val != null) ? ((Object)val).name : null) ?? "(none)") + "'."); } private static void NormalizeAudioSources(GameObject root, ManualLogSource logger) { AudioSource[] componentsInChildren = root.GetComponentsInChildren(true); foreach (AudioSource val in componentsInChildren) { AudioClip val2 = ResolveAudioClip(val); if ((Object)(object)val2 != (Object)null && (Object)(object)val.clip == (Object)null) { val.clip = val2; } val.playOnAwake = false; val.loop = false; val.spatialBlend = 0f; val.dopplerLevel = 0f; string[] obj = new string[9] { "AudioSource '", ((Object)val).name, "' normalized. clip='", ((val2 != null) ? ((Object)val2).name : null) ?? "(none)", "', ", $"length={((val2 != null) ? val2.length : 0f):0.###}, volume={val.volume:0.###}, ", "resource='", null, null }; AudioResource resource = val.resource; obj[7] = ((resource != null) ? ((Object)resource).name : null) ?? "(none)"; obj[8] = "'."; LogVerbose(logger, string.Concat(obj)); } } private static void LogVerbose(ManualLogSource logger, string message) { if (EnableVerboseBundleLogs) { logger.LogInfo((object)message); } } private static int GetExpectedMaterialCount(Renderer renderer) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null && (Object)(object)val.sharedMesh != (Object)null) { return Mathf.Max(1, val.sharedMesh.subMeshCount); } MeshFilter val2 = default(MeshFilter); if (((Component)renderer).TryGetComponent(ref val2) && (Object)(object)val2.sharedMesh != (Object)null) { return Mathf.Max(1, val2.sharedMesh.subMeshCount); } return Mathf.Max(1, renderer.sharedMaterials.Length); } private static string GetSharedMeshName(Renderer renderer) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null) { if (!((Object)(object)val.sharedMesh != (Object)null)) { return "(none)"; } return ((Object)val.sharedMesh).name; } MeshFilter val2 = default(MeshFilter); if (((Component)renderer).TryGetComponent(ref val2) && (Object)(object)val2.sharedMesh != (Object)null) { return ((Object)val2.sharedMesh).name; } return "(none)"; } private static Material[] AlignMaterialSlots(Material[] materials, int expectedMaterialCount) { if (expectedMaterialCount <= 0) { return Array.Empty(); } if (materials.Length == expectedMaterialCount && materials.All((Material material) => (Object)(object)material != (Object)null)) { return materials; } Material[] array = (Material[])(object)new Material[expectedMaterialCount]; Material val = ((IEnumerable)materials).LastOrDefault((Func)((Material material) => (Object)(object)material != (Object)null)); for (int i = 0; i < expectedMaterialCount; i++) { array[i] = (Material)((i < materials.Length && (Object)(object)materials[i] != (Object)null) ? ((object)materials[i]) : ((object)val)); } return array; } private static Material[] NormalizeMaterials(Renderer renderer, Material[] materials, Shader? fallbackShader) { if (materials.Length == 0) { return materials; } bool faceLikeRenderer = IsFaceLikeRenderer(renderer); Material[] array = (Material[])(object)new Material[materials.Length]; bool flag = false; for (int i = 0; i < materials.Length; i++) { Material val = materials[i]; if ((Object)(object)val != (Object)null && CanUseSourceShader(val)) { array[i] = val; continue; } if ((Object)(object)fallbackShader == (Object)null) { array[i] = val; continue; } array[i] = CreateCompatibleMaterial(renderer, val, fallbackShader, i, faceLikeRenderer); flag = true; } if (!flag) { return materials; } return array; } private static Material CreateCompatibleMaterial(Renderer renderer, Material? source, Shader fallbackShader, int index, bool faceLikeRenderer) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) if (CanUseSourceShader(source)) { return source; } Material val = new Material(ResolveCompatibleFallbackShader(source, fallbackShader)) { name = (((Object)(object)source != (Object)null) ? (((Object)source).name + "_Runtime") : $"RuntimeMaterial_{index}") }; TextureSlotInfo textureSlot = ReadFirstTextureSlot(source, TexturePropertyCandidates); if ((Object)(object)textureSlot.Texture == (Object)null) { textureSlot = ReadFallbackBaseTextureSlot(source); } TextureSlotInfo textureSlot2 = ReadFirstTextureSlot(source, NormalPropertyCandidates); TextureSlotInfo textureSlot3 = ReadFirstTextureSlot(source, EmissionPropertyCandidates); TextureSlotInfo textureSlot4 = ReadFirstTextureSlot(source, MetallicPropertyCandidates); TextureSlotInfo textureSlot5 = ReadFirstTextureSlot(source, OcclusionPropertyCandidates); Color val2 = ResolveCompatibleBaseColor((Color)(((??)ReadFirstColor(source, ColorPropertyCandidates)) ?? Color.white)); Texture texture = textureSlot.Texture; Texture texture2 = textureSlot2.Texture; Texture texture3 = textureSlot3.Texture; Texture texture4 = textureSlot4.Texture; Texture? texture5 = textureSlot5.Texture; float num = (((Object)(object)source != (Object)null && source.HasProperty("_Cutoff")) ? Mathf.Clamp01(source.GetFloat("_Cutoff")) : 0f); float num2 = (((Object)(object)source != (Object)null && source.HasProperty("_Smoothness")) ? Mathf.Clamp01(source.GetFloat("_Smoothness")) : (((Object)(object)source != (Object)null && source.HasProperty("_Glossiness")) ? Mathf.Clamp01(source.GetFloat("_Glossiness")) : 0f)); float num3 = (((Object)(object)source != (Object)null && source.HasProperty("_Metallic")) ? Mathf.Clamp01(source.GetFloat("_Metallic")) : 0f); bool flag = IsEmissionEnabled(source, texture3); Color val3 = ((flag && !faceLikeRenderer) ? ClampColor((Color)(((??)TryReadColor(source, "_EmissionColor")) ?? Color.black), 1f) : Color.black); OptimizeTextureSampling(texture); OptimizeTextureSampling(texture2); OptimizeTextureSampling(texture3); OptimizeTextureSampling(texture4); OptimizeTextureSampling(texture5); val.color = val2; if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", val2); } if (val.HasProperty("_Color")) { val.SetColor("_Color", val2); } CopyTexture(val, "_BaseMap", textureSlot); CopyTexture(val, "_MainTex", textureSlot); CopyTexture(val, "_BumpMap", textureSlot2); CopyTexture(val, "_EmissionMap", textureSlot3); CopyTexture(val, "_MetallicGlossMap", textureSlot4); CopyTexture(val, "_OcclusionMap", textureSlot5); if (val.HasProperty("_BumpScale")) { val.SetFloat("_BumpScale", ((Object)(object)source != (Object)null && source.HasProperty("_BumpScale")) ? source.GetFloat("_BumpScale") : 1f); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", num3); } if (val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", num2); } if (val.HasProperty("_Glossiness")) { val.SetFloat("_Glossiness", num2); } if (val.HasProperty("_Cutoff")) { val.SetFloat("_Cutoff", num); } if (val.HasProperty("_OcclusionStrength")) { val.SetFloat("_OcclusionStrength", ((Object)(object)source != (Object)null && source.HasProperty("_OcclusionStrength")) ? source.GetFloat("_OcclusionStrength") : 1f); } if (val.HasProperty("_SpecularHighlights")) { val.SetFloat("_SpecularHighlights", ((Object)(object)source != (Object)null && source.HasProperty("_SpecularHighlights")) ? source.GetFloat("_SpecularHighlights") : 1f); } if (val.HasProperty("_EnvironmentReflections")) { val.SetFloat("_EnvironmentReflections", ((Object)(object)source != (Object)null && source.HasProperty("_EnvironmentReflections")) ? source.GetFloat("_EnvironmentReflections") : 1f); } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", val3); if (flag && ((Object)(object)texture3 != (Object)null || ((Color)(ref val3)).maxColorComponent > 0.001f)) { val.EnableKeyword("_EMISSION"); } else { val.DisableKeyword("_EMISSION"); } } if (val.HasProperty("_Cull") && (Object)(object)source != (Object)null && source.HasProperty("_Cull")) { val.SetFloat("_Cull", source.GetFloat("_Cull")); } ConfigureSurfaceMode(val, source, texture, val2, num, faceLikeRenderer); EnableShadowSupport(val); return val; } private static Material CreateRuntimeSourceMaterial(Renderer renderer, Material source, Shader fallbackShader, int index, bool faceLikeRenderer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) Material val; try { val = new Material(source) { name = ((Object)source).name + "_Runtime" }; } catch { val = new Material(ResolveCompatibleFallbackShader(source, fallbackShader)) { name = $"{((Object)source).name}_RuntimeFallback_{index}" }; } TextureSlotInfo textureSlot = ReadFirstTextureSlot(source, TexturePropertyCandidates); if ((Object)(object)textureSlot.Texture == (Object)null) { textureSlot = ReadFallbackBaseTextureSlot(source); } _ = textureSlot.Texture; CopyTexture(val, "_BaseMap", textureSlot); CopyTexture(val, "_MainTex", textureSlot); TextureSlotInfo textureSlot2 = ReadFirstTextureSlot(source, NormalPropertyCandidates); TextureSlotInfo textureSlot3 = ReadFirstTextureSlot(source, EmissionPropertyCandidates); TextureSlotInfo textureSlot4 = ReadFirstTextureSlot(source, MetallicPropertyCandidates); TextureSlotInfo textureSlot5 = ReadFirstTextureSlot(source, OcclusionPropertyCandidates); CopyTexture(val, "_BumpMap", textureSlot2); CopyTexture(val, "_EmissionMap", textureSlot3); CopyTexture(val, "_MetallicGlossMap", textureSlot4); CopyTexture(val, "_OcclusionMap", textureSlot5); Color val2 = ResolveCompatibleBaseColor((Color)(((??)ReadFirstColor(source, ColorPropertyCandidates)) ?? Color.white)); if (val.HasProperty("_Tint")) { val.SetColor("_Tint", val2); } if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", val2); } if (val.HasProperty("_Color")) { val.SetColor("_Color", val2); } CopyCompatibleFloatProperty(source, val, "_BumpScale"); CopyCompatibleFloatProperty(source, val, "_Metallic"); CopyCompatibleFloatProperty(source, val, "_Smoothness"); CopyCompatibleFloatProperty(source, val, "_Glossiness"); CopyCompatibleFloatProperty(source, val, "_OcclusionStrength"); CopyCompatibleFloatProperty(source, val, "_SpecularHighlights"); CopyCompatibleFloatProperty(source, val, "_EnvironmentReflections"); CopyCompatibleFloatProperty(source, val, "_Cutoff"); CopyCompatibleFloatProperty(source, val, "_Cull"); CopyCompatibleFloatProperty(source, val, "_Surface"); CopyCompatibleFloatProperty(source, val, "_Blend"); CopyCompatibleFloatProperty(source, val, "_ZWrite"); CopyCompatibleFloatProperty(source, val, "_AlphaClip"); CopyCompatibleColorProperty(source, val, "_EmissionColor"); EnableShadowSupport(val); return val; } private static Color ResolveCompatibleBaseColor(Color sourceColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ClampColor(sourceColor, 1f); } private static Shader ResolveCompatibleFallbackShader(Material? source, Shader defaultFallbackShader) { string shaderName = (((Object)(object)((source != null) ? source.shader : null) != (Object)null) ? (((Object)source.shader).name ?? string.Empty) : string.Empty); if (!string.IsNullOrWhiteSpace(shaderName) && CustomToonShaderTokens.Any((string token) => shaderName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)) { return Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture") ?? defaultFallbackShader; } return defaultFallbackShader; } private static bool IsSkinLikeMaterial(Renderer renderer, Material? source, Texture? baseTexture) { string materialName = ((source != null) ? ((Object)source).name : null) ?? string.Empty; string textureName = ((baseTexture != null) ? ((Object)baseTexture).name : null) ?? string.Empty; string rendererName = ((Object)renderer).name ?? string.Empty; string rendererPath = BuildRendererPath(((Component)renderer).transform, ((Component)renderer).transform.root); return SkinLikeTokens.Any((string token) => materialName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0 || textureName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0 || rendererName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0 || rendererPath.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0); } private static void EnableShadowSupport(Material[]? materials) { if (materials != null) { for (int i = 0; i < materials.Length; i++) { EnableShadowSupport(materials[i]); } } } private static void EnableShadowSupport(Material? material) { if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_ReceiveShadows")) { material.SetFloat("_ReceiveShadows", 1f); } if (material.HasProperty("_CastShadows")) { material.SetFloat("_CastShadows", 1f); } material.SetShaderPassEnabled("ShadowCaster", true); } } private static bool CanUseSourceShader(Material? source) { if ((Object)(object)source == (Object)null || (Object)(object)source.shader == (Object)null) { return false; } string text = ((Object)source.shader).name ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return false; } if (text.IndexOf("Hidden/InternalErrorShader", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("FallbackError", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } try { return source.shader.isSupported; } catch { return false; } } private static Texture? TryReadTexture(Material? source, string propertyName) { if ((Object)(object)source == (Object)null || !source.HasProperty(propertyName)) { return null; } return source.GetTexture(propertyName); } private static Color? TryReadColor(Material? source, string propertyName) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || !source.HasProperty(propertyName)) { return null; } return source.GetColor(propertyName); } private static bool TrySetTextureSafe(Material? material, string propertyName, Texture? texture) { if ((Object)(object)material == (Object)null || string.IsNullOrWhiteSpace(propertyName) || !material.HasProperty(propertyName)) { return false; } try { material.SetTexture(propertyName, texture); return true; } catch { return false; } } private static void OptimizeTextureSampling(Texture? texture) { } private static void DisableOptionalSurfaceTextures(Material material) { string[] optionalSurfaceTextureProperties = OptionalSurfaceTextureProperties; foreach (string propertyName in optionalSurfaceTextureProperties) { TrySetTextureSafe(material, propertyName, null); } material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } private static void ApplyRealisticMaterialTuning(Material material, Color preservedTint) { } private static void CopyCompatibleFloatProperty(Material? source, Material target, string propertyName) { if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null) && source.HasProperty(propertyName) && target.HasProperty(propertyName)) { target.SetFloat(propertyName, source.GetFloat(propertyName)); } } private static void CopyCompatibleColorProperty(Material? source, Material target, string propertyName) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null) && source.HasProperty(propertyName) && target.HasProperty(propertyName)) { target.SetColor(propertyName, source.GetColor(propertyName)); } } private static Color? ReadFirstColor(Material? source, IEnumerable propertyNames) { foreach (string propertyName in propertyNames) { Color? result = TryReadColor(source, propertyName); if (result.HasValue) { return result; } } return null; } private static TextureSlotInfo ReadFirstTextureSlot(Material? source, IEnumerable propertyNames) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null) { return TextureSlotInfo.Empty; } foreach (string propertyName in propertyNames) { if (source.HasProperty(propertyName)) { Texture texture = source.GetTexture(propertyName); if ((Object)(object)texture != (Object)null) { return new TextureSlotInfo(texture, source.GetTextureScale(propertyName), source.GetTextureOffset(propertyName)); } } } return TextureSlotInfo.Empty; } private static TextureSlotInfo ReadFallbackBaseTextureSlot(Material? source) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null) { return TextureSlotInfo.Empty; } string[] texturePropertyNames = source.GetTexturePropertyNames(); foreach (string text in texturePropertyNames) { if (text.IndexOf("bump", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("normal", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("emission", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("occlusion", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("metal", StringComparison.OrdinalIgnoreCase) < 0) { Texture texture = source.GetTexture(text); if ((Object)(object)texture != (Object)null) { return new TextureSlotInfo(texture, source.GetTextureScale(text), source.GetTextureOffset(text)); } } } return TextureSlotInfo.Empty; } private static bool IsTransparentMaterial(Material? source, Color color) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) Material source2 = source; if (color.a < 0.999f) { return true; } if ((Object)(object)source2 == (Object)null) { return false; } if (source2.renderQueue >= 3000) { return true; } if (source2.HasProperty("_Surface") && source2.GetFloat("_Surface") > 0.5f) { return true; } if (source2.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")) { return true; } string shaderName = (((Object)(object)source2.shader != (Object)null) ? (((Object)source2.shader).name ?? string.Empty) : string.Empty); return TransparentTokens.Any((string token) => shaderName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)source2).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0); } private static bool TextureHasAlpha(Texture? texture) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (val == null) { return false; } TextureFormat format = val.format; string text = ((object)(TextureFormat)(ref format)).ToString(); if (text.IndexOf("RGBA", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("ARGB", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("BGRA", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Alpha", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("DXT5", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("BC7", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("ETC2_RGBA", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("ASTC_RGBA", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static void ConfigureSurfaceMode(Material material, Material? source, Texture? baseTexture, Color baseColor, float cutoff, bool faceLikeRenderer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) bool num = IsTransparentMaterial(source, baseColor); bool flag = TextureHasAlpha(baseTexture); bool flag2 = cutoff > 0.001f || (flag && IsLikelyDecalMaterial(source, faceLikeRenderer)); if (num) { ConfigureTransparentMaterial(material, source); return; } if (flag2) { ConfigureAlphaClipMaterial(material, source); return; } if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 0f); } if (material.HasProperty("_AlphaClip")) { material.SetFloat("_AlphaClip", 0f); } if (material.HasProperty("_Cutoff")) { material.SetFloat("_Cutoff", 0f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 1); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 0); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 1); } material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_ALPHATEST_ON"); material.renderQueue = 2000; } private static void ConfigureAlphaClipMaterial(Material material, Material? source) { if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 0f); } if (material.HasProperty("_AlphaClip")) { material.SetFloat("_AlphaClip", 1f); } if (material.HasProperty("_Cutoff")) { material.SetFloat("_Cutoff", ((Object)(object)source != (Object)null && source.HasProperty("_Cutoff")) ? source.GetFloat("_Cutoff") : 0.5f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 1); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 0); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 1); } material.EnableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.renderQueue = 2450; } private static void ConfigureTransparentMaterial(Material material, Material? source) { if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 1f); } if (material.HasProperty("_Blend")) { material.SetFloat("_Blend", 0f); } if (material.HasProperty("_SrcBlend")) { material.SetInt("_SrcBlend", 5); } if (material.HasProperty("_DstBlend")) { material.SetInt("_DstBlend", 10); } if (material.HasProperty("_ZWrite")) { material.SetInt("_ZWrite", 0); } if ((Object)(object)source != (Object)null && source.HasProperty("_Cutoff") && source.GetFloat("_Cutoff") > 0.001f) { if (material.HasProperty("_AlphaClip")) { material.SetFloat("_AlphaClip", 1f); } if (material.HasProperty("_Cutoff")) { material.SetFloat("_Cutoff", source.GetFloat("_Cutoff")); } } else if (material.HasProperty("_AlphaClip")) { material.SetFloat("_AlphaClip", 0f); } material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.DisableKeyword("_ALPHATEST_ON"); material.renderQueue = 3000; } private static bool IsLikelyDecalMaterial(Material? source, bool faceLikeRenderer) { Material source2 = source; if (faceLikeRenderer) { return true; } if ((Object)(object)source2 == (Object)null) { return false; } return FaceLikeTokens.Any((string token) => ((Object)source2).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0); } private static bool IsFaceLikeRenderer(Renderer renderer) { Renderer renderer2 = renderer; string path = BuildRendererPath(((Component)renderer2).transform, ((Component)renderer2).transform.root); return FaceLikeTokens.Any((string token) => ((Object)renderer2).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0 || path.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0); } private static string BuildRendererPath(Transform current, Transform root) { Stack stack = new Stack(); Transform val = current; while ((Object)(object)val != (Object)null) { stack.Push(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } return string.Join("/", stack); } private static void CopyTexture(Material target, string targetPropertyName, TextureSlotInfo textureSlot) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)textureSlot.Texture == (Object)null) && target.HasProperty(targetPropertyName)) { target.SetTexture(targetPropertyName, textureSlot.Texture); target.SetTextureScale(targetPropertyName, textureSlot.Scale); target.SetTextureOffset(targetPropertyName, textureSlot.Offset); } } private static bool IsEmissionEnabled(Material? source, Texture? emissionTexture) { if ((Object)(object)emissionTexture != (Object)null) { return true; } if ((Object)(object)source == (Object)null) { return false; } string[] emissionTogglePropertyCandidates = EmissionTogglePropertyCandidates; foreach (string text in emissionTogglePropertyCandidates) { if (source.HasProperty(text) && source.GetFloat(text) > 0.5f) { return true; } } return source.IsKeywordEnabled("_EMISSION"); } private static Color ClampColor(Color color, float maxChannel) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) maxChannel = Mathf.Max(0f, maxChannel); return new Color(Mathf.Clamp(color.r, 0f, maxChannel), Mathf.Clamp(color.g, 0f, maxChannel), Mathf.Clamp(color.b, 0f, maxChannel), Mathf.Clamp01(color.a)); } private static Bounds CalculateRendererBounds(GameObject root) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return new Bounds(Vector3.zero, Vector3.zero); } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } private static void ValidateFile(string path) { if (!File.Exists(path)) { throw new FileNotFoundException("Required Unity asset bundle file was not found.", path); } } private static AudioClip? ResolveAudioClip(AudioSource? audioSource) { if ((Object)(object)audioSource == (Object)null) { return null; } if ((Object)(object)audioSource.clip != (Object)null) { return audioSource.clip; } AudioResource resource = audioSource.resource; return (AudioClip?)(object)((resource is AudioClip) ? resource : null); } } } namespace MikuDanceProject.Core { internal enum DanceConfigKey { ModEnabled, EnableAudio, AudioVolume, AudioRangeMeters, StabilizeModelLighting, LightingExposureCompensation, ModelScale, SpawnModelKey } internal sealed class LocalizedConfigEntry { public DanceConfigKey Key { get; } public ConfigEntryBase Entry { get; } public LocalizedConfigEntry(DanceConfigKey key, ConfigEntryBase entry) { Key = key; Entry = entry; } } internal static class DanceConfigLocalization { [CompilerGenerated] private sealed class d__23 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private ConfigDefinition <>2__current; private int <>l__initialThreadId; private DanceConfigKey configKey; public DanceConfigKey <>3__configKey; private string[] 5__2; private string[] <>7__wrap2; private int <>7__wrap3; private string
5__5; private string[] <>7__wrap5; private int <>7__wrap6; ConfigDefinition IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>7__wrap2 = null;
5__5 = null; <>7__wrap5 = null; <>1__state = -2; } private bool MoveNext() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00dc; } <>1__state = -1; string[] array = new string[2] { "Settings", "设置" }; 5__2 = new string[3] { GetKeyName(configKey, isChineseLanguage: false), GetKeyName(configKey, isChineseLanguage: true), GetLegacyKeyName(configKey) }; <>7__wrap2 = array; <>7__wrap3 = 0; goto IL_0116; IL_0116: if (<>7__wrap3 < <>7__wrap2.Length) {
5__5 = <>7__wrap2[<>7__wrap3]; <>7__wrap5 = 5__2; <>7__wrap6 = 0; goto IL_00ea; } <>7__wrap2 = null; return false; IL_00ea: if (<>7__wrap6 < <>7__wrap5.Length) { string text = <>7__wrap5[<>7__wrap6]; if (!string.IsNullOrWhiteSpace(text)) { <>2__current = new ConfigDefinition(
5__5, text); <>1__state = 1; return true; } goto IL_00dc; } <>7__wrap5 = null;
5__5 = null; <>7__wrap3++; goto IL_0116; IL_00dc: <>7__wrap6++; goto IL_00ea; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__23 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__23(0); } d__.configKey = <>3__configKey; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__24 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private ConfigDefinition <>2__current; private int <>l__initialThreadId; private string[] 5__2; private string[] <>7__wrap2; private int <>7__wrap3; private string
5__5; private string[] <>7__wrap5; private int <>7__wrap6; ConfigDefinition IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>7__wrap2 = null;
5__5 = null; <>7__wrap5 = null; <>1__state = -2; } private bool MoveNext() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00d2; } <>1__state = -1; string[] array = new string[3] { "Settings", "设置", "Internal" }; 5__2 = new string[3] { "SavedAirportPlacement", GetSavedAirportPlacementKeyName(isChineseLanguage: false), GetSavedAirportPlacementKeyName(isChineseLanguage: true) }; <>7__wrap2 = array; <>7__wrap3 = 0; goto IL_010c; IL_010c: if (<>7__wrap3 < <>7__wrap2.Length) {
5__5 = <>7__wrap2[<>7__wrap3]; <>7__wrap5 = 5__2; <>7__wrap6 = 0; goto IL_00e0; } <>7__wrap2 = null; return false; IL_00e0: if (<>7__wrap6 < <>7__wrap5.Length) { string text = <>7__wrap5[<>7__wrap6]; if (!string.IsNullOrWhiteSpace(text)) { <>2__current = new ConfigDefinition(
5__5, text); <>1__state = 1; return true; } goto IL_00d2; } <>7__wrap5 = null;
5__5 = null; <>7__wrap3++; goto IL_010c; IL_00d2: <>7__wrap6++; goto IL_00e0; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__24(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const int SimplifiedChineseLanguageIndex = 9; private const string SettingsSection = "Settings"; private const string LocalizedSettingsSection = "设置"; private const string LegacyInternalSection = "Internal"; private const string LegacySavedAirportPlacementKey = "SavedAirportPlacement"; private static readonly BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static bool DetectChineseLanguage() { bool isChineseLanguage; bool num = TryGetConfiguredGameLanguage(out isChineseLanguage); string languageName; bool flag = TryGetLocalizedTextLanguageName(out languageName); if (num) { return isChineseLanguage; } if (flag) { return IsChineseLanguageName(languageName); } if (!CultureInfo.CurrentUICulture.Name.StartsWith("zh", StringComparison.OrdinalIgnoreCase) && !CultureInfo.CurrentCulture.Name.StartsWith("zh", StringComparison.OrdinalIgnoreCase) && TimeZoneInfo.Local.Id.IndexOf("China", StringComparison.OrdinalIgnoreCase) < 0) { return TimeZoneInfo.Local.Id.IndexOf("Shanghai", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } public static string BuildLanguageDetectionSummary(bool isChineseLanguage) { bool isChineseLanguage2; string languageValueText; string text = (TryGetConfiguredGameLanguage(out isChineseLanguage2, out languageValueText) ? (languageValueText + "/" + (isChineseLanguage2 ? "Chinese" : "English")) : "unknown"); string languageName; string text2 = (TryGetLocalizedTextLanguageName(out languageName) ? languageName : "unknown"); return (isChineseLanguage ? "Chinese" : "English") + " (prefs=" + text + ", runtime=" + text2 + ")"; } public static string GetSectionName(bool isChineseLanguage) { if (!isChineseLanguage) { return "Settings"; } return "设置"; } public static string GetSavedAirportPlacementKeyName(bool isChineseLanguage) { if (!isChineseLanguage) { return "Saved Airport Placement"; } return "保存的机场展示位置"; } public static string GetSavedAirportPlacementDescription(bool isChineseLanguage) { if (!isChineseLanguage) { return "Internal serialized Airport showcase placement. Managed automatically by the plugin."; } return "内部使用的机场展示位置。插件会自动管理这个值。"; } public static string GetKeyName(DanceConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case DanceConfigKey.ModEnabled: return "启用 Miku 展示"; case DanceConfigKey.EnableAudio: return "启用音乐"; case DanceConfigKey.AudioVolume: return "音乐音量"; case DanceConfigKey.AudioRangeMeters: return "音乐可听范围"; case DanceConfigKey.StabilizeModelLighting: return "稳定模型光照"; case DanceConfigKey.LightingExposureCompensation: return "光照曝光补偿"; case DanceConfigKey.ModelScale: return "模型大小"; case DanceConfigKey.SpawnModelKey: return "移动模型按键"; } } return configKey switch { DanceConfigKey.ModEnabled => "Enable Miku Showcase", DanceConfigKey.EnableAudio => "Enable Audio", DanceConfigKey.AudioVolume => "Audio Volume", DanceConfigKey.AudioRangeMeters => "Audio Range Meters", DanceConfigKey.StabilizeModelLighting => "Stabilize Model Lighting", DanceConfigKey.LightingExposureCompensation => "Lighting Exposure Compensation", DanceConfigKey.ModelScale => "Model Scale", DanceConfigKey.SpawnModelKey => "Spawn Model Key", _ => string.Empty, }; } public static string GetDescription(DanceConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case DanceConfigKey.ModEnabled: return "总开关。关闭后插件仍会加载,但不会生成或移动展示模型。"; case DanceConfigKey.EnableAudio: return "是否播放随展示模型一起打包的音乐。"; case DanceConfigKey.AudioVolume: return "打包音乐源使用的音量,范围 0 到 1。"; case DanceConfigKey.AudioRangeMeters: return "打包音乐源的最大可听距离,单位为米。"; case DanceConfigKey.StabilizeModelLighting: return "开启后会调整运行时材质,降低强光环境下模型过曝发白。"; case DanceConfigKey.LightingExposureCompensation: return "稳定模型光照使用的亮度倍率。数值越低,强光下模型越暗。"; case DanceConfigKey.ModelScale: return "生成展示模型时使用的统一缩放倍率。"; case DanceConfigKey.SpawnModelKey: return "轻按此键会把模型移动到本地玩家附近的地面位置。在机场大厅按住 3 秒,会把大厅展示位置保存到配置文件供下次启动使用。"; } } return configKey switch { DanceConfigKey.ModEnabled => "Master switch. When disabled, the plugin stays loaded but will not spawn or move the display model.", DanceConfigKey.EnableAudio => "Whether the display model plays the bundled audio track.", DanceConfigKey.AudioVolume => "Audio volume applied to the bundled audio source. Range: 0 to 1.", DanceConfigKey.AudioRangeMeters => "Maximum audible range for the bundled audio source, in meters.", DanceConfigKey.StabilizeModelLighting => "When enabled, runtime materials are tuned to reduce over-bright scene lighting on the bundled model.", DanceConfigKey.LightingExposureCompensation => "Brightness multiplier used by Stabilize Model Lighting. Lower values darken strong lighting more.", DanceConfigKey.ModelScale => "Uniform scale applied to the spawned display model.", DanceConfigKey.SpawnModelKey => "Tap this key to move the model to the local player's grounded position. Hold it for 3 seconds in the Airport lobby to save the lobby showcase position into this config file for future launches.", _ => string.Empty, }; } public static bool TryGetConfigKey(string keyName, out DanceConfigKey configKey) { foreach (DanceConfigKey value in Enum.GetValues(typeof(DanceConfigKey))) { if (IsConfigKeyName(keyName, value)) { configKey = value; return true; } } configKey = DanceConfigKey.ModEnabled; return false; } public static bool TryGetLocalizedSectionName(string sectionName, bool isChineseLanguage, out string localizedSectionName) { if (string.Equals(sectionName, "Settings", StringComparison.OrdinalIgnoreCase) || string.Equals(sectionName, "设置", StringComparison.Ordinal) || string.Equals(sectionName, "Internal", StringComparison.OrdinalIgnoreCase)) { localizedSectionName = GetSectionName(isChineseLanguage); return true; } localizedSectionName = string.Empty; return false; } public static void ApplyLocalizedDescriptions(ConfigFile configFile, bool isChineseLanguage) { ConfigEntryBase[] configEntriesSnapshot = GetConfigEntriesSnapshot(configFile); foreach (ConfigEntryBase val in configEntriesSnapshot) { if (val != null && !(val.Definition == (ConfigDefinition)null) && val.Description != null && TryGetConfigKey(val.Definition.Key, out var configKey)) { SetPrivateField(val.Description, "k__BackingField", GetDescription(configKey, isChineseLanguage)); } } } public static void RewriteConfigFileLocalization(string configFilePath, bool isChineseLanguage) { if (!string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath)) { string[] array = File.ReadAllLines(configFilePath); string[] array2 = new string[array.Length]; bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i] ?? string.Empty; flag |= !string.Equals(text, array2[i] = RewriteConfigFileLine(text, isChineseLanguage), StringComparison.Ordinal); } if (flag) { File.WriteAllLines(configFilePath, array2); } } } public static void MigrateLocalizedConfigEntries(ConfigFile configFile, IEnumerable visibleEntries) { IDictionary orphanedEntries = GetOrphanedEntries(configFile); if (orphanedEntries == null || orphanedEntries.Count == 0) { return; } bool flag = false; foreach (LocalizedConfigEntry visibleEntry in visibleEntries) { flag |= TryMigrateLocalizedConfigValue(visibleEntry.Entry, visibleEntry.Key, orphanedEntries); } if (flag) { configFile.Save(); } } public static void MigrateSavedAirportPlacement(ConfigFile configFile, ConfigEntryBase savedAirportPlacementEntry) { IDictionary orphanedEntries = GetOrphanedEntries(configFile); if (orphanedEntries == null || savedAirportPlacementEntry == null) { return; } foreach (ConfigDefinition savedAirportPlacementAliasDefinition in GetSavedAirportPlacementAliasDefinitions()) { if (!DefinitionsEqual(savedAirportPlacementAliasDefinition, savedAirportPlacementEntry.Definition) && orphanedEntries.Contains(savedAirportPlacementAliasDefinition)) { object obj = orphanedEntries[savedAirportPlacementAliasDefinition]; if (obj != null && string.IsNullOrWhiteSpace(savedAirportPlacementEntry.GetSerializedValue())) { savedAirportPlacementEntry.SetSerializedValue(obj.ToString()); } orphanedEntries.Remove(savedAirportPlacementAliasDefinition); } } } public static Dictionary BuildUiLocalizationMap(bool isChineseLanguage) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); AddUiLocalizationPair(dictionary, "MikuShowcase", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "com.github.Thanks.MikuDance", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "Settings", GetSectionName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "设置", GetSectionName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "Internal", GetSectionName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "SavedAirportPlacement", GetSavedAirportPlacementKeyName(isChineseLanguage)); AddUiLocalizationPair(dictionary, GetSavedAirportPlacementKeyName(isChineseLanguage: false), GetSavedAirportPlacementKeyName(isChineseLanguage)); AddUiLocalizationPair(dictionary, GetSavedAirportPlacementKeyName(isChineseLanguage: true), GetSavedAirportPlacementKeyName(isChineseLanguage)); foreach (DanceConfigKey value in Enum.GetValues(typeof(DanceConfigKey))) { string sectionName = GetSectionName(isChineseLanguage); string keyName = GetKeyName(value, isChineseLanguage); AddUiLocalizationPair(dictionary, "Settings", sectionName); AddUiLocalizationPair(dictionary, "设置", sectionName); AddUiLocalizationPair(dictionary, GetKeyName(value, isChineseLanguage: false), keyName); AddUiLocalizationPair(dictionary, ToReadableName(GetKeyName(value, isChineseLanguage: false)), keyName); AddUiLocalizationPair(dictionary, GetKeyName(value, isChineseLanguage: true), keyName); AddUiLocalizationPair(dictionary, GetLegacyKeyName(value), keyName); AddUiLocalizationPair(dictionary, ToReadableName(GetLegacyKeyName(value)), keyName); AddUiLocalizationPair(dictionary, GetDescription(value, isChineseLanguage: false), GetDescription(value, isChineseLanguage)); AddUiLocalizationPair(dictionary, GetDescription(value, isChineseLanguage: true), GetDescription(value, isChineseLanguage)); } return dictionary; } private static string RewriteConfigFileLine(string line, bool isChineseLanguage) { if (string.IsNullOrWhiteSpace(line)) { return line ?? string.Empty; } string text = line.Trim(); if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal)) { if (!TryGetLocalizedSectionName(text.Substring(1, text.Length - 2).Trim(), isChineseLanguage, out string localizedSectionName)) { return line; } int num = line.IndexOf('['); int num2 = line.LastIndexOf(']'); if (num >= 0 && num2 >= num) { return line.Substring(0, num + 1) + localizedSectionName + line.Substring(num2); } return line; } if (!TrySplitConfigSettingLine(line, out string leading, out string keyName, out string separatorAndValue) || (!TryGetConfigKey(keyName, out var configKey) && !IsSavedAirportPlacementKeyName(keyName))) { return line; } if (IsSavedAirportPlacementKeyName(keyName)) { return leading + GetSavedAirportPlacementKeyName(isChineseLanguage) + separatorAndValue; } return leading + GetKeyName(configKey, isChineseLanguage) + separatorAndValue; } private static bool TrySplitConfigSettingLine(string line, out string leading, out string keyName, out string separatorAndValue) { leading = string.Empty; keyName = string.Empty; separatorAndValue = string.Empty; if (string.IsNullOrWhiteSpace(line)) { return false; } string text = line.TrimStart(Array.Empty()); if (text.StartsWith("#", StringComparison.Ordinal) || text.StartsWith(";", StringComparison.Ordinal)) { return false; } int num = line.IndexOf('='); if (num <= 0) { return false; } int i; for (i = 0; i < num && char.IsWhiteSpace(line[i]); i++) { } int num2 = num - 1; while (num2 >= i && char.IsWhiteSpace(line[num2])) { num2--; } if (num2 < i) { return false; } leading = line.Substring(0, i); keyName = line.Substring(i, num2 - i + 1); separatorAndValue = line.Substring(num2 + 1); return true; } private static bool TryMigrateLocalizedConfigValue(ConfigEntryBase entry, DanceConfigKey configKey, IDictionary orphanedEntries) { if (entry == null || entry.Definition == (ConfigDefinition)null || orphanedEntries == null) { return false; } bool flag = false; foreach (ConfigDefinition aliasDefinition in GetAliasDefinitions(configKey)) { if (DefinitionsEqual(aliasDefinition, entry.Definition) || !orphanedEntries.Contains(aliasDefinition)) { continue; } if (!flag) { object obj = orphanedEntries[aliasDefinition]; if (obj != null) { entry.SetSerializedValue(obj.ToString()); } flag = true; } orphanedEntries.Remove(aliasDefinition); } return flag; } [IteratorStateMachine(typeof(d__23))] private static IEnumerable GetAliasDefinitions(DanceConfigKey configKey) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(-2) { <>3__configKey = configKey }; } [IteratorStateMachine(typeof(d__24))] private static IEnumerable GetSavedAirportPlacementAliasDefinitions() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(-2); } private static bool IsConfigKeyName(string keyName, DanceConfigKey configKey) { if (!string.Equals(keyName, GetKeyName(configKey, isChineseLanguage: false), StringComparison.OrdinalIgnoreCase) && !string.Equals(keyName, GetKeyName(configKey, isChineseLanguage: true), StringComparison.Ordinal)) { return string.Equals(keyName, GetLegacyKeyName(configKey), StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsSavedAirportPlacementKeyName(string keyName) { if (!string.Equals(keyName, "SavedAirportPlacement", StringComparison.OrdinalIgnoreCase) && !string.Equals(keyName, GetSavedAirportPlacementKeyName(isChineseLanguage: false), StringComparison.OrdinalIgnoreCase)) { return string.Equals(keyName, GetSavedAirportPlacementKeyName(isChineseLanguage: true), StringComparison.Ordinal); } return true; } private static string GetLegacyKeyName(DanceConfigKey configKey) { return configKey switch { DanceConfigKey.ModEnabled => "ModEnabled", DanceConfigKey.EnableAudio => "EnableAudio", DanceConfigKey.AudioVolume => "AudioVolume", DanceConfigKey.AudioRangeMeters => "AudioRangeMeters", DanceConfigKey.StabilizeModelLighting => "StabilizeModelLighting", DanceConfigKey.LightingExposureCompensation => "LightingExposureCompensation", DanceConfigKey.ModelScale => "ModelScale", DanceConfigKey.SpawnModelKey => "SpawnModelKey", _ => string.Empty, }; } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage) { string languageValueText; return TryGetConfiguredGameLanguage(out isChineseLanguage, out languageValueText); } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage, out string languageValueText) { isChineseLanguage = false; languageValueText = string.Empty; try { if (!PlayerPrefs.HasKey("LanguageSetting")) { return false; } int result = PlayerPrefs.GetInt("LanguageSetting", int.MinValue); if (result != int.MinValue) { languageValueText = result.ToString(CultureInfo.InvariantCulture); isChineseLanguage = IsChineseLanguageIndex(result); return true; } string text = (languageValueText = PlayerPrefs.GetString("LanguageSetting", string.Empty)); if (string.IsNullOrWhiteSpace(text)) { return false; } if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { isChineseLanguage = IsChineseLanguageIndex(result); return true; } isChineseLanguage = IsChineseLanguageName(text); return true; } catch { return false; } } private static bool TryGetLocalizedTextLanguageName(out string languageName) { languageName = string.Empty; try { languageName = ((object)(Language)(ref LocalizedText.CURRENT_LANGUAGE)).ToString(); return !string.IsNullOrWhiteSpace(languageName); } catch { return false; } } private static bool IsChineseLanguageName(string languageName) { if (string.IsNullOrWhiteSpace(languageName)) { return false; } if (int.TryParse(languageName.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return IsChineseLanguageIndex(result); } if (languageName.IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) < 0 && languageName.IndexOf("中文", StringComparison.OrdinalIgnoreCase) < 0) { return languageName.StartsWith("zh", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsChineseLanguageIndex(int languageValue) { if (languageValue != 9) { return languageValue == 10; } return true; } private static ConfigEntryBase[] GetConfigEntriesSnapshot(ConfigFile configFile) { PropertyInfo property = typeof(ConfigFile).GetProperty("Entries", InstanceFlags); if (configFile == null || !(property?.GetValue(configFile) is IDictionary dictionary) || dictionary.Count == 0) { return Array.Empty(); } List list = new List(); foreach (DictionaryEntry item in dictionary) { object? value = item.Value; ConfigEntryBase val = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); if (val != null) { list.Add(val); } } return list.ToArray(); } private static IDictionary? GetOrphanedEntries(ConfigFile configFile) { return ((object)configFile)?.GetType().GetProperty("OrphanedEntries", InstanceFlags)?.GetValue(configFile) as IDictionary; } private static bool DefinitionsEqual(ConfigDefinition left, ConfigDefinition right) { if (string.Equals((left != null) ? left.Section : null, (right != null) ? right.Section : null, StringComparison.Ordinal)) { return string.Equals((left != null) ? left.Key : null, (right != null) ? right.Key : null, StringComparison.Ordinal); } return false; } private static void SetPrivateField(object target, string fieldName, object value) { if (target != null && !string.IsNullOrWhiteSpace(fieldName)) { target.GetType().GetField(fieldName, InstanceFlags)?.SetValue(target, value); } } private static void AddUiLocalizationPair(Dictionary map, string source, string localized) { if (map != null && !string.IsNullOrWhiteSpace(source) && !string.IsNullOrWhiteSpace(localized)) { string text = source.Trim(); string text3 = (map[text] = localized.Trim()); map[text3] = text3; string key = text.Replace(" ", string.Empty); string key2 = text3.Replace(" ", string.Empty); if (!map.ContainsKey(key)) { map[key] = text3; } if (!map.ContainsKey(key2)) { map[key2] = text3; } map[text.ToUpperInvariant()] = text3; map[text3.ToUpperInvariant()] = text3; } } private static string ToReadableName(string keyName) { if (string.IsNullOrWhiteSpace(keyName)) { return string.Empty; } List list = new List(keyName.Length + 8); for (int i = 0; i < keyName.Length; i++) { char c = keyName[i]; if (i > 0 && char.IsUpper(c) && !char.IsWhiteSpace(keyName[i - 1]) && !char.IsUpper(keyName[i - 1])) { list.Add(' '); } list.Add(c); } return new string(list.ToArray()); } private static string GetLocalizedModDisplayName(bool isChineseLanguage) { if (!isChineseLanguage) { return "MikuShowcase"; } return "Miku 展示"; } } internal sealed class DancePluginConfig { private const string SettingsSection = "Settings"; private readonly string _pluginDirectory; private readonly ConfigFile _configFile; private readonly ConfigEntry _savedAirportPlacement; private readonly List _visibleEntries = new List(); public ConfigEntry ModEnabled { get; } public ConfigEntry EnableAudio { get; } public ConfigEntry AudioVolume { get; } public ConfigEntry AudioRangeMeters { get; } public ConfigEntry StabilizeModelLighting { get; } public ConfigEntry LightingExposureCompensation { get; } public ConfigEntry ModelScale { get; } public ConfigEntry SpawnModelKey { get; } public ConfigEntry SavedAirportPlacementEntry => _savedAirportPlacement; public bool IsChineseLanguage { get; private set; } public IReadOnlyList VisibleEntries => _visibleEntries; public float ResolvedModelScale => Mathf.Clamp(ModelScale.Value, 0.1f, 3f); public float ResolvedAudioVolume => Mathf.Clamp01(AudioVolume.Value); public float ResolvedAudioRangeMeters => Mathf.Clamp(AudioRangeMeters.Value, 1f, 30f); public float ResolvedLightingExposureCompensation => Mathf.Clamp(LightingExposureCompensation.Value, 0.4f, 1f); public DancePluginConfig(ConfigFile config, string pluginDirectory) { _configFile = config; _pluginDirectory = Path.GetFullPath(pluginDirectory); IsChineseLanguage = DanceConfigLocalization.DetectChineseLanguage(); ModEnabled = BindEntry(DanceConfigKey.ModEnabled, defaultValue: true, null); EnableAudio = BindEntry(DanceConfigKey.EnableAudio, defaultValue: true, null); AudioVolume = BindEntry(DanceConfigKey.AudioVolume, 0.1f, (AcceptableValueBase?)(object)new AcceptableValueRange(0f, 1f)); AudioRangeMeters = BindEntry(DanceConfigKey.AudioRangeMeters, 5f, (AcceptableValueBase?)(object)new AcceptableValueRange(1f, 30f)); StabilizeModelLighting = BindEntry(DanceConfigKey.StabilizeModelLighting, defaultValue: true, null); LightingExposureCompensation = BindEntry(DanceConfigKey.LightingExposureCompensation, 0.82f, (AcceptableValueBase?)(object)new AcceptableValueRange(0.4f, 1f)); ModelScale = BindEntry(DanceConfigKey.ModelScale, 1.2f, (AcceptableValueBase?)(object)new AcceptableValueRange(0.1f, 3f)); SpawnModelKey = BindEntry(DanceConfigKey.SpawnModelKey, (KeyCode)289, null); _savedAirportPlacement = config.Bind(DanceConfigLocalization.GetSectionName(IsChineseLanguage), DanceConfigLocalization.GetSavedAirportPlacementKeyName(IsChineseLanguage), string.Empty, DanceConfigLocalization.GetSavedAirportPlacementDescription(IsChineseLanguage)); DanceConfigLocalization.MigrateSavedAirportPlacement(config, (ConfigEntryBase)(object)_savedAirportPlacement); DanceConfigLocalization.MigrateLocalizedConfigEntries(config, _visibleEntries); RemoveObsoleteConfigEntries(config.ConfigFilePath); Save(); } public string ResolveUnityBundlePath() { string[] array = new string[3] { Path.Combine(_pluginDirectory, "miku_lobby_display.bundle"), Path.Combine(_pluginDirectory, "UnityBundle\\miku_lobby_display.bundle"), Path.Combine(_pluginDirectory, "Assets\\UnityBundle\\miku_lobby_display.bundle") }; return array.Select(Path.GetFullPath).FirstOrDefault(File.Exists) ?? Path.GetFullPath(array[0]); } public void Save() { _configFile.Save(); DanceConfigLocalization.RewriteConfigFileLocalization(_configFile.ConfigFilePath, IsChineseLanguage); } public bool RefreshLocalization(bool isChineseLanguage, bool saveConfigFile) { bool result = IsChineseLanguage != isChineseLanguage; IsChineseLanguage = isChineseLanguage; DanceConfigLocalization.ApplyLocalizedDescriptions(_configFile, IsChineseLanguage); if (saveConfigFile) { Save(); return result; } DanceConfigLocalization.RewriteConfigFileLocalization(_configFile.ConfigFilePath, IsChineseLanguage); return result; } public bool TryGetSavedAirportPlacement(out Vector3 position, out Vector3 forward) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); forward = Vector3.forward; string value = _savedAirportPlacement.Value; if (string.IsNullOrWhiteSpace(value)) { return false; } string[] array = value.Split(new char[1] { '|' }); if (array.Length != 2) { return false; } if (!TryParseVector3(array[0], out position) || !TryParseVector3(array[1], out forward)) { position = default(Vector3); forward = Vector3.forward; return false; } forward = Vector3.ProjectOnPlane(forward, Vector3.up); if (((Vector3)(ref forward)).sqrMagnitude <= 0.0001f) { forward = Vector3.forward; } else { ((Vector3)(ref forward)).Normalize(); } return true; } public void SaveAirportPlacement(Vector3 position, Vector3 forward) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Vector3 value = Vector3.ProjectOnPlane(forward, Vector3.up); if (((Vector3)(ref value)).sqrMagnitude <= 0.0001f) { value = Vector3.forward; } else { ((Vector3)(ref value)).Normalize(); } _savedAirportPlacement.Value = SerializeVector3(position) + "|" + SerializeVector3(value); Save(); } private ConfigEntry BindEntry(DanceConfigKey configKey, T defaultValue, AcceptableValueBase? acceptableValues) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ConfigEntry val = _configFile.Bind(DanceConfigLocalization.GetSectionName(IsChineseLanguage), DanceConfigLocalization.GetKeyName(configKey, IsChineseLanguage), defaultValue, new ConfigDescription(DanceConfigLocalization.GetDescription(configKey, IsChineseLanguage), acceptableValues, Array.Empty())); _visibleEntries.Add(new LocalizedConfigEntry(configKey, (ConfigEntryBase)(object)val)); return val; } private static void RemoveObsoleteConfigEntries(string configPath) { if (!File.Exists(configPath)) { return; } HashSet obsoleteKeys = new HashSet { "AssetRootPath", "ModelPath", "MotionPath", "VerticalOffset", "ModelPitchCorrection", "ModelRollCorrection", "LobbyPositionX", "LobbyPositionY", "LobbyPositionZ", "GroundProbeMaxDistance", "UseManualLobbyPlacement", "ManualLobbyPositionX", "ManualLobbyPositionY", "ManualLobbyPositionZ", "ManualLobbyForwardX", "ManualLobbyForwardY", "ManualLobbyForwardZ", "PitchOffset", "YawOffset", "RollOffset", "ElevatorForwardOffset", "ElevatorRightOffset", "FallbackPositionX", "FallbackPositionY", "FallbackPositionZ", "SpawnForwardOffset", "SpawnRightOffset", "PreferredLobbyPositionX", "PreferredLobbyPositionY", "PreferredLobbyPositionZ", "ModelYawCorrection" }; string[] array = File.ReadAllLines(configPath); List list = new List(array.Length); for (int i = 0; i < array.Length; i++) { string text = array[i]; if (!IsObsoleteConfigValueLine(text, obsoleteKeys)) { list.Add(text); continue; } while (list.Count > 0 && string.IsNullOrWhiteSpace(list[list.Count - 1])) { list.RemoveAt(list.Count - 1); } while (list.Count > 0 && list[list.Count - 1].StartsWith("#", StringComparison.Ordinal)) { list.RemoveAt(list.Count - 1); } for (; i + 1 < array.Length && string.IsNullOrWhiteSpace(array[i + 1]); i++) { } } if (list.Count != array.Length) { File.WriteAllLines(configPath, list); } } private static bool IsObsoleteConfigValueLine(string line, HashSet obsoleteKeys) { int num = line.IndexOf(" = ", StringComparison.Ordinal); if (num <= 0) { return false; } string item = line.Substring(0, num); return obsoleteKeys.Contains(item); } private static string SerializeVector3(Vector3 value) { return string.Join(",", value.x.ToString("R", CultureInfo.InvariantCulture), value.y.ToString("R", CultureInfo.InvariantCulture), value.z.ToString("R", CultureInfo.InvariantCulture)); } private static bool TryParseVector3(string serialized, out Vector3 value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) value = default(Vector3); string[] array = serialized.Split(new char[1] { ',' }); if (array.Length != 3) { return false; } if (!float.TryParse(array[0], NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result3)) { return false; } value = new Vector3(result, result2, result3); return true; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.Thanks.MikuDance", "MikuShowcase", "1.0.0")] public sealed class MikuDancePlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__6 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public MikuDancePlugin <>4__this; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown int num = <>1__state; MikuDancePlugin mikuDancePlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (mikuDancePlugin._pluginConfig == null) { return false; } 5__2 = 0; break; case 1: <>1__state = -1; 5__2++; break; } if (5__2 < 20) { if (OptionalModConfigBridge.TryRegister(mikuDancePlugin._pluginConfig, ((BaseUnityPlugin)mikuDancePlugin).Logger)) { return false; } <>2__current = (object)new WaitForSecondsRealtime(0.5f); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float ModConfigUiLocalizationIntervalSeconds = 0.25f; private DancePluginConfig? _pluginConfig; private float _nextModConfigUiLocalizationTime; private void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath; DancePluginConfig dancePluginConfig = (_pluginConfig = new DancePluginConfig(((BaseUnityPlugin)this).Config, text)); GameObject val = new GameObject("MikuDanceController"); Object.DontDestroyOnLoad((Object)val); val.AddComponent().Initialize(dancePluginConfig, ((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogDebug((object)("MikuShowcase plugin initialized. pluginDirectory='" + text + "', bundlePath='" + dancePluginConfig.ResolveUnityBundlePath() + "', configPath='" + ((BaseUnityPlugin)this).Config.ConfigFilePath + "'.")); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[MikuShowcase] Config language: " + DanceConfigLocalization.BuildLanguageDetectionSummary(dancePluginConfig.IsChineseLanguage))); } private void Start() { ((MonoBehaviour)this).StartCoroutine(RegisterModConfigRoutine()); } private void Update() { if (_pluginConfig != null) { bool flag = DanceConfigLocalization.DetectChineseLanguage(); if (_pluginConfig.IsChineseLanguage != flag && _pluginConfig.RefreshLocalization(flag, saveConfigFile: true)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[MikuShowcase] Config language changed: " + (flag ? "Chinese" : "English"))); } if (!(Time.unscaledTime < _nextModConfigUiLocalizationTime)) { _nextModConfigUiLocalizationTime = Time.unscaledTime + 0.25f; OptionalModConfigBridge.TryLocalizeVisibleUi(_pluginConfig); } } } [IteratorStateMachine(typeof(d__6))] private IEnumerator RegisterModConfigRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { <>4__this = this }; } } internal static class OptionalModConfigBridge { [CompilerGenerated] private sealed class d__15 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__15(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { object? obj2; Transform val2; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; object obj = menuInstance; Component val = (Component)((obj is Component) ? obj : null); if (val != null) { <>2__current = val.transform; <>1__state = 1; return true; } goto IL_004d; } case 1: <>1__state = -1; goto IL_004d; case 2: { <>1__state = -1; break; } IL_004d: obj2 = menuType.GetProperty("Content", AllBindings)?.GetValue(menuInstance); val2 = (Transform)((obj2 is Transform) ? obj2 : null); if (val2 != null) { <>2__current = val2; <>1__state = 2; return true; } break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__15 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__15(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__14 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; private HashSet 5__2; private IEnumerator <>7__wrap2; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new HashSet(); <>7__wrap2 = EnumerateCandidateTransforms(menuInstance, menuType).GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap2.MoveNext()) { Transform current = <>7__wrap2.Current; if ((Object)(object)current != (Object)null && 5__2.Add(((Object)current).GetInstanceID())) { <>2__current = current; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap2 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__14 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__14(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const string ModConfigPluginGuid = "com.github.PEAKModding.PEAKLib.ModConfig"; private const string SettingsHandlerUtilityTypeName = "PEAKLib.ModConfig.SettingsHandlerUtility"; private const string ModConfigPluginTypeName = "PEAKLib.ModConfig.ModConfigPlugin"; private static readonly BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static bool _registered; public static bool TryRegister(DancePluginConfig config, ManualLogSource logger) { DancePluginConfig config2 = config; if (_registered) { return true; } try { Type type = FindLoadedType("PEAKLib.ModConfig.SettingsHandlerUtility"); Type type2 = FindLoadedType("PEAKLib.ModConfig.ModConfigPlugin"); if (type == null || type2 == null) { return false; } object obj = type2.GetField("instance", AllBindings)?.GetValue(null); if (obj == null) { return false; } if (!(type2.GetProperty("EntriesProcessed", AllBindings)?.GetValue(obj, null) is IList entriesProcessed)) { return false; } string sectionName = DanceConfigLocalization.GetSectionName(config2.IsChineseLanguage); InvokeBool(type, (ConfigEntryBase)(object)config2.ModEnabled, sectionName, delegate(bool value) { config2.ModEnabled.Value = value; config2.Save(); }); InvokeBool(type, (ConfigEntryBase)(object)config2.EnableAudio, sectionName, delegate(bool value) { config2.EnableAudio.Value = value; config2.Save(); }); InvokeFloat(type, (ConfigEntryBase)(object)config2.AudioVolume, sectionName, delegate(float value) { config2.AudioVolume.Value = value; config2.Save(); }); InvokeFloat(type, (ConfigEntryBase)(object)config2.AudioRangeMeters, sectionName, delegate(float value) { config2.AudioRangeMeters.Value = value; config2.Save(); }); InvokeBool(type, (ConfigEntryBase)(object)config2.StabilizeModelLighting, sectionName, delegate(bool value) { config2.StabilizeModelLighting.Value = value; config2.Save(); }); InvokeFloat(type, (ConfigEntryBase)(object)config2.LightingExposureCompensation, sectionName, delegate(float value) { config2.LightingExposureCompensation.Value = value; config2.Save(); }); InvokeFloat(type, (ConfigEntryBase)(object)config2.ModelScale, sectionName, delegate(float value) { config2.ModelScale.Value = value; config2.Save(); }); InvokeKeybind(type, (ConfigEntryBase)(object)config2.SpawnModelKey, sectionName, delegate(KeyCode value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) config2.SpawnModelKey.Value = value; config2.Save(); }); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.ModEnabled); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.EnableAudio); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.AudioVolume); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.AudioRangeMeters); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.StabilizeModelLighting); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.LightingExposureCompensation); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.ModelScale); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.SpawnModelKey); MarkProcessed(entriesProcessed, (ConfigEntryBase)(object)config2.SavedAirportPlacementEntry); _registered = true; TryLocalizeVisibleUi(config2); logger.LogDebug((object)("Registered ModConfig entries into a single '" + sectionName + "' page.")); return true; } catch (Exception arg) { logger.LogError((object)$"Failed to register ModConfig bridge: {arg}"); return true; } } public static void TryLocalizeVisibleUi(DancePluginConfig config) { if (config == null || !TryGetModConfigMenuInstance(out Type menuType, out object menuInstance) || menuType == null || menuInstance == null) { return; } Behaviour val = (Behaviour)((menuInstance is Behaviour) ? menuInstance : null); if (val == null || (Object)(object)val == (Object)null) { return; } try { if (!val.isActiveAndEnabled || !((Component)val).gameObject.activeInHierarchy) { return; } } catch { return; } Dictionary map = DanceConfigLocalization.BuildUiLocalizationMap(config.IsChineseLanguage); foreach (Transform item in EnumerateModConfigUiRoots(menuInstance, menuType)) { ApplyTextLocalizationToRoot(item, map); } ApplyTextLocalizationToLoadedUi(map); } private static void InvokeBool(Type settingsType, ConfigEntryBase entry, string tabName, Action callback) { Invoke(settingsType, "AddBoolToTab", entry, tabName, callback); } private static void InvokeFloat(Type settingsType, ConfigEntryBase entry, string tabName, Action callback) { Invoke(settingsType, "AddFloatToTab", entry, tabName, callback); } private static void InvokeKeybind(Type settingsType, ConfigEntryBase entry, string tabName, Action callback) { Invoke(settingsType, "AddKeybindToTab", entry, tabName, callback); } private static void Invoke(Type settingsType, string methodName, ConfigEntryBase entry, string tabName, Delegate callback) { string methodName2 = methodName; MethodInfo? methodInfo = settingsType.GetMethods(AllBindings).FirstOrDefault((MethodInfo candidate) => string.Equals(candidate.Name, methodName2, StringComparison.Ordinal) && candidate.GetParameters().Length == 3); if (methodInfo == null) { throw new MissingMethodException(settingsType.FullName, methodName2); } methodInfo.Invoke(null, new object[3] { entry, tabName, callback }); } private static void MarkProcessed(IList entriesProcessed, ConfigEntryBase entry) { if (!entriesProcessed.Contains(entry)) { entriesProcessed.Add(entry); } } private static Type? FindLoadedType(string fullName) { string fullName2 = fullName; return (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType(fullName2, throwOnError: false, ignoreCase: false)).FirstOrDefault((Type type) => type != null); } private static bool TryGetModConfigMenuInstance(out Type? menuType, out object? menuInstance) { menuType = null; menuInstance = null; if (!Chainloader.PluginInfos.TryGetValue("com.github.PEAKModding.PEAKLib.ModConfig", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return false; } Assembly assembly = ((object)value.Instance).GetType().Assembly; menuType = assembly.GetType("PEAKLib.ModConfig.Components.ModdedSettingsMenu"); menuInstance = menuType?.GetProperty("Instance", AllBindings)?.GetValue(null); if (menuType != null) { return menuInstance != null; } return false; } [IteratorStateMachine(typeof(d__14))] private static IEnumerable EnumerateModConfigUiRoots(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } [IteratorStateMachine(typeof(d__15))] private static IEnumerable EnumerateCandidateTransforms(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } private static void ApplyTextLocalizationToRoot(Transform root, Dictionary map) { if (!((Object)(object)root == (Object)null) && map != null && map.Count != 0) { TMP_Text[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyTextLocalization(componentsInChildren[i], map); } } } private static void ApplyTextLocalizationToLoadedUi(Dictionary map) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (map == null || map.Count == 0) { return; } try { TMP_Text[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { ApplyTextLocalization(val, map); } } } } catch { } } private static void ApplyTextLocalization(TMP_Text text, Dictionary map) { if (!((Object)(object)text == (Object)null) && map != null && map.Count != 0) { string text2 = ((text.text == null) ? string.Empty : text.text.Trim()); if (!string.IsNullOrWhiteSpace(text2) && map.TryGetValue(text2, out string value) && !string.Equals(text2, value, StringComparison.Ordinal)) { text.text = value; } } } } internal static class PluginConstants { public const string Guid = "com.github.Thanks.MikuDance"; public const string Name = "MikuShowcase"; public const string Version = "1.0.0"; public const string DefaultUnityBundleFileName = "miku_lobby_display.bundle"; public const string LegacyUnityBundlePath = "UnityBundle\\miku_lobby_display.bundle"; public const string LegacyAssetsUnityBundlePath = "Assets\\UnityBundle\\miku_lobby_display.bundle"; } }