Decompiled source of LethalSponge v1.1.8
LethalSponge/LethalSponge.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DunGen; using GameNetcodeStuff; using HarmonyLib; using LethalLevelLoader; using LethalLevelLoader.AssetBundles; using Microsoft.CodeAnalysis; using MoreCompany.Cosmetics; using Scoops; using Scoops.compatibility; using Scoops.patches; using Scoops.rendering; using Scoops.service; using Sponge.Utilities.IL; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Experimental.Rendering; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityMeshSimplifier; using UnityMeshSimplifier.Internal; using UnityMeshSimplifier.Utility; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: InternalsVisibleTo("Whinarn.UnityMeshSimplifier.Editor")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("LethalLevelLoader")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: AssemblyCompany("LethalSponge")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.0.0")] [assembly: AssemblyInformationalVersion("0.0.0-alpha.0.49+de6ae1242adef43631eec20d6d00e37d1727bdc2")] [assembly: AssemblyProduct("LethalSponge")] [assembly: AssemblyTitle("LethalSponge")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Sponge.Utilities.IL { public class ILInjector { [CompilerGenerated] private sealed class <GetRelativeInstructions>d__32 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private int offset; public int <>3__offset; private int size; public int <>3__size; public ILInjector <>4__this; private int <i>5__1; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetRelativeInstructions>d__32(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__1 = 0; break; case 1: <>1__state = -1; <i>5__1++; break; } if (<i>5__1 < size) { <>2__current = <>4__this.instructions[<>4__this.index + offset + <i>5__1]; <>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(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <GetRelativeInstructions>d__32 <GetRelativeInstructions>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <GetRelativeInstructions>d__ = this; } else { <GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__32(0) { <>4__this = <>4__this }; } <GetRelativeInstructions>d__.offset = <>3__offset; <GetRelativeInstructions>d__.size = <>3__size; return <GetRelativeInstructions>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private const string INVALID = "Injector is invalid"; private const string MATCH_END_INVALID = "The end of the last search was invalid"; private List<CodeInstruction> instructions = instructions.ToList(); private ILGenerator generator; private int index; private int matchEnd; public bool IsValid => instructions != null && IsIndexValid(index); public CodeInstruction Instruction { get { if (!IsIndexInRange(index)) { return null; } return instructions[index]; } set { if (!IsIndexInRange(index)) { throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}"); } instructions[index] = value; } } public CodeInstruction LastMatchedInstruction { get { int num = matchEnd - 1; if (!IsIndexInRange(num)) { return null; } return instructions[num]; } set { int num = matchEnd - 1; if (!IsIndexInRange(num)) { throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}"); } instructions[num] = value; } } public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly(); public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null) { this.generator = generator; index = 0; matchEnd = -1; base..ctor(); } public ILInjector GoToStart() { matchEnd = index; index = 0; return this; } public ILInjector GoToEnd() { matchEnd = index; index = instructions.Count; return this; } public ILInjector Forward(int offset) { if (!IsValid) { return this; } matchEnd = index; index = Math.Clamp(index + offset, -1, instructions.Count); return this; } public ILInjector Back(int offset) { return Forward(-offset); } private void MarkInvalid() { index = -1; matchEnd = -1; } private void Search(bool forward, ILMatcher[] predicates) { if (!IsValid) { return; } int num = 1; if (!forward) { num = -1; index--; } while (forward ? (index < instructions.Count) : (index >= 0)) { if (forward && index + predicates.Length > instructions.Count) { index = instructions.Count; break; } int i; for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++) { } if (i == predicates.Length) { matchEnd = index + i; return; } index += num; } MarkInvalid(); } public ILInjector Find(params ILMatcher[] predicates) { Search(forward: true, predicates); return this; } public ILInjector ReverseFind(params ILMatcher[] predicates) { Search(forward: false, predicates); return this; } public ILInjector GoToPush(int popIndex) { if (!IsValid) { return this; } matchEnd = index; index--; int num = 0; while (index >= 0) { CodeInstruction instruction = instructions[index]; num += instruction.PushCount(); num -= instruction.PopCount(); if (num > popIndex) { return this; } index--; } return this; } public ILInjector SkipBranch() { if (Instruction == null) { return this; } if (!(Instruction.operand is Label label) || 1 == 0) { throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}"); } return FindLabel(label); } public ILInjector FindLabel(Label label) { matchEnd = index + 1; for (index = 0; index < instructions.Count; index++) { if (instructions[index].labels.Contains(label)) { return this; } } MarkInvalid(); return this; } public ILInjector GoToMatchEnd() { index = matchEnd; return this; } public ILInjector GoToLastMatchedInstruction() { if (!IsIndexValid(matchEnd)) { return this; } index = matchEnd - 1; return this; } private bool IsIndexValid(int index) { return index != -1; } private bool IsIndexInRange(int index) { return index >= 0 && index < instructions.Count; } public CodeInstruction GetRelativeInstruction(int offset) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}"); } return instructions[num]; } public void SetRelativeInstruction(int offset, CodeInstruction instruction) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } int num = index + offset; if (!IsIndexInRange(num)) { throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}"); } instructions[num] = instruction; } [IteratorStateMachine(typeof(<GetRelativeInstructions>d__32))] public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetRelativeInstructions>d__32(-2) { <>4__this = this, <>3__offset = offset, <>3__size = size }; } public IEnumerable<CodeInstruction> GetRelativeInstructions(int size) { return GetRelativeInstructions(0, size); } private void GetLastMatchRangeAbsolute(out int start, out int end) { start = index; end = matchEnd; if (start > end) { int num = end; int num2 = start; start = num; end = num2; } } private void GetLastMatchRange(out int start, out int size) { GetLastMatchRangeAbsolute(out start, out var end); if (start < 0 || start >= instructions.Count) { throw new InvalidOperationException($"Last match range starts at invalid index {start}"); } if (end < 0 || end > instructions.Count) { throw new InvalidOperationException($"Last match range ends at invalid index {end}"); } size = end - start; } public List<CodeInstruction> GetLastMatch() { GetLastMatchRange(out var start, out var size); return instructions.GetRange(start, size); } public Label AddLabel() { if (generator == null) { throw new InvalidOperationException("No ILGenerator was provided"); } Label label = generator.DefineLabel(); Instruction.labels.Add(label); return label; } public ILInjector AddLabel(Label label) { Instruction.labels.Add(label); return this; } public ILInjector InsertInPlace(params CodeInstruction[] instructions) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } this.instructions.InsertRange(index, instructions); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector Insert(params CodeInstruction[] instructions) { InsertInPlace(instructions); index += instructions.Length; return this; } public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } List<Label> labels = Instruction.labels; this.instructions.InsertRange(index, instructions); Instruction.labels.AddRange(labels); labels.Clear(); if (matchEnd >= index) { matchEnd += instructions.Length; } return this; } public ILInjector InsertAfterBranch(params CodeInstruction[] instructions) { InsertInPlaceAfterBranch(instructions); index += instructions.Length; return this; } public ILInjector RemoveAllPreviousInstructions() { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(0, index); matchEnd -= index; if (matchEnd < 0) { matchEnd = 0; } index = 0; return this; } public ILInjector Remove(int count = 1) { if (!IsValid) { throw new InvalidOperationException("Injector is invalid"); } instructions.RemoveRange(index, count); if (matchEnd > index) { matchEnd = Math.Max(index, matchEnd - count); } return this; } public ILInjector RemoveLastMatch() { GetLastMatchRange(out var start, out var size); instructions.RemoveRange(start, size); index = start; matchEnd = start; return this; } public ILInjector ReplaceLastMatch(params CodeInstruction[] instructions) { RemoveLastMatch(); Insert(instructions); return this; } public List<CodeInstruction> ReleaseInstructions() { List<CodeInstruction> result = instructions; instructions = null; return result; } public ILInjector PrintContext(int context, string header = "") { if (!IsValid) { throw new InvalidOperationException("Injector is invalid (" + header + ")"); } StringBuilder stringBuilder = new StringBuilder(header); if (header.Length > 0) { stringBuilder.Append(':'); } stringBuilder.AppendLine(); GetLastMatchRangeAbsolute(out var start, out var end); int num = Math.Min(end + 1 + context, instructions.Count); for (int i = Math.Max(start - context, 0); i < num; i++) { if (end == -1 && i == index) { stringBuilder.Append("╶> "); } else { if (i >= start && i < end) { stringBuilder.Append("│"); } else { stringBuilder.Append(" "); } if (i == index) { stringBuilder.Append("╶> "); } else { stringBuilder.Append(" "); } } stringBuilder.AppendLine($"{i}: {instructions[i]}"); } Plugin.Log.LogInfo((object)stringBuilder); return this; } public ILInjector PrintContext(string header = "") { return PrintContext(4, header); } } public interface ILMatcher { private static OpCode[] branchInstructions = new OpCode[4] { OpCodes.Br, OpCodes.Br_S, OpCodes.Brfalse, OpCodes.Brfalse_S }; bool Matches(CodeInstruction instruction); static NotMatcher Not(ILMatcher matcher) { return new NotMatcher(matcher); } static OpcodeMatcher Opcode(OpCode opcode) { return new OpcodeMatcher(opcode); } static OpcodesMatcher Opcodes(params OpCode[] opcodes) { return new OpcodesMatcher(opcodes); } static OpcodeOperandMatcher OpcodeOperand(OpCode opcode, object operand) { return new OpcodeOperandMatcher(opcode, operand); } static InstructionMatcher Instruction(CodeInstruction instruction) { return new InstructionMatcher(instruction); } static LdargMatcher Ldarg(int? arg = null) { return new LdargMatcher(arg); } static LdlocMatcher Ldloc(int? loc = null) { return new LdlocMatcher(loc); } static StlocMatcher Stloc(int? loc = null) { return new StlocMatcher(loc); } static LdcI32Matcher Ldc(int? value = null) { return new LdcI32Matcher(value); } static BranchMatcher Branch() { return new BranchMatcher(); } static OpcodeOperandMatcher Ldfld(FieldInfo field) { if (field == null) { Plugin.Log.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null\n{new StackTrace()}"); } return new OpcodeOperandMatcher(OpCodes.Ldfld, field); } static OpcodeOperandMatcher Ldsfld(FieldInfo field) { if (field == null) { Plugin.Log.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null\n{new StackTrace()}"); } return new OpcodeOperandMatcher(OpCodes.Ldsfld, field); } static OpcodeOperandMatcher Stfld(FieldInfo field) { if (field == null) { Plugin.Log.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null\n{new StackTrace()}"); } return new OpcodeOperandMatcher(OpCodes.Stfld, field); } static OpcodeOperandMatcher Stsfld(FieldInfo field) { if (field == null) { Plugin.Log.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null\n{new StackTrace()}"); } return new OpcodeOperandMatcher(OpCodes.Stsfld, field); } static OpcodeOperandMatcher Callvirt(MethodBase method) { if (method == null) { Plugin.Log.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null\n{new StackTrace()}"); } return OpcodeOperand(OpCodes.Callvirt, method); } static OpcodeOperandMatcher Call(MethodBase method) { if (method == null) { Plugin.Log.LogWarning((object)$"Method passed to ILMatcher.Call() was null\n{new StackTrace()}"); } return OpcodeOperand(OpCodes.Call, method); } static PredicateMatcher Predicate(Func<CodeInstruction, bool> predicate) { return new PredicateMatcher(predicate); } static PredicateMatcher Predicate(Func<FieldInfo, bool> predicate) { return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg)); } } public class NotMatcher : ILMatcher { private readonly ILMatcher matcher; public NotMatcher(ILMatcher matcher) { this.matcher = matcher; base..ctor(); } public bool Matches(CodeInstruction instruction) { return !matcher.Matches(instruction); } } public class OpcodeMatcher : ILMatcher { private readonly OpCode opcode; public OpcodeMatcher(OpCode opcode) { this.opcode = opcode; base..ctor(); } public bool Matches(CodeInstruction instruction) { return instruction.opcode == opcode; } } public class OpcodesMatcher : ILMatcher { private readonly OpCode[] opcodes; public OpcodesMatcher(OpCode[] opcodes) { this.opcodes = opcodes; base..ctor(); } public bool Matches(CodeInstruction instruction) { return opcodes.Contains(instruction.opcode); } } public class OpcodeOperandMatcher : ILMatcher { private readonly OpCode opcode; private readonly object operand; public OpcodeOperandMatcher(OpCode opcode, object operand) { this.opcode = opcode; this.operand = operand; base..ctor(); } public bool Matches(CodeInstruction instruction) { return instruction.opcode == opcode && instruction.operand == operand; } } public class InstructionMatcher : ILMatcher { private readonly OpCode opcode = instruction.opcode; private readonly object operand = instruction.operand; private readonly Label[] labels = instruction.labels.ToArray(); public InstructionMatcher(CodeInstruction instruction) { } public bool Matches(CodeInstruction instruction) { if (instruction.opcode != opcode) { return false; } if (instruction.operand != operand) { return false; } if (instruction.labels.Count != labels.Length) { return false; } for (int i = 0; i < labels.Length; i++) { if (labels[i] != instruction.labels[i]) { return false; } } return true; } } public class LdargMatcher : ILMatcher { private readonly int? arg; public LdargMatcher(int? arg) { this.arg = arg; base..ctor(); } public bool Matches(CodeInstruction instruction) { return arg.HasValue ? (instruction.GetLdargIndex() == arg) : instruction.GetLdargIndex().HasValue; } } public class LdlocMatcher : ILMatcher { private readonly int? loc; public LdlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { return loc.HasValue ? (instruction.GetLdlocIndex() == loc) : instruction.GetLdlocIndex().HasValue; } } public class StlocMatcher : ILMatcher { private readonly int? loc; public StlocMatcher(int? loc) { this.loc = loc; base..ctor(); } public bool Matches(CodeInstruction instruction) { return loc.HasValue ? (instruction.GetStlocIndex() == loc) : instruction.GetStlocIndex().HasValue; } } public class LdcI32Matcher : ILMatcher { private readonly int? value; public LdcI32Matcher(int? value) { this.value = value; base..ctor(); } public bool Matches(CodeInstruction instruction) { return (!value.HasValue && instruction.GetLdcI32().HasValue) || instruction.GetLdcI32() == value; } } public class BranchMatcher : ILMatcher { public bool Matches(CodeInstruction instruction) { Label? label = default(Label?); return CodeInstructionExtensions.Branches(instruction, ref label); } } public class PredicateMatcher : ILMatcher { private readonly Func<CodeInstruction, bool> predicate; public PredicateMatcher(Func<CodeInstruction, bool> predicate) { this.predicate = predicate; base..ctor(); } public bool Matches(CodeInstruction instruction) { return predicate(instruction); } } internal static class InstructionUtilities { public static CodeInstruction MakeLdarg(int index) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if (1 == 0) { } CodeInstruction result = (CodeInstruction)((index >= 256) ? ((object)new CodeInstruction(OpCodes.Ldarg, (object)index)) : (index switch { 0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null), 1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null), 2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null), 3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null), _ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index), })); if (1 == 0) { } return result; } public static int PopCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) { MethodInfo methodInfo = (MethodInfo)instruction.operand; int num = methodInfo.GetParameters().Length; if (!methodInfo.IsStatic) { num++; } return num; } if (instruction.opcode == OpCodes.Ret) { return 1; } StackBehaviour stackBehaviourPop = instruction.opcode.StackBehaviourPop; if (1 == 0) { } int result = stackBehaviourPop switch { StackBehaviour.Pop0 => 0, StackBehaviour.Pop1 => 1, StackBehaviour.Pop1_pop1 => 2, StackBehaviour.Popi => 1, StackBehaviour.Popi_pop1 => 2, StackBehaviour.Popi_popi => 2, StackBehaviour.Popi_popi8 => 2, StackBehaviour.Popi_popi_popi => 3, StackBehaviour.Popi_popr4 => 2, StackBehaviour.Popi_popr8 => 2, StackBehaviour.Popref => 1, StackBehaviour.Popref_pop1 => 2, StackBehaviour.Popref_popi => 2, StackBehaviour.Popref_popi_popi => 3, StackBehaviour.Popref_popi_popi8 => 3, StackBehaviour.Popref_popi_popr4 => 3, StackBehaviour.Popref_popi_popr8 => 3, StackBehaviour.Popref_popi_popref => 3, StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"), StackBehaviour.Popref_popi_pop1 => 3, _ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), }; if (1 == 0) { } return result; } public static int PushCount(this CodeInstruction instruction) { if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) { MethodInfo methodInfo = (MethodInfo)instruction.operand; if (methodInfo.ReturnType == typeof(void)) { return 0; } return 1; } StackBehaviour stackBehaviourPush = instruction.opcode.StackBehaviourPush; if (1 == 0) { } int result = stackBehaviourPush switch { StackBehaviour.Push0 => 0, StackBehaviour.Push1 => 1, StackBehaviour.Push1_push1 => 2, StackBehaviour.Pushi => 1, StackBehaviour.Pushi8 => 1, StackBehaviour.Pushr4 => 1, StackBehaviour.Pushr8 => 1, StackBehaviour.Pushref => 1, StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"), _ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), }; if (1 == 0) { } return result; } public static int? GetLdargIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldarg_0) { return 0; } if (opcode == OpCodes.Ldarg_1) { return 1; } if (opcode == OpCodes.Ldarg_2) { return 2; } if (opcode == OpCodes.Ldarg_3) { return 3; } if (opcode == OpCodes.Ldarg || opcode == OpCodes.Ldarg_S) { return instruction.operand as int?; } return null; } public static int? GetLdlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return 0; } if (opcode == OpCodes.Ldloc_1) { return 1; } if (opcode == OpCodes.Ldloc_2) { return 2; } if (opcode == OpCodes.Ldloc_3) { return 3; } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static int? GetStlocIndex(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return 0; } if (opcode == OpCodes.Stloc_1) { return 1; } if (opcode == OpCodes.Stloc_2) { return 2; } if (opcode == OpCodes.Stloc_3) { return 3; } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return (instruction.operand as LocalBuilder)?.LocalIndex; } return null; } public static CodeInstruction LdlocToStloc(this CodeInstruction instruction) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldloc_0) { return new CodeInstruction(OpCodes.Stloc_0, (object)null); } if (opcode == OpCodes.Ldloc_1) { return new CodeInstruction(OpCodes.Stloc_1, (object)null); } if (opcode == OpCodes.Ldloc_2) { return new CodeInstruction(OpCodes.Stloc_2, (object)null); } if (opcode == OpCodes.Ldloc_3) { return new CodeInstruction(OpCodes.Stloc_3, (object)null); } if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S) { return new CodeInstruction(OpCodes.Stloc, instruction.operand); } return null; } public static CodeInstruction StlocToLdloc(this CodeInstruction instruction) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown OpCode opcode = instruction.opcode; if (opcode == OpCodes.Stloc_0) { return new CodeInstruction(OpCodes.Ldloc_0, (object)null); } if (opcode == OpCodes.Stloc_1) { return new CodeInstruction(OpCodes.Ldloc_1, (object)null); } if (opcode == OpCodes.Stloc_2) { return new CodeInstruction(OpCodes.Ldloc_2, (object)null); } if (opcode == OpCodes.Stloc_3) { return new CodeInstruction(OpCodes.Ldloc_3, (object)null); } if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S) { return new CodeInstruction(OpCodes.Ldloc, instruction.operand); } return null; } public static int? GetLdcI32(this CodeInstruction instruction) { OpCode opcode = instruction.opcode; if (opcode == OpCodes.Ldc_I4_M1) { return -1; } if (opcode == OpCodes.Ldc_I4_0) { return 0; } if (opcode == OpCodes.Ldc_I4_1) { return 1; } if (opcode == OpCodes.Ldc_I4_2) { return 2; } if (opcode == OpCodes.Ldc_I4_3) { return 3; } if (opcode == OpCodes.Ldc_I4_4) { return 4; } if (opcode == OpCodes.Ldc_I4_5) { return 5; } if (opcode == OpCodes.Ldc_I4_6) { return 6; } if (opcode == OpCodes.Ldc_I4_7) { return 7; } if (opcode == OpCodes.Ldc_I4_8) { return 8; } if (opcode == OpCodes.Ldc_I4_S) { return instruction.operand as sbyte?; } if (opcode == OpCodes.Ldc_I4) { return instruction.operand as int?; } return null; } } } namespace UnityMeshSimplifier { [Serializable] [StructLayout(LayoutKind.Auto)] public struct BlendShape { public string ShapeName; public BlendShapeFrame[] Frames; public BlendShape(string shapeName, BlendShapeFrame[] frames) { ShapeName = shapeName; Frames = frames; } } [Serializable] [StructLayout(LayoutKind.Auto)] public struct BlendShapeFrame { public float FrameWeight; public Vector3[] DeltaVertices; public Vector3[] DeltaNormals; public Vector3[] DeltaTangents; public BlendShapeFrame(float frameWeight, Vector3[] deltaVertices, Vector3[] deltaNormals, Vector3[] deltaTangents) { FrameWeight = frameWeight; DeltaVertices = deltaVertices; DeltaNormals = deltaNormals; DeltaTangents = deltaTangents; } } [AddComponentMenu("")] internal class LODBackupComponent : MonoBehaviour { [SerializeField] private Renderer[] originalRenderers = null; public Renderer[] OriginalRenderers { get { return originalRenderers; } set { originalRenderers = value; } } } [AddComponentMenu("Rendering/LOD Generator Helper")] public sealed class LODGeneratorHelper : MonoBehaviour { [SerializeField] [Tooltip("The fade mode used by the created LOD group.")] private LODFadeMode fadeMode = (LODFadeMode)0; [SerializeField] [Tooltip("If the cross-fading should be animated by time.")] private bool animateCrossFading = false; [SerializeField] [Tooltip("If the renderers under this game object and any children should be automatically collected.")] private bool autoCollectRenderers = true; [SerializeField] [Tooltip("The simplification options.")] private SimplificationOptions simplificationOptions = SimplificationOptions.Default; [SerializeField] [Tooltip("The path within the assets directory to save the generated assets. Leave this empty to use the default path.")] private string saveAssetsPath = string.Empty; [SerializeField] [Tooltip("The LOD levels.")] private LODLevel[] levels = null; [SerializeField] private bool isGenerated = false; public LODFadeMode FadeMode { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return fadeMode; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) fadeMode = value; } } public bool AnimateCrossFading { get { return animateCrossFading; } set { animateCrossFading = value; } } public bool AutoCollectRenderers { get { return autoCollectRenderers; } set { autoCollectRenderers = value; } } public SimplificationOptions SimplificationOptions { get { return simplificationOptions; } set { simplificationOptions = value; } } public string SaveAssetsPath { get { return saveAssetsPath; } set { saveAssetsPath = value; } } public LODLevel[] Levels { get { return levels; } set { levels = value; } } public bool IsGenerated => isGenerated; private void Reset() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) fadeMode = (LODFadeMode)0; animateCrossFading = false; autoCollectRenderers = true; simplificationOptions = SimplificationOptions.Default; levels = new LODLevel[3] { new LODLevel(0.5f, 1f) { CombineMeshes = false, CombineSubMeshes = false, SkinQuality = (SkinQuality)0, ShadowCastingMode = (ShadowCastingMode)1, ReceiveShadows = true, SkinnedMotionVectors = true, LightProbeUsage = (LightProbeUsage)1, ReflectionProbeUsage = (ReflectionProbeUsage)1 }, new LODLevel(0.17f, 0.65f) { CombineMeshes = true, CombineSubMeshes = false, SkinQuality = (SkinQuality)0, ShadowCastingMode = (ShadowCastingMode)1, ReceiveShadows = true, SkinnedMotionVectors = true, LightProbeUsage = (LightProbeUsage)1, ReflectionProbeUsage = (ReflectionProbeUsage)3 }, new LODLevel(0.02f, 0.4225f) { CombineMeshes = true, CombineSubMeshes = true, SkinQuality = (SkinQuality)2, ShadowCastingMode = (ShadowCastingMode)0, ReceiveShadows = false, SkinnedMotionVectors = false, LightProbeUsage = (LightProbeUsage)0, ReflectionProbeUsage = (ReflectionProbeUsage)0 } }; } } public sealed class ValidateSimplificationOptionsException : Exception { private readonly string propertyName; public string PropertyName => propertyName; public override string Message => base.Message + Environment.NewLine + "Property name: " + propertyName; public ValidateSimplificationOptionsException(string propertyName, string message) : base(message) { this.propertyName = propertyName; } public ValidateSimplificationOptionsException(string propertyName, string message, Exception innerException) : base(message, innerException) { this.propertyName = propertyName; } } public static class LODGenerator { private struct RendererInfo { public string name; public bool isStatic; public bool isNewMesh; public Transform transform; public Mesh mesh; public Material[] materials; public Transform rootBone; public Transform[] bones; } public static readonly string LODParentGameObjectName = "_UMS_LODs_"; public static readonly string LODAssetDefaultParentPath = "Assets/UMS_LODs/"; public static readonly string AssetsRootPath = "Assets/"; public static readonly string LODAssetUserData = "UnityMeshSimplifierLODAsset"; public static LODGroup GenerateLODs(LODGeneratorHelper generatorHelper) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)generatorHelper == (Object)null) { throw new ArgumentNullException("generatorHelper"); } GameObject gameObject = ((Component)generatorHelper).gameObject; LODLevel[] levels = generatorHelper.Levels; bool autoCollectRenderers = generatorHelper.AutoCollectRenderers; SimplificationOptions simplificationOptions = generatorHelper.SimplificationOptions; string saveAssetsPath = generatorHelper.SaveAssetsPath; LODGroup val = GenerateLODs(gameObject, levels, autoCollectRenderers, simplificationOptions, saveAssetsPath); if ((Object)(object)val == (Object)null) { return null; } val.animateCrossFading = generatorHelper.AnimateCrossFading; val.fadeMode = generatorHelper.FadeMode; return val; } public static LODGroup GenerateLODs(GameObject gameObject, LODLevel[] levels, bool autoCollectRenderers, SimplificationOptions simplificationOptions, Transform root = null) { return GenerateLODs(gameObject, levels, autoCollectRenderers, simplificationOptions, null, root); } public static LODGroup GenerateLODs(GameObject gameObject, LODLevel[] levels, bool autoCollectRenderers, SimplificationOptions simplificationOptions, string saveAssetsPath, Transform root = null) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gameObject == (Object)null) { throw new ArgumentNullException("gameObject"); } if (levels == null) { throw new ArgumentNullException("levels"); } Transform val = gameObject.transform; if ((Object)(object)root != (Object)null) { val = root; } Transform val2 = val.Find(LODParentGameObjectName); if ((Object)(object)val2 != (Object)null) { throw new InvalidOperationException("The game object already appears to have LODs. Please remove them first."); } LODGroup component = gameObject.GetComponent<LODGroup>(); if ((Object)(object)component != (Object)null) { throw new InvalidOperationException("The game object already appears to have a LOD Group. Please remove it first."); } MeshSimplifier.ValidateOptions(simplificationOptions); saveAssetsPath = ValidateSaveAssetsPath(saveAssetsPath); GameObject val3 = new GameObject(LODParentGameObjectName); Transform transform = val3.transform; ParentAndResetTransform(transform, val); LODGroup val4 = gameObject.AddComponent<LODGroup>(); Renderer[] array = null; if (autoCollectRenderers) { array = GetChildRenderersForLOD(gameObject); } List<Renderer> list = new List<Renderer>((array != null) ? array.Length : 10); LOD[] array2 = (LOD[])(object)new LOD[levels.Length]; for (int i = 0; i < levels.Length; i++) { LODLevel level = levels[i]; GameObject val5 = new GameObject($"Level{i:00}"); Transform transform2 = val5.transform; ParentAndResetTransform(transform2, transform); Renderer[] array3 = array ?? level.Renderers; List<Renderer> list2 = new List<Renderer>((array3 != null) ? array3.Length : 0); if (level.Quality == 1f) { array2[i] = new LOD(level.ScreenRelativeTransitionHeight, array3); continue; } if (array3 != null && array3.Length != 0) { MeshRenderer[] renderers = (from renderer in array3 let meshFilter = ((Component)renderer).GetComponent<MeshFilter>() where renderer.enabled && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)null && (Object)(object)meshFilter != (Object)null && (Object)(object)meshFilter.sharedMesh != (Object)null select <>h__TransparentIdentifier0).Select(<>h__TransparentIdentifier0 => { Renderer renderer4 = <>h__TransparentIdentifier0.renderer; return (MeshRenderer)(object)((renderer4 is MeshRenderer) ? renderer4 : null); }).ToArray(); SkinnedMeshRenderer[] renderers2 = (from renderer in array3 where renderer.enabled && (Object)(object)((renderer is SkinnedMeshRenderer) ? renderer : null) != (Object)null && (Object)(object)((SkinnedMeshRenderer)((renderer is SkinnedMeshRenderer) ? renderer : null)).sharedMesh != (Object)null select (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null)).ToArray(); RendererInfo[] array4 = null; RendererInfo[] array5 = null; if (level.CombineMeshes) { array4 = CombineStaticMeshes(val, i, renderers); array5 = CombineSkinnedMeshes(val, i, renderers2); } else { array4 = GetStaticRenderers(renderers); array5 = GetSkinnedRenderers(renderers2); } if (array4 != null) { for (int j = 0; j < array4.Length; j++) { RendererInfo renderer2 = array4[j]; Renderer item = CreateLevelRenderer(gameObject, i, in level, transform2, j, in renderer2, in simplificationOptions, saveAssetsPath); list2.Add(item); } } if (array5 != null) { for (int k = 0; k < array5.Length; k++) { RendererInfo renderer3 = array5[k]; Renderer item2 = CreateLevelRenderer(gameObject, i, in level, transform2, k, in renderer3, in simplificationOptions, saveAssetsPath); list2.Add(item2); } } Renderer[] array6 = array3; foreach (Renderer item3 in array6) { if (!list.Contains(item3)) { list.Add(item3); } } } array2[i] = new LOD(level.ScreenRelativeTransitionHeight, list2.ToArray()); } CreateBackup(gameObject, list.ToArray()); val4.animateCrossFading = false; val4.SetLODs(array2); return val4; } public static bool DestroyLODs(LODGeneratorHelper generatorHelper) { if ((Object)(object)generatorHelper == (Object)null) { throw new ArgumentNullException("generatorHelper"); } return DestroyLODs(((Component)generatorHelper).gameObject); } public static bool DestroyLODs(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { throw new ArgumentNullException("gameObject"); } RestoreBackup(gameObject); Transform transform = gameObject.transform; Transform val = transform.Find(LODParentGameObjectName); if ((Object)(object)val == (Object)null) { return false; } DestroyObject((Object)(object)((Component)val).gameObject); LODGroup component = gameObject.GetComponent<LODGroup>(); if ((Object)(object)component != (Object)null) { DestroyObject((Object)(object)component); } return true; } private static RendererInfo[] GetStaticRenderers(MeshRenderer[] renderers) { List<RendererInfo> list = new List<RendererInfo>(renderers.Length); foreach (MeshRenderer val in renderers) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if ((Object)(object)component == (Object)null) { Debug.LogWarning((object)"A renderer was missing a mesh filter and was ignored.", (Object)(object)val); continue; } Mesh sharedMesh = component.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { Debug.LogWarning((object)"A renderer was missing a mesh and was ignored.", (Object)(object)val); continue; } list.Add(new RendererInfo { name = ((Object)val).name, isStatic = true, isNewMesh = false, transform = ((Component)val).transform, mesh = sharedMesh, materials = ((Renderer)val).sharedMaterials }); } return list.ToArray(); } private static RendererInfo[] GetSkinnedRenderers(SkinnedMeshRenderer[] renderers) { List<RendererInfo> list = new List<RendererInfo>(renderers.Length); foreach (SkinnedMeshRenderer val in renderers) { Mesh sharedMesh = val.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { Debug.LogWarning((object)"A renderer was missing a mesh and was ignored.", (Object)(object)val); continue; } list.Add(new RendererInfo { name = ((Object)val).name, isStatic = false, isNewMesh = false, transform = ((Component)val).transform, mesh = sharedMesh, materials = ((Renderer)val).sharedMaterials, rootBone = val.rootBone, bones = val.bones }); } return list.ToArray(); } private static RendererInfo[] CombineStaticMeshes(Transform transform, int levelIndex, MeshRenderer[] renderers) { if (renderers.Length == 0) { return null; } List<RendererInfo> list = new List<RendererInfo>(renderers.Length); Material[] resultMaterials; Mesh val = MeshCombiner.CombineMeshes(transform, renderers, out resultMaterials); ((Object)val).name = $"{((Object)transform).name}_static{levelIndex:00}"; string name = $"{((Object)transform).name}_combined_static"; list.Add(new RendererInfo { name = name, isStatic = true, isNewMesh = true, transform = null, mesh = val, materials = resultMaterials, rootBone = null, bones = null }); return list.ToArray(); } private static RendererInfo[] CombineSkinnedMeshes(Transform transform, int levelIndex, SkinnedMeshRenderer[] renderers) { if (renderers.Length == 0) { return null; } List<RendererInfo> list = new List<RendererInfo>(renderers.Length); IEnumerable<SkinnedMeshRenderer> enumerable = renderers.Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer.sharedMesh != (Object)null && renderer.sharedMesh.blendShapeCount > 0); IEnumerable<SkinnedMeshRenderer> enumerable2 = renderers.Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer.sharedMesh == (Object)null); SkinnedMeshRenderer[] array = renderers.Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer.sharedMesh != (Object)null && renderer.sharedMesh.blendShapeCount == 0).ToArray(); foreach (SkinnedMeshRenderer item in enumerable2) { Debug.LogWarning((object)"A renderer was missing a mesh and was ignored.", (Object)(object)item); } foreach (SkinnedMeshRenderer item2 in enumerable) { list.Add(new RendererInfo { name = ((Object)item2).name, isStatic = false, isNewMesh = false, transform = ((Component)item2).transform, mesh = item2.sharedMesh, materials = ((Renderer)item2).sharedMaterials, rootBone = item2.rootBone, bones = item2.bones }); } if (array.Length != 0) { Material[] resultMaterials; Transform[] resultBones; Mesh val = MeshCombiner.CombineMeshes(transform, array, out resultMaterials, out resultBones); ((Object)val).name = $"{((Object)transform).name}_skinned{levelIndex:00}"; Transform rootBone = FindBestRootBone(transform, array); string name = $"{((Object)transform).name}_combined_skinned"; list.Add(new RendererInfo { name = name, isStatic = false, isNewMesh = false, transform = null, mesh = val, materials = resultMaterials, rootBone = rootBone, bones = resultBones }); } return list.ToArray(); } private static void ParentAndResetTransform(Transform transform, Transform parentTransform) { //IL_000a: 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_0022: Unknown result type (might be due to invalid IL or missing references) transform.SetParent(parentTransform); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; } private static void ParentAndOffsetTransform(Transform transform, Transform parentTransform, Transform originalTransform) { //IL_0003: 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_001d: Unknown result type (might be due to invalid IL or missing references) transform.position = originalTransform.position; transform.rotation = originalTransform.rotation; transform.localScale = originalTransform.lossyScale; transform.SetParent(parentTransform, true); } private static Renderer CreateLevelRenderer(GameObject gameObject, int levelIndex, in LODLevel level, Transform levelTransform, int rendererIndex, in RendererInfo renderer, in SimplificationOptions simplificationOptions, string saveAssetsPath) { Mesh val = renderer.mesh; if (level.Quality < 1f && Config.generateLODMeshes.Value) { MeshInfo meshInfo = new MeshInfo(val); meshInfo.name = ((Object)val).name + "LOD" + levelIndex; if (MeshService.lodMeshDict.TryGetValue(meshInfo, out var value)) { val = value; } else { val = SimplifyMesh(val, level.Quality, in simplificationOptions); ((Object)val).name = ((Object)val).name + "LOD" + levelIndex; val.UploadMeshData(true); MeshService.lodMeshDict.Add(meshInfo, val); } if (renderer.isNewMesh) { DestroyObject((Object)(object)renderer.mesh); } } if (renderer.isStatic) { string name = $"{rendererIndex:000}_static_{renderer.name}"; return (Renderer)(object)CreateStaticLevelRenderer(name, levelTransform, renderer.transform, val, renderer.materials, in level); } string name2 = $"{rendererIndex:000}_skinned_{renderer.name}"; return (Renderer)(object)CreateSkinnedLevelRenderer(name2, levelTransform, renderer.transform, val, renderer.materials, renderer.rootBone, renderer.bones, in level); } private static MeshRenderer CreateStaticLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, in LODLevel level) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[2] { typeof(MeshFilter), typeof(MeshRenderer) }); Transform transform = val.transform; if ((Object)(object)originalTransform != (Object)null) { ParentAndOffsetTransform(transform, parentTransform, originalTransform); } else { ParentAndResetTransform(transform, parentTransform); } MeshFilter component = val.GetComponent<MeshFilter>(); component.sharedMesh = mesh; MeshRenderer component2 = val.GetComponent<MeshRenderer>(); ((Renderer)component2).sharedMaterials = materials; SetupLevelRenderer((Renderer)(object)component2, in level); return component2; } private static SkinnedMeshRenderer CreateSkinnedLevelRenderer(string name, Transform parentTransform, Transform originalTransform, Mesh mesh, Material[] materials, Transform rootBone, Transform[] bones, in LODLevel level) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(SkinnedMeshRenderer) }); Transform transform = val.transform; if ((Object)(object)originalTransform != (Object)null) { ParentAndOffsetTransform(transform, parentTransform, originalTransform); } else { ParentAndResetTransform(transform, parentTransform); } SkinnedMeshRenderer component = val.GetComponent<SkinnedMeshRenderer>(); component.sharedMesh = mesh; ((Renderer)component).sharedMaterials = materials; component.rootBone = rootBone; component.bones = bones; SetupLevelRenderer((Renderer)(object)component, in level); return component; } private static Transform FindBestRootBone(Transform transform, SkinnedMeshRenderer[] skinnedMeshRenderers) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) if (skinnedMeshRenderers == null || skinnedMeshRenderers.Length == 0) { return null; } Transform result = null; float num = float.MaxValue; for (int i = 0; i < skinnedMeshRenderers.Length; i++) { if (!((Object)(object)skinnedMeshRenderers[i] == (Object)null) && !((Object)(object)skinnedMeshRenderers[i].rootBone == (Object)null)) { Transform rootBone = skinnedMeshRenderers[i].rootBone; Vector3 val = rootBone.position - transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { result = rootBone; num = sqrMagnitude; } } } return result; } private static void SetupLevelRenderer(Renderer renderer, in LODLevel level) { //IL_000b: 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_004a: 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_0087: Unknown result type (might be due to invalid IL or missing references) renderer.shadowCastingMode = level.ShadowCastingMode; renderer.receiveShadows = level.ReceiveShadows; renderer.motionVectorGenerationMode = level.MotionVectorGenerationMode; renderer.lightProbeUsage = level.LightProbeUsage; renderer.reflectionProbeUsage = level.ReflectionProbeUsage; SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if ((Object)(object)val != (Object)null) { val.quality = level.SkinQuality; val.skinnedMotionVectors = level.SkinnedMotionVectors; } } private static Renderer[] GetChildRenderersForLOD(GameObject gameObject) { List<Renderer> list = new List<Renderer>(); CollectChildRenderersForLOD(gameObject.transform, list); return list.ToArray(); } private static void CollectChildRenderersForLOD(Transform transform, List<Renderer> resultRenderers) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) Renderer[] components = ((Component)transform).GetComponents<Renderer>(); components = components.Where((Renderer r) => !(r is SkinnedMeshRenderer)).ToArray(); components = components.Where((Renderer r) => r.enabled).ToArray(); resultRenderers.AddRange(components); int childCount = transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = transform.GetChild(i); if (((Component)child).gameObject.activeSelf && (LayerMask.op_Implicit(MeshService.LODlayers) & (1 << ((Component)child).gameObject.layer)) != 0 && !string.Equals(((Object)child).name, LODParentGameObjectName) && !((Object)(object)((Component)child).GetComponent<LODGroup>() != (Object)null) && !((Object)(object)((Component)child).GetComponent<LODGeneratorHelper>() != (Object)null)) { CollectChildRenderersForLOD(child, resultRenderers); } } } private static Mesh SimplifyMesh(Mesh mesh, float quality, in SimplificationOptions options) { MeshSimplifier meshSimplifier = new MeshSimplifier(); meshSimplifier.SimplificationOptions = options; meshSimplifier.Initialize(mesh); meshSimplifier.SimplifyMesh(quality); Mesh val = meshSimplifier.ToMesh(); val.bindposes = mesh.bindposes; return val; } private static void DestroyObject(Object obj) { if (obj == (Object)null) { throw new ArgumentNullException("obj"); } Object.Destroy(obj); } private static void CreateBackup(GameObject gameObject, Renderer[] originalRenderers) { LODBackupComponent lODBackupComponent = gameObject.AddComponent<LODBackupComponent>(); ((Object)lODBackupComponent).hideFlags = (HideFlags)2; lODBackupComponent.OriginalRenderers = originalRenderers; } private static void RestoreBackup(GameObject gameObject) { LODBackupComponent[] components = gameObject.GetComponents<LODBackupComponent>(); LODBackupComponent[] array = components; foreach (LODBackupComponent lODBackupComponent in array) { Renderer[] originalRenderers = lODBackupComponent.OriginalRenderers; if (originalRenderers != null) { Renderer[] array2 = originalRenderers; foreach (Renderer val in array2) { if ((Object)(object)val != (Object)null) { val.enabled = true; } } } DestroyObject((Object)(object)lODBackupComponent); } } private static string ValidateSaveAssetsPath(string saveAssetsPath) { if (string.IsNullOrEmpty(saveAssetsPath)) { return null; } Debug.LogWarning((object)"Unable to save assets when not running in the Unity Editor."); return null; } } [Serializable] public struct LODLevel { [SerializeField] [Range(0f, 1f)] [Tooltip("The screen relative height to use for the transition.")] private float screenRelativeTransitionHeight; [SerializeField] [Range(0f, 1f)] [Tooltip("The width of the cross-fade transition zone (proportion to the current LOD's whole length).")] private float fadeTransitionWidth; [SerializeField] [Range(0f, 1f)] [Tooltip("The desired quality for this level.")] private float quality; [SerializeField] [Tooltip("If all renderers and meshes under this level should be combined into one, where possible.")] private bool combineMeshes; [SerializeField] [Tooltip("If all sub-meshes should be combined into one, where possible.")] private bool combineSubMeshes; [SerializeField] [Tooltip("The renderers used in this level.")] private Renderer[] renderers; [SerializeField] [Tooltip("The skin quality to use for renderers on this level.")] private SkinQuality skinQuality; [SerializeField] [Tooltip("The shadow casting mode for renderers on this level.")] private ShadowCastingMode shadowCastingMode; [SerializeField] [Tooltip("If renderers on this level should receive shadows.")] private bool receiveShadows; [SerializeField] [Tooltip("The motion vector generation mode for renderers on this level.")] private MotionVectorGenerationMode motionVectorGenerationMode; [SerializeField] [Tooltip("If renderers on this level should use skinned motion vectors.")] private bool skinnedMotionVectors; [SerializeField] [Tooltip("The light probe usage for renderers on this level.")] private LightProbeUsage lightProbeUsage; [SerializeField] [Tooltip("The reflection probe usage for renderers on this level.")] private ReflectionProbeUsage reflectionProbeUsage; public float ScreenRelativeTransitionHeight { get { return screenRelativeTransitionHeight; } set { screenRelativeTransitionHeight = Mathf.Clamp01(value); } } public float FadeTransitionWidth { get { return fadeTransitionWidth; } set { fadeTransitionWidth = Mathf.Clamp01(value); } } public float Quality { get { return quality; } set { quality = Mathf.Clamp01(value); } } public bool CombineMeshes { get { return combineMeshes; } set { combineMeshes = value; } } public bool CombineSubMeshes { get { return combineSubMeshes; } set { combineSubMeshes = value; } } public Renderer[] Renderers { get { return renderers; } set { renderers = value; } } public SkinQuality SkinQuality { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return skinQuality; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) skinQuality = value; } } public ShadowCastingMode ShadowCastingMode { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return shadowCastingMode; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) shadowCastingMode = value; } } public bool ReceiveShadows { get { return receiveShadows; } set { receiveShadows = value; } } public MotionVectorGenerationMode MotionVectorGenerationMode { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return motionVectorGenerationMode; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) motionVectorGenerationMode = value; } } public bool SkinnedMotionVectors { get { return skinnedMotionVectors; } set { skinnedMotionVectors = value; } } public LightProbeUsage LightProbeUsage { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return lightProbeUsage; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) lightProbeUsage = value; } } public ReflectionProbeUsage ReflectionProbeUsage { get { //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return reflectionProbeUsage; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) reflectionProbeUsage = value; } } public LODLevel(float screenRelativeTransitionHeight, float quality) : this(screenRelativeTransitionHeight, 0f, quality, combineMeshes: false, combineSubMeshes: false, null) { } public LODLevel(float screenRelativeTransitionHeight, float fadeTransitionWidth, float quality, bool combineMeshes, bool combineSubMeshes) : this(screenRelativeTransitionHeight, fadeTransitionWidth, quality, combineMeshes, combineSubMeshes, null) { } public LODLevel(float screenRelativeTransitionHeight, float fadeTransitionWidth, float quality, bool combineMeshes, bool combineSubMeshes, Renderer[] renderers) { //IL_003a: 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) //IL_004f: 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_0064: Unknown result type (might be due to invalid IL or missing references) this.screenRelativeTransitionHeight = Mathf.Clamp01(screenRelativeTransitionHeight); this.fadeTransitionWidth = fadeTransitionWidth; this.quality = Mathf.Clamp01(quality); this.combineMeshes = combineMeshes; this.combineSubMeshes = combineSubMeshes; this.renderers = renderers; skinQuality = (SkinQuality)0; shadowCastingMode = (ShadowCastingMode)1; receiveShadows = true; motionVectorGenerationMode = (MotionVectorGenerationMode)1; skinnedMotionVectors = true; lightProbeUsage = (LightProbeUsage)1; reflectionProbeUsage = (ReflectionProbeUsage)1; } } public static class MathHelper { public const float PI = MathF.PI; public const double PId = Math.PI; public const float Deg2Rad = MathF.PI / 180f; public const double Deg2Radd = Math.PI / 180.0; public const float Rad2Deg = 180f / MathF.PI; public const double Rad2Degd = 180.0 / Math.PI; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Min(double val1, double val2, double val3) { return (!(val1 < val2)) ? ((val2 < val3) ? val2 : val3) : ((val1 < val3) ? val1 : val3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Clamp(double value, double min, double max) { return (!(value >= min)) ? min : ((value <= max) ? value : max); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double TriangleArea(ref Vector3d p0, ref Vector3d p1, ref Vector3d p2) { Vector3d from = p1 - p0; Vector3d to = p2 - p0; return from.Magnitude * (Math.Sin(Vector3d.Angle(ref from, ref to) * (Math.PI / 180.0)) * to.Magnitude) * 0.5; } } public struct SymmetricMatrix { public double m0; public double m1; public double m2; public double m3; public double m4; public double m5; public double m6; public double m7; public double m8; public double m9; public double this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return index switch { 0 => m0, 1 => m1, 2 => m2, 3 => m3, 4 => m4, 5 => m5, 6 => m6, 7 => m7, 8 => m8, 9 => m9, _ => throw new ArgumentOutOfRangeException("index"), }; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SymmetricMatrix(double c) { m0 = c; m1 = c; m2 = c; m3 = c; m4 = c; m5 = c; m6 = c; m7 = c; m8 = c; m9 = c; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SymmetricMatrix(double m0, double m1, double m2, double m3, double m4, double m5, double m6, double m7, double m8, double m9) { this.m0 = m0; this.m1 = m1; this.m2 = m2; this.m3 = m3; this.m4 = m4; this.m5 = m5; this.m6 = m6; this.m7 = m7; this.m8 = m8; this.m9 = m9; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SymmetricMatrix(double a, double b, double c, double d) { m0 = a * a; m1 = a * b; m2 = a * c; m3 = a * d; m4 = b * b; m5 = b * c; m6 = b * d; m7 = c * c; m8 = c * d; m9 = d * d; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SymmetricMatrix operator +(SymmetricMatrix a, SymmetricMatrix b) { return new SymmetricMatrix(a.m0 + b.m0, a.m1 + b.m1, a.m2 + b.m2, a.m3 + b.m3, a.m4 + b.m4, a.m5 + b.m5, a.m6 + b.m6, a.m7 + b.m7, a.m8 + b.m8, a.m9 + b.m9); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal double Determinant1() { return m0 * m4 * m7 + m2 * m1 * m5 + m1 * m5 * m2 - m2 * m4 * m2 - m0 * m5 * m5 - m1 * m1 * m7; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal double Determinant2() { return m1 * m5 * m8 + m3 * m4 * m7 + m2 * m6 * m5 - m3 * m5 * m5 - m1 * m6 * m7 - m2 * m4 * m8; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal double Determinant3() { return m0 * m5 * m8 + m3 * m1 * m7 + m2 * m6 * m2 - m3 * m5 * m2 - m0 * m6 * m7 - m2 * m1 * m8; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal double Determinant4() { return m0 * m4 * m8 + m3 * m1 * m5 + m1 * m6 * m2 - m3 * m4 * m2 - m0 * m6 * m5 - m1 * m1 * m8; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public double Determinant(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33) { return this[a11] * this[a22] * this[a33] + this[a13] * this[a21] * this[a32] + this[a12] * this[a23] * this[a31] - this[a13] * this[a22] * this[a31] - this[a11] * this[a23] * this[a32] - this[a12] * this[a21] * this[a33]; } } public struct Vector3d : IEquatable<Vector3d> { public static readonly Vector3d zero = new Vector3d(0.0, 0.0, 0.0); public const double Epsilon = double.Epsilon; public double x; public double y; public double z; public double Magnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Math.Sqrt(x * x + y * y + z * z); } } public double MagnitudeSqr { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return x * x + y * y + z * z; } } public Vector3d Normalized { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { Normalize(ref this, out var result); return result; } } public double this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return index switch { 0 => x, 1 => y, 2 => z, _ => throw new ArgumentOutOfRangeException("index", "Invalid Vector3d index!"), }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { switch (index) { case 0: x = value; break; case 1: y = value; break; case 2: z = value; break; default: throw new ArgumentOutOfRangeException("index", "Invalid Vector3d index!"); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector3d(double value) { x = value; y = value; z = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector3d(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector3d(Vector3 vector) { //IL_0002: 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_001c: Unknown result type (might be due to invalid IL or missing references) x = vector.x; y = vector.y; z = vector.z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator +(Vector3d a, Vector3d b) { return new Vector3d(a.x + b.x, a.y + b.y, a.z + b.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator -(Vector3d a, Vector3d b) { return new Vector3d(a.x - b.x, a.y - b.y, a.z - b.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator *(Vector3d a, double d) { return new Vector3d(a.x * d, a.y * d, a.z * d); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator *(double d, Vector3d a) { return new Vector3d(a.x * d, a.y * d, a.z * d); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator /(Vector3d a, double d) { return new Vector3d(a.x / d, a.y / d, a.z / d); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3d operator -(Vector3d a) { return new Vector3d(0.0 - a.x, 0.0 - a.y, 0.0 - a.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector3d lhs, Vector3d rhs) { return (lhs - rhs).MagnitudeSqr < double.Epsilon; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(Vector3d lhs, Vector3d rhs) { return (lhs - rhs).MagnitudeSqr >= double.Epsilon; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Vector3d(Vector3 v) { //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_000f: Unknown result type (might be due to invalid IL or missing references) return new Vector3d(v.x, v.y, v.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator Vector3(Vector3d v) { //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_001e: Unknown result type (might be due to invalid IL or missing references) return new Vector3((float)v.x, (float)v.y, (float)v.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Set(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scale(ref Vector3d scale) { x *= scale.x; y *= scale.y; z *= scale.z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Normalize() { double magnitude = Magnitude; if (magnitude > double.Epsilon) { x /= magnitude; y /= magnitude; z /= magnitude; } else { x = (y = (z = 0.0)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clamp(double min, double max) { if (x < min) { x = min; } else if (x > max) { x = max; } if (y < min) { y = min; } else if (y > max) { y = max; } if (z < min) { z = min; } else if (z > max) { z = max; } } public override int GetHashCode() { return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2); } public override bool Equals(object obj) { if (!(obj is Vector3d vector3d)) { return false; } return x == vector3d.x && y == vector3d.y && z == vector3d.z; } public bool Equals(Vector3d other) { return x == other.x && y == other.y && z == other.z; } public override string ToString() { return $"({x:F1}, {y:F1}, {z:F1})"; } public string ToString(string format) { return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Dot(ref Vector3d lhs, ref Vector3d rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Cross(ref Vector3d lhs, ref Vector3d rhs, out Vector3d result) { result = new Vector3d(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Angle(ref Vector3d from, ref Vector3d to) { Vector3d lhs = from.Normalized; Vector3d rhs = to.Normalized; return Math.Acos(MathHelper.Clamp(Dot(ref lhs, ref rhs), -1.0, 1.0)) * (180.0 / Math.PI); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Lerp(ref Vector3d a, ref Vector3d b, double t, out Vector3d result) { result = new Vector3d(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Scale(ref Vector3d a, ref Vector3d b, out Vector3d result) { result = new Vector3d(a.x * b.x, a.y * b.y, a.z * b.z); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Normalize(ref Vector3d value, out Vector3d result) { double magnitude = value.Magnitude; if (magnitude > double.Epsilon) { result = new Vector3d(value.x / magnitude, value.y / magnitude, value.z / magnitude); } else { result = zero; } } } public static class MeshCombiner { public static Mesh CombineMeshes(Transform rootTransform, MeshRenderer[] renderers, out Material[] resultMaterials) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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_0136: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rootTransform == (Object)null) { throw new ArgumentNullException("rootTransform"); } if (renderers == null) { throw new ArgumentNullException("renderers"); } Mesh[] array = (Mesh[])(object)new Mesh[renderers.Length]; Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[renderers.Length]; Material[][] array3 = new Material[renderers.Length][]; for (int i = 0; i < renderers.Length; i++) { MeshRenderer val = renderers[i]; if ((Object)(object)val == (Object)null) { throw new ArgumentException($"The renderer at index {i} is null.", "renderers"); } Transform transform = ((Component)val).transform; MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if ((Object)(object)component == (Object)null) { throw new ArgumentException($"The renderer at index {i} has no mesh filter.", "renderers"); } if ((Object)(object)component.sharedMesh == (Object)null) { throw new ArgumentException($"The mesh filter for renderer at index {i} has no mesh.", "renderers"); } if (!CanReadMesh(component.sharedMesh)) { array[i] = MeshService.GetReadableMesh(component.sharedMesh); } else { array[i] = component.sharedMesh; } array2[i] = rootTransform.worldToLocalMatrix * transform.localToWorldMatrix; array3[i] = ((Renderer)val).sharedMaterials; } return CombineMeshes(array, array2, array3, out resultMaterials); } public static Mesh CombineMeshes(Transform rootTransform, SkinnedMeshRenderer[] renderers, out Material[] resultMaterials, out Transform[] resultBones) { //IL_00fe: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rootTransform == (Object)null) { throw new ArgumentNullException("rootTransform"); } if (renderers == null) { throw new ArgumentNullException("renderers"); } Mesh[] array = (Mesh[])(object)new Mesh[renderers.Length]; Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[renderers.Length]; Material[][] array3 = new Material[renderers.Length][]; Transform[][] array4 = new Transform[renderers.Length][]; for (int i = 0; i < renderers.Length; i++) { SkinnedMeshRenderer val = renderers[i]; if ((Object)(object)val == (Object)null) { throw new ArgumentException($"The renderer at index {i} is null.", "renderers"); } if ((Object)(object)val.sharedMesh == (Object)null) { throw new ArgumentException($"The renderer at index {i} has no mesh.", "renderers"); } if (!CanReadMesh(val.sharedMesh)) { array[i] = MeshService.GetReadableMesh(val.sharedMesh); } else { array[i] = val.sharedMesh; } Transform transform = ((Component)val).transform; array2[i] = transform.worldToLocalMatrix * transform.localToWorldMatrix; array3[i] = ((Renderer)val).sharedMaterials; array4[i] = val.bones; } return CombineMeshes(array, array2, array3, array4, out resultMaterials, out resultBones); } public static Mesh CombineMeshes(Mesh[] meshes, Matrix4x4[] transforms, Material[][] materials, out Material[] resultMaterials) { if (meshes == null) { throw new ArgumentNullException("meshes"); } if (transforms == null) { throw new ArgumentNullException("transforms"); } if (materials == null) { throw new ArgumentNullException("materials"); } Transform[] resultBones; return CombineMeshes(meshes, transforms, materials, null, out resultMaterials, out resultBones); } public static Mesh CombineMeshes(Mesh[] meshes, Matrix4x4[] transforms, Material[][] materials, Transform[][] bones, out Material[] resultMaterials, out Transform[] resultBones) { //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) if (meshes == null) { throw new ArgumentNullException("meshes"); } if (transforms == null) { throw new ArgumentNullException("transforms"); } if (materials == null) { throw new ArgumentNullException("materials"); } if (transforms.Length != meshes.Length) { throw new ArgumentException("The array of transforms doesn't have the same length as the array of meshes.", "transforms"); } if (materials.Length != meshes.Length) { throw new ArgumentException("The array of materials doesn't have the same length as the array of meshes.", "materials"); } if (bones != null && bones.Length != meshes.Length) { throw new ArgumentException("The array of bones doesn't have the same length as the array of meshes.", "bones"); } int num = 0; int num2 = 0; for (int i = 0; i < meshes.Length; i++) { Mesh val = meshes[i]; if ((Object)(object)val == (Object)null || !CanReadMesh(val)) { continue; } Material[] array = materials[i]; if (array == null || array.Length != val.subMeshCount) { continue; } for (int j = 0; j < array.Length; j++) { if ((Object)(object)array[j] == (Object)null) { } } if (bones != null) { Transform[] array2 = bones[i]; if (array2 == null) { continue; } for (int k = 0; k < array2.Length; k++) { if ((Object)(object)array2[k] == (Object)null) { } } } num += val.vertexCount; num2 += val.subMeshCount; } List<Vector3> list = new List<Vector3>(num); List<int[]> list2 = new List<int[]>(num2); List<Vector3> dest = null; List<Vector4> dest2 = null; List<Color> dest3 = null; List<BoneWeight> dest4 = null; List<Vector4>[] array3 = new List<Vector4>[MeshUtils.UVChannelCount]; List<Matrix4x4> list3 = null; List<Transform> list4 = null; List<Material> list5 = new List<Material>(num2); Dictionary<Material, int> dictionary = new Dictionary<Material, int>(num2); int num3 = 0; for (int l = 0; l < meshes.Length; l++) { Mesh val2 = meshes[l]; Matrix4x4 transform = transforms[l]; Material[] array4 = materials[l]; Transform[] array5 = ((bones != null) ? bones[l] : null); int subMeshCount = val2.subMeshCount; int vertexCount = val2.vertexCount; Vector3[] vertices = val2.vertices; Vector3[] normals = val2.normals; Vector4[] tangents = val2.tangents; IList<Vector4>[] meshUVs = MeshUtils.GetMeshUVs(val2); Color[] colors = val2.colors; BoneWeight[] boneWeights = val2.boneWeights; Matrix4x4[] bindposes = val2.bindposes; if (array5 != null && boneWeights != null && boneWeights.Length != 0 && bindposes != null && bindposes.Length != 0 && array5.Length == bindposes.Length) { if (list3 == null) { list3 = new List<Matrix4x4>(bindposes); list4 = new List<Transform>(array5); } int[] array6 = new int[array5.Length]; for (int m = 0; m < array5.Length; m++) { int num4 = list4.IndexOf(array5[m]); if (num4 == -1 || bindposes[m] != list3[num4]) { num4 = list4.Count; list4.Add(array5[m]); list3.Add(bindposes[m]); } array6[m] = num4; } RemapBones(boneWeights, array6); } TransformVertices(vertices, ref transform); TransformNormals(normals, ref transform); TransformTangents(tangents, ref transform); CopyVertexPositions(list, vertices); CopyVertexAttributes(ref dest, normals, num3, vertexCount, num, new Vector3(1f, 0f, 0f)); CopyVertexAttributes(ref dest2, tangents, num3, vertexCount, num, new Vector4(0f, 0f, 1f, 1f)); CopyVertexAttributes(ref dest3, colors, num3, vertexCount, num, new Color(1f, 1f, 1f, 1f)); CopyVertexAttributes(ref dest4, boneWeights, num3, vertexCount, num, default(BoneWeight)); for (int n = 0; n < meshUVs.Length; n++) { CopyVertexAttributes(ref array3[n], meshUVs[n], num3, vertexCount, num, new Vector4(0f, 0f, 0f, 0f)); } for (int num5 = 0; num5 < subMeshCount; num5++) { Material val3 = array4[num5]; int[] triangles = val2.GetTriangles(num5, true); if (num3 > 0) { for (int num6 = 0; num6 < triangles.Length; num6++) { triangles[num6] += num3; } } if (dictionary.TryGetValue(val3, out var value)) { list2[value] = MergeArrays(list2[value], triangles); continue; } int count = list2.Count; dictionary.Add(val3, count); list5.Add(val3); list2.Add(triangles); } num3 += vertexCount; } Vector3[] vertices2 = list.ToArray(); int[][] indices = list2.ToArray(); Vector3[] normals2 = dest?.ToArray(); Vector4[] tangents2 = dest2?.ToArray(); Color[] colors2 = dest3?.ToArray(); BoneWeight[] boneWeights2 = dest4?.ToArray(); List<Vector4>[] uvs = array3.ToArray(); Matrix4x4[] bindposes2 = list3?.ToArray(); resultMaterials = list5.ToArray(); resultBones = list4?.ToArray(); return MeshUtils.CreateMesh(vertices2, indices, normals2, tangents2, colors2, boneWeights2, uvs, bindposes2, null); } private static void CopyVertexPositions(ICollection<Vector3> list, Vector3[] arr) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (arr != null && arr.Length != 0) { for (int i = 0; i < arr.Length; i++) { list.Add(arr[i]); } } } private static void CopyVertexAttributes<T>(ref List<T> dest, IEnumerable<T> src, int previousVertexCount, int meshVertexCount, int totalVertexCount, T defaultValue) { if (src == null || src.Count() == 0) { if (dest != null) { for (int i = 0; i < meshVertexCount; i++) { dest.Add(defaultValue); } } return; } if (dest == null) { dest = new List<T>(totalVertexCount); for (int j = 0; j < previousVertexCount; j++) { dest.Add(defaultValue); } } dest.AddRange(src); } private static T[] MergeArrays<T>(T[] arr1, T[] arr2) { T[] array = new T[arr1.Length + arr2.Length]; Array.Copy(arr1, 0, array, 0, arr1.Length); Array.Copy(arr2, 0, array, arr1.Length, arr2.Length); return array; } private static void TransformVertices(Vector3[] vertices, ref Matrix4x4 transform) { //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_0015: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < vertices.Length; i++) { vertices[i] = ((Matrix4x4)(ref transform)).MultiplyPoint3x4(vertices[i]); } } private static void TransformNormals(Vector3[] normals, ref Matrix4x4 transform) { //IL_0015: 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) if (normals != null) { for (int i = 0; i < normals.Length; i++) { normals[i] = ((Matrix4x4)(ref transform)).MultiplyVector(normals[i]); } } } private static void TransformTangents(Vector4[] tangents, ref Matrix4x4 transform) { //IL_0035: 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_003f: 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_0048: 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_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) if (tangents != null) { for (int i = 0; i < tangents.Length; i++) { Vector3 val = ((Matrix4x4)(ref transform)).MultiplyVector(new Vector3(tangents[i].x, tangents[i].y, tangents[i].z)); tangents[i] = new Vector4(val.x, val.y, val.z, tangents[i].w); } } } private static void RemapBones(BoneWeight[] boneWeights, int[] boneIndices) { for (int i = 0; i < boneWeights.Length; i++) { if (((BoneWeight)(ref boneWeights[i])).weight0 > 0f) { ((BoneWeight)(ref boneWeights[i])).boneIndex0 = boneIndices[((BoneWeight)(ref boneWeights[i])).boneIndex0]; } if (((BoneWeight)(ref boneWeights[i])).weight1 > 0f) { ((BoneWeight)(ref boneWeights[i])).boneIndex1 = boneIndices[((BoneWeight)(ref boneWeights[i])).boneIndex1]; } if (((BoneWeight)(ref boneWeights[i])).weight2 > 0f) { ((BoneWeight)(ref boneWeights[i])).boneIndex2 = boneIndices[((BoneWeight)(ref boneWeights[i])).boneIndex2]; } if (((BoneWeight)(ref boneWeights[i])).weight3 > 0f) { ((BoneWeight)(ref boneWeights[i])).boneIndex3 = boneIndices[((BoneWeight)(ref boneWeights[i])).boneIndex3]; } } } private static bool CanReadMesh(Mesh mesh) { return mesh.isReadable; } } public sealed class MeshSimplifier { private const int TriangleEdgeCount = 3; private const int TriangleVertexCount = 3; private const double DoubleEpsilon = 0.001; private const double DenomEpilson = 1E-08; private static readonly int UVChannelCount = MeshUtils.UVChannelCount; private SimplificationOptions simplificationOptions = SimplificationOptions.Default; private bool verbose = false; private int subMeshCount = 0; private int[] subMeshOffsets = null; private ResizableArray<Triangle> triangles = null; private ResizableArray<Vertex> vertices = null; private ResizableArray<Ref> refs = null; private ResizableArray<Vector3> vertNormals = null; private ResizableArray<Vector4> vertTangents = null; private UVChannels<Vector2> vertUV2D = null; private UVChannels<Vector3> vertUV3D = null; private UVChannels<Vector4> vertUV4D = null; private ResizableArray<Color> vertColors = null; private ResizableArray<BoneWeight> vertBoneWeights = null; private ResizableArray<BlendShapeContainer> blendShapes = null; private Matrix4x4[] bindposes = null; private readonly double[] errArr = new double[3]; private readonly int[] attributeIndexArr = new int[3]; private readonly HashSet<Triangle> triangleHashSet1 = new HashSet<Triangle>(); private readonly HashSet<Triangle> triangleHashSet2 = new HashSet<Triangle>(); public SimplificationOptions SimplificationOptions { get { return simplificationOptions; } set { ValidateOptions(value); simplificationOptions = value; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public bool PreserveBorderEdges { get { return simplificationOptions.PreserveBorderEdges; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.PreserveBorderEdges = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public bool PreserveUVSeamEdges { get { return simplificationOptions.PreserveUVSeamEdges; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.PreserveUVSeamEdges = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public bool PreserveUVFoldoverEdges { get { return simplificationOptions.PreserveUVFoldoverEdges; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.PreserveUVFoldoverEdges = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public bool PreserveSurfaceCurvature { get { return simplificationOptions.PreserveSurfaceCurvature; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.PreserveSurfaceCurvature = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public bool EnableSmartLink { get { return simplificationOptions.EnableSmartLink; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.EnableSmartLink = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public int MaxIterationCount { get { return simplificationOptions.MaxIterationCount; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.MaxIterationCount = value; SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public double Agressiveness { get { return simplificationOptions.Agressiveness; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.Agressiveness = value; SimplificationOptions = simplificationOptions; } } public bool Verbose { get { return verbose; } set { verbose = value; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public double VertexLinkDistance { get { return simplificationOptions.VertexLinkDistance; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.VertexLinkDistance = ((value > double.Epsilon) ? value : double.Epsilon); SimplificationOptions = simplificationOptions; } } [Obsolete("Use MeshSimplifier.SimplificationOptions instead.", false)] public double VertexLinkDistanceSqr { get { return simplificationOptions.VertexLinkDistance * simplificationOptions.VertexLinkDistance; } set { SimplificationOptions simplificationOptions = this.simplificationOptions; simplificationOptions.VertexLinkDistance = Math.Sqrt(value); SimplificationOptions = simplificationOptions; } } public Vector3[] Vertices { get { //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) int length = vertices.Length; Vector3[] array = (Vector3[])(object)new Vector3[length]; Vertex[] data = vertices.Data; for (int i = 0; i < length; i++) { array[i] = (Vector3)data[i].p; } return array; } set { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (value == null) { throw new ArgumentNullException("value"); } bindposes = null; vertices.Resize(value.Length); Vertex[] data = vertices.Data; for (int i = 0; i < value.Length; i++) { data[i] = new Vertex(i, value[i]); } } } public int SubMeshCount => subMeshCount; public int BlendShapeCount => (blendShapes != null) ? blendShapes.Length : 0; public Vector3[] Normals { get { return (vertNormals != null) ? vertNormals.Data : null; } set { InitializeVertexAttribute(value, ref vertNormals, "normals"); } } public Vector4[] Tangents { get { return (vertTangents != null) ? vertTangents.Data : null; } set { InitializeVertexAttribute(value, ref vertTangents, "tangents"); } } public Vector2[] UV1 { get { return GetUVs2D(0); } set { SetUVs(0, value); } } public Vector2[] UV2 { get { return GetUVs2D(1); } set { SetUVs(1, value); } } public Vector2[] UV3 { get { return GetUVs2D(2); } set { SetUVs(2, value); } } public Vector2[] UV4 { get { return GetUVs2D(3); } set { SetUVs(3, value); } } public Color[] Colors { get { return (vertColors != null) ? vertColors.Data : null; } set { InitializeVertexAttribute(value, ref vertColors, "colors"); } } public BoneWeight[] BoneWeights { get { return (vertBoneWeights != null) ? vertBoneWeights.Data : null; } set { InitializeVertexAttribute(value, ref vertBoneWeights, "boneWeights"); } } public MeshSimplifier() { triangles = new ResizableArray<Triangle>(0); vertices = new ResizableArray<Vertex>(0); refs = new ResizableArray<Ref>(0); } public MeshSimplifier(Mesh mesh) : this() { if ((Object)(object)mesh != (Object)null) { Initialize(mesh); } } private void InitializeVertexAttribute<T>(T[] attributeValues, ref ResizableArray<T> attributeArray, string attributeName) { if (attributeValues != null && attributeValues.Length == vertices.Length) { if (attributeArray == null) { attributeArray = new ResizableArray<T>(attributeValues.Length, attributeValues.Length); } else { attributeArray.Resize(attributeValues.Length); } T[] data = attributeArray.Data; Array.Copy(attributeValues, 0, data, 0, attributeValues.Length); return; } if (attributeValues != null && attributeValues.Length != 0) { Debug.LogErrorFormat("Failed to set vertex attribute '{0}' with {1} length of array, when {2} was needed.", new object[3] { attributeName, attributeValues.Length, vertices.Length }); } attributeArray = null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static double VertexError(ref SymmetricMatrix q, double x, double y, double z) { return q.m0 * x * x + 2.0 * q.m1 * x * y + 2.0 * q.m2 * x * z + 2.0 * q.m3 * x + q.m4 * y * y + 2.0 * q.m5 * y * z + 2.0 * q.m6 * y + q.m7 * z * z + 2.0 * q.m8 * z + q.m9; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private double CurvatureError(ref Vertex vert0, ref Vertex vert1) { double magnitude = (vert0.p - vert1.p).Magnitude; HashSet<Triangle> hashSet = triangleHashSet1; hashSet.Clear(); GetTrianglesContainingVertex(ref vert0, hashSet); GetTrianglesContainingVertex(ref vert1, hashSet); HashSet<Triangle> hashSet2 = triangleHashSet2; hashSet2.Clear(); GetTrianglesContainingBothVertices(ref vert0, ref vert1, hashSet2); double num = 0.0; foreach (Triangle item in hashSet) { double num2 = 0.0; Vector3d lhs = item.n; foreach (Triangle item2 in hashSet2) { Vector3d rhs = item2.n; double num3 = Vector3d.Dot(ref lhs, ref rhs); if (num3 > num2) { num2 = num3; } } if (num2 > num) { num = num2; } } return magnitude * num; } private double CalculateError(ref Vertex vert0, ref Vertex vert1, out Vector3d result) { SymmetricMatrix q = vert0.q + vert1.q; bool flag = vert0.borderEdge && vert1.borderEdge; double num = 0.0; double num2 = q.Determinant1(); if (num2 != 0.0 && !flag) { result = new Vector3d(-1.0 / num2 * q.Determinant2(), 1.0 / num2 * q.Determinant3(), -1.0 / num2 * q.Determinant4()); double num3 = 0.0; if (simplificationOptions.PreserveSurfaceCurvature) { num3 = CurvatureError(ref vert0, ref vert1); } num = VertexError(ref q, result.x, result.y, r