Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalSponge v1.4.3
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.service; 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.60+8e73371a76f6e40597f30002ede5013018327d8b")] [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, result.z) + num3; } else { Vector3d p =