using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FMOD; using FMODUnity; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Localization; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DrivingRangeTheater")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DrivingRangeTheater")] [assembly: AssemblyTitle("DrivingRangeTheater")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DrivingRangeTheater { public class DrivingRangeBackCameraButton : MonoBehaviour, IInteractable { public Entity AsEntity { get; private set; } public bool IsInteractionEnabled => DrivingRangeStaticCameraManager.IsCycleNextButtonEnabled; public LocalizedString InteractString => UI.SPECTATOR_Prompt_Previous_Ref; public void LocalPlayerInteract() { if (NetworkClient.active) { TheaterCycleMsg theaterCycleMsg = default(TheaterCycleMsg); theaterCycleMsg.direction = -1; NetworkClient.Send(theaterCycleMsg, 0); } } private void Awake() { AsEntity = ((Component)this).GetComponent(); } } internal static class BackButtonInstaller { private const float OffsetMeters = 0.2508f; private static bool _installed; public static void ResetForNewScene() { _installed = false; } public static void TryInstall(DrivingRangeStaticCameraManager mgr) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) if (_installed) { return; } DrivingRangeNextCameraButton val = Traverse.Create((object)mgr).Field("nextCameraButton").Value; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType(); } if ((Object)(object)val == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"Back button: no DrivingRangeNextCameraButton found yet — will retry."); } return; } if ((Object)(object)((Component)val).transform.parent != (Object)null && (Object)(object)((Component)val).transform.parent.Find("SBG-BackCameraButton") != (Object)null) { _installed = true; return; } GameObject val2 = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = "SBG-BackCameraButton"; Vector3 val3 = Vector3.right * 0.2508f; Vector3 val4 = ((Component)val).transform.TransformVector(val3); val2.transform.localPosition = ((Component)val).transform.localPosition + val3; val2.transform.localRotation = ((Component)val).transform.localRotation; val2.transform.localScale = ((Component)val).transform.localScale; DrivingRangeNextCameraButton component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } val2.AddComponent(); Entity component2 = ((Component)val).GetComponent(); Entity component3 = val2.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null && (Object)(object)component2.TargetReticlePosition != (Object)null && (Object)(object)component3.TargetReticlePosition != (Object)null) { ((Component)component3.TargetReticlePosition).transform.position = ((Component)component2.TargetReticlePosition).transform.position + val4; } _installed = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"Back button installed at {val2.transform.position}."); } } } public struct TheaterCycleMsg : NetworkMessage { public int direction; } [BepInPlugin("cray.drivingrangetheater", "DrivingRangeTheater", "0.1.0")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(DrivingRangeStaticCameraManager), "OnStartServer")] internal static class Patch_Manager_OnStartServer { private static void Postfix() { NetworkServer.ReplaceHandler((Action)OnClientCycle, true); Log.LogInfo((object)"Registered TheaterCycleMsg server handler."); } } [HarmonyPatch(typeof(DrivingRangeStaticCameraManager), "ApplyCurrentCameraIndex")] internal static class Patch_Manager_ApplyCurrentCameraIndex { private static bool Prefix(DrivingRangeStaticCameraManager __instance) { Renderer value = Traverse.Create((object)__instance).Field("screenRenderer").Value; if ((Object)(object)value == (Object)null) { return true; } if ((Object)(object)TheaterController.Current == (Object)null) { ((Component)value).gameObject.AddComponent().Initialize(value, __instance); } if (VideoLibrary.Videos.Count == 0) { TheaterController.Current.ShowNoVideos(); return false; } TheaterController.Current.ApplyIndex(__instance.NetworkcurrentCameraIndex); BackButtonInstaller.TryInstall(__instance); return false; } } public const string ModGuid = "cray.drivingrangetheater"; public const string ModName = "DrivingRangeTheater"; public const string ModVersion = "0.1.0"; internal static ManualLogSource Log; internal static ConfigEntry VolumeConfig; internal static ConfigEntry OverscanCompensationConfig; internal static ConfigEntry ScreenResolutionConfig; private static float _lastServerCycleTime; private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; VolumeConfig = ((BaseUnityPlugin)this).Config.Bind("Theater", "Volume", 0.5f, new ConfigDescription("Client-local master volume for the driving-range theater (0.0 - 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); ScreenResolutionConfig = ((BaseUnityPlugin)this).Config.Bind("Theater", "ScreenResolution", 1024, new ConfigDescription("Client-local theater screen RT resolution. Accepted values: 1024, 1536, 2048.", (AcceptableValueBase)(object)new AcceptableValueList(new int[3] { 1024, 1536, 2048 }), Array.Empty())); OverscanCompensationConfig = ((BaseUnityPlugin)this).Config.Bind("Theater", "OverscanCompensation", 0f, new ConfigDescription("Shrinks the displayed video inside the theater screen RT to compensate for screen overscan/cropping (0.0 - 0.25).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.25f), Array.Empty())); VolumeConfig.SettingChanged += delegate { TheaterController.Current?.SetVolume(VolumeConfig.Value); }; ScreenResolutionConfig.SettingChanged += delegate { TheaterController.Current?.ApplyConfiguredScreenResolution(); }; OverscanCompensationConfig.SettingChanged += delegate { TheaterController.Current?.RefreshDisplayComposition(); }; PauseMenu.Paused += VolumeSliderUi.HandlePauseShown; PauseMenu.Unpaused += VolumeSliderUi.HandlePauseHidden; VideoLibrary.ScanAll(Paths.PluginPath, Log); new Harmony("cray.drivingrangetheater").PatchAll(); NetworkClient.OnConnectedEvent = (Action)Delegate.Combine(NetworkClient.OnConnectedEvent, new Action(RegisterClientHandlers)); Log.LogInfo((object)string.Format("{0} v{1} loaded ({2} video(s)).", "DrivingRangeTheater", "0.1.0", VideoLibrary.Videos.Count)); } internal static int GetConfiguredScreenResolution() { int num = ((ScreenResolutionConfig != null) ? ScreenResolutionConfig.Value : 1024); if (num != 1536 && num != 2048) { return 1024; } return num; } private static void RegisterClientHandlers() { } internal static void OnClientCycle(NetworkConnectionToClient conn, TheaterCycleMsg msg) { if (Time.realtimeSinceStartup - _lastServerCycleTime < 0.2f) { return; } _lastServerCycleTime = Time.realtimeSinceStartup; DrivingRangeStaticCameraManager instance = SingletonNetworkBehaviour.Instance; if (!((Object)(object)instance == (Object)null)) { int num = Mathf.Max(VideoLibrary.Videos.Count, 1); int num2 = ((msg.direction >= 0) ? 1 : (-1)); int num3 = instance.NetworkcurrentCameraIndex; if (num3 < 0) { num3 = 0; } int networkcurrentCameraIndex = ((num3 + num2) % num + num) % num; instance.NetworkcurrentCameraIndex = networkcurrentCameraIndex; } } } internal class TheaterController : MonoBehaviour { private struct ScreenTextureBinding { public string Name; public Texture Texture; public Vector2 Scale; public Vector2 Offset; } private sealed class Slot { public string Label; public VideoPlayer Player; public RenderTexture RenderTexture; public int VideoIndex = -1; public bool Prepared; } public static TheaterController Current; private Slot[] _slots; private int _activeSlot; private Renderer _screenRenderer; private Material _screenMaterial; private ScreenTextureBinding[] _screenBindings = Array.Empty(); private RenderTexture _screenRenderTexture; private TextMeshPro _statusText; private DrivingRangeStaticCameraManager _vanillaManager; private Sound[] _sounds; private Channel _activeChannel; private bool _activeChannelValid; private float _driftCheckTimer; private const float DriftCheckInterval = 2f; private const int DriftToleranceMs = 250; private Vector3 _lastAudioWorldPos; private const float AudioMinDistance = 6f; private const float AudioMaxDistance = 45f; private int _activeAudioIndex = -1; private string[] _screenTextureSlots = Array.Empty(); public void Initialize(Renderer screenRenderer, DrivingRangeStaticCameraManager vanillaMgr) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Invalid comparison between Unknown and I4 //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) Current = this; _screenRenderer = screenRenderer; _screenMaterial = screenRenderer.material; _vanillaManager = vanillaMgr; try { if (Traverse.Create((object)vanillaMgr).Field("cameras").GetValue() is DrivingRangeStaticCamera[] array && array.Length != 0) { object value = Traverse.Create((object)array[0]).Field("thisCamera").GetValue(); Camera val = (Camera)((value is Camera) ? value : null); if ((Object)(object)val != (Object)null && (Object)(object)val.targetTexture != (Object)null) { _screenRenderTexture = val.targetTexture; ApplyConfiguredScreenResolution(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Theater RT sized from vanilla camera: {((Texture)_screenRenderTexture).width}x{((Texture)_screenRenderTexture).height} ({((Object)_screenRenderTexture).name})"); } } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("RT size probe failed: " + ex.Message)); } } _slots = new Slot[3]; for (int i = 0; i < _slots.Length; i++) { _slots[i] = CreateSlot("SBG-TheaterSlot-" + i, 1920, 1080); } Shader shader = _screenMaterial.shader; int propertyCount = shader.GetPropertyCount(); List list = new List(); for (int j = 0; j < propertyCount; j++) { if ((int)shader.GetPropertyType(j) == 4) { string propertyName = shader.GetPropertyName(j); string text = propertyName.ToLowerInvariant(); if (text.Contains("maintex") || text.Contains("basemap") || text.Contains("emission")) { list.Add(propertyName); } } } if (list.Count == 0) { if (_screenMaterial.HasProperty("_MainTex")) { list.Add("_MainTex"); } if (_screenMaterial.HasProperty("_BaseMap")) { list.Add("_BaseMap"); } if (_screenMaterial.HasProperty("_EmissionMap")) { list.Add("_EmissionMap"); } } _screenTextureSlots = list.ToArray(); _screenBindings = new ScreenTextureBinding[_screenTextureSlots.Length]; for (int k = 0; k < _screenTextureSlots.Length; k++) { string text2 = _screenTextureSlots[k]; _screenBindings[k] = new ScreenTextureBinding { Name = text2, Texture = _screenMaterial.GetTexture(text2), Scale = _screenMaterial.GetTextureScale(text2), Offset = _screenMaterial.GetTextureOffset(text2) }; _screenMaterial.SetTextureScale(text2, Vector2.one); _screenMaterial.SetTextureOffset(text2, Vector2.zero); } if (_screenMaterial.HasProperty("_EmissionColor")) { _screenMaterial.SetColor("_EmissionColor", Color.white * 1.2f); } _screenMaterial.EnableKeyword("_EMISSION"); CreateStatusText(); _sounds = (Sound[])(object)new Sound[VideoLibrary.Entries.Count]; } private Slot CreateSlot(string label, int rtW, int rtH) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown RenderTexture val = new RenderTexture(rtW, rtH, 0, (RenderTextureFormat)0) { name = label + "-RT", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, useMipMap = false }; val.Create(); GameObject val2 = new GameObject(label); val2.transform.SetParent(((Component)this).transform, false); VideoPlayer val3 = val2.AddComponent(); val3.playOnAwake = false; val3.waitForFirstFrame = true; val3.isLooping = true; val3.renderMode = (VideoRenderMode)2; val3.targetTexture = val; val3.source = (VideoSource)1; val3.audioOutputMode = (VideoAudioOutputMode)0; val3.aspectRatio = (VideoAspectRatio)5; Slot slot = new Slot { Label = label, Player = val3, RenderTexture = val }; val3.errorReceived += (ErrorEventHandler)delegate(VideoPlayer v, string msg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("[" + label + "] " + msg)); } }; val3.prepareCompleted += (EventHandler)delegate { HandleSlotPrepared(slot); }; val3.started += (EventHandler)delegate { HandleSlotStarted(slot); }; return slot; } public void ApplyIndex(int index) { if (VideoLibrary.Entries.Count != 0) { index = Wrap(index, VideoLibrary.Entries.Count); StopActiveChannel(); int num = FindSlotFor(index); if (num < 0) { num = _activeSlot; BindSlotToVideo(_slots[num], index); } _activeSlot = num; AssignRenderTargets(_activeSlot); Slot slot = _slots[_activeSlot]; if (slot.Player.url != BuildUrl(index)) { BindSlotToVideo(slot, index); } ShowStatus("Loading..."); slot.Player.Prepare(); slot.Player.Play(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Theater playing [{index}] {Path.GetFileName(VideoLibrary.Entries[index].VideoPath)} (slot {_activeSlot})"); } PreloadNeighbors(index); } } private void HandleSlotPrepared(Slot slot) { slot.Prepared = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[{slot.Label}] prepared: {Path.GetFileName(slot.Player.url)} ({slot.Player.width}x{slot.Player.height}x{slot.Player.frameRate:F1}fps)"); } if (_slots != null && _slots[_activeSlot] == slot) { AssignRenderTargets(_activeSlot); CompositeToScreen(slot.RenderTexture); } } private void HandleSlotStarted(Slot slot) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[" + slot.Label + "] started: " + Path.GetFileName(slot.Player.url))); } if (_slots != null && _slots[_activeSlot] == slot) { AssignRenderTargets(_activeSlot); CompositeToScreen(slot.RenderTexture); HideStatus(); if (slot.VideoIndex >= 0 && slot.VideoIndex != _activeAudioIndex) { StartAudioFor(slot.VideoIndex); } } } private void PreloadNeighbors(int centerIndex) { int count = VideoLibrary.Entries.Count; if (count <= 1) { return; } int num = Wrap(centerIndex + 1, count); int num2 = Wrap(centerIndex - 1, count); for (int i = 0; i < _slots.Length; i++) { if (i != _activeSlot) { int num3 = ((num != centerIndex && FindSlotFor(num) < 0) ? num : ((num2 != centerIndex && FindSlotFor(num2) < 0) ? num2 : (-1))); if (num3 < 0) { break; } BindSlotToVideo(_slots[i], num3); _slots[i].Player.Prepare(); } } } private void BindSlotToVideo(Slot slot, int videoIndex) { if (slot.VideoIndex != videoIndex) { slot.Player.Stop(); slot.Player.url = VideoLibrary.Entries[videoIndex].VideoPath; slot.VideoIndex = videoIndex; slot.Prepared = false; } } private int FindSlotFor(int videoIndex) { for (int i = 0; i < _slots.Length; i++) { if (_slots[i].VideoIndex == videoIndex) { return i; } } return -1; } private void BindScreenTo(RenderTexture rt) { for (int i = 0; i < _screenTextureSlots.Length; i++) { _screenMaterial.SetTexture(_screenTextureSlots[i], (Texture)(object)rt); } _screenMaterial.mainTexture = (Texture)(object)rt; } private static void UpgradeVanillaRenderTextureInPlace(DrivingRangeStaticCameraManager vanillaMgr, RenderTexture sharedTarget, int desiredSize) { if ((Object)(object)sharedTarget == (Object)null || desiredSize <= 0 || (((Texture)sharedTarget).width == desiredSize && ((Texture)sharedTarget).height == desiredSize)) { return; } try { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Upgrading shared theater RT in place: '{((Object)sharedTarget).name}' {((Texture)sharedTarget).width}x{((Texture)sharedTarget).height} -> {desiredSize}x{desiredSize}"); } sharedTarget.Release(); ((Texture)sharedTarget).width = desiredSize; ((Texture)sharedTarget).height = desiredSize; sharedTarget.Create(); if (!(Traverse.Create((object)vanillaMgr).Field("cameras").GetValue() is DrivingRangeStaticCamera[] array)) { return; } foreach (DrivingRangeStaticCamera val in array) { if ((Object)(object)val == (Object)null) { continue; } Traverse val2 = Traverse.Create((object)val); object value = val2.Field("thisCamera").GetValue(); Camera val3 = (Camera)((value is Camera) ? value : null); if (!((Object)(object)val3 == (Object)null)) { val3.targetTexture = sharedTarget; val3.RemoveAllCommandBuffers(); object value2 = val2.Field("staticRenderTexture").GetValue(); RenderTexture val4 = (RenderTexture)((value2 is RenderTexture) ? value2 : null); if ((Object)(object)val4 != (Object)null) { val4.Release(); Object.Destroy((Object)(object)val4); } object value3 = val2.Field("staticDepthTexture").GetValue(); RenderTexture val5 = (RenderTexture)((value3 is RenderTexture) ? value3 : null); if ((Object)(object)val5 != (Object)null) { val5.Release(); Object.Destroy((Object)(object)val5); } val2.Field("staticRenderTexture").SetValue((object)null); val2.Field("staticDepthTexture").SetValue((object)null); val2.Field("hasTextures").SetValue((object)false); val.RenderStaticTexture(); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("In-place theater RT upgrade failed: " + ex.Message)); } } } public void ApplyConfiguredScreenResolution() { if (!((Object)(object)_screenRenderTexture == (Object)null) && !((Object)(object)_vanillaManager == (Object)null)) { UpgradeVanillaRenderTextureInPlace(_vanillaManager, _screenRenderTexture, Plugin.GetConfiguredScreenResolution()); RefreshDisplayComposition(); } } private void AssignRenderTargets(int activeSlot) { for (int i = 0; i < _slots.Length; i++) { if ((Object)(object)_slots[i].Player.targetTexture != (Object)(object)_slots[i].RenderTexture) { _slots[i].Player.targetTexture = _slots[i].RenderTexture; } } if ((Object)(object)_screenRenderTexture == (Object)null) { BindScreenTo(_slots[activeSlot].RenderTexture); } else { BindScreenTo(_screenRenderTexture); } } private void CompositeToScreen(RenderTexture source) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_screenRenderTexture == (Object)null) && !((Object)(object)source == (Object)null)) { float num = ((Plugin.OverscanCompensationConfig != null) ? Mathf.Clamp01(Plugin.OverscanCompensationConfig.Value) : 0.12f); float num2 = ((Texture)_screenRenderTexture).width; float num3 = ((Texture)_screenRenderTexture).height; float num4 = num2 * (1f - num * 2f); float num5 = num3 * (1f - num * 2f); float num6 = ((((Texture)source).height > 0) ? ((float)((Texture)source).width / (float)((Texture)source).height) : 1.7777778f); float num7 = ((num5 > 0f) ? (num4 / num5) : num6); float num8 = num4; float num9 = num5; if (num7 > num6) { num8 = num9 * num6; } else { num9 = num8 / num6; } float num10 = (num2 - num8) * 0.5f; float num11 = (num3 - num9) * 0.5f; RenderTexture active = RenderTexture.active; RenderTexture.active = _screenRenderTexture; GL.PushMatrix(); GL.LoadPixelMatrix(0f, num2, num3, 0f); GL.Clear(true, true, Color.black); Graphics.DrawTexture(new Rect(num10, num11, num8, num9), (Texture)(object)source); GL.PopMatrix(); RenderTexture.active = active; } } private string BuildUrl(int index) { return VideoLibrary.Entries[index].VideoPath; } private void StartAudioFor(int index) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) VideoEntry videoEntry = VideoLibrary.Entries[index]; if (string.IsNullOrEmpty(videoEntry.AudioPath)) { return; } if (_sounds[index].handle == IntPtr.Zero) { System coreSystem = RuntimeManager.CoreSystem; RESULT val = ((System)(ref coreSystem)).createSound(videoEntry.AudioPath, (MODE)2097298, ref _sounds[index]); if ((int)val != 0) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"FMOD createSound failed for {videoEntry.AudioPath}: {val}"); } return; } } System coreSystem2 = RuntimeManager.CoreSystem; RESULT val2 = ((System)(ref coreSystem2)).playSound(_sounds[index], default(ChannelGroup), false, ref _activeChannel); if ((int)val2 != 0) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"FMOD playSound failed: {val2}"); } } else { ((Channel)(ref _activeChannel)).setMode((MODE)2097168); ((Channel)(ref _activeChannel)).set3DMinMaxDistance(6f, 45f); ((Channel)(ref _activeChannel)).setVolume(Plugin.VolumeConfig.Value); _activeChannelValid = true; _activeAudioIndex = index; _driftCheckTimer = 2f; UpdateAudioSpatialization(force: true); } } private void StopActiveChannel() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (_activeChannelValid) { ((Channel)(ref _activeChannel)).stop(); _activeChannelValid = false; _activeAudioIndex = -1; } } public void SetVolume(float v) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) v = Mathf.Clamp01(v); if (_activeChannelValid) { ((Channel)(ref _activeChannel)).setVolume(v); } } public void RefreshDisplayComposition() { if (_slots != null && _activeSlot >= 0 && _activeSlot < _slots.Length) { VideoPlayer player = _slots[_activeSlot].Player; if ((Object)(object)_screenRenderTexture != (Object)null && (Object)(object)player != (Object)null && (player.isPlaying || player.isPrepared)) { CompositeToScreen(_slots[_activeSlot].RenderTexture); } } } public void ShowNoVideos() { StopActiveChannel(); ShowStatus("No video files added"); } private void CreateStatusText() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_statusText != (Object)null) && !((Object)(object)_screenRenderer == (Object)null)) { GameObject val = new GameObject("SBG-TheaterStatus"); val.transform.SetParent(((Component)this).transform, false); _statusText = val.AddComponent(); ((TMP_Text)_statusText).text = string.Empty; ((TMP_Text)_statusText).fontSize = 8f; ((TMP_Text)_statusText).alignment = (TextAlignmentOptions)514; ((Graphic)_statusText).color = Color.white; ((TMP_Text)_statusText).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)_statusText).outlineWidth = 0.2f; ((TMP_Text)_statusText).rectTransform.sizeDelta = new Vector2(12f, 4f); ((Component)_statusText).gameObject.SetActive(false); UpdateStatusTransform(); } } private void UpdateStatusTransform() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_statusText == (Object)null) && !((Object)(object)_screenRenderer == (Object)null)) { Transform transform = _statusText.transform; Bounds bounds = _screenRenderer.bounds; transform.position = ((Bounds)(ref bounds)).center + ((Component)_screenRenderer).transform.forward * 0.03f; transform.rotation = ((Component)_screenRenderer).transform.rotation * Quaternion.Euler(0f, 180f, 0f); transform.localScale = Vector3.one * 0.45f; } } private void ShowStatus(string text) { if ((Object)(object)_statusText == (Object)null) { CreateStatusText(); } if (!((Object)(object)_statusText == (Object)null)) { UpdateStatusTransform(); ((TMP_Text)_statusText).text = text; ((Component)_statusText).gameObject.SetActive(true); } } private void HideStatus() { if ((Object)(object)_statusText != (Object)null) { ((Component)_statusText).gameObject.SetActive(false); } } private Vector3 GetAudioWorldPosition() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_screenRenderer != (Object)null) { Bounds bounds = _screenRenderer.bounds; return ((Bounds)(ref bounds)).center; } return ((Component)this).transform.position; } private void UpdateAudioSpatialization(bool force = false) { //IL_000a: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) //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 (!_activeChannelValid) { return; } Vector3 audioWorldPosition = GetAudioWorldPosition(); if (!force) { Vector3 val = audioWorldPosition - _lastAudioWorldPos; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { return; } } VECTOR val2 = RuntimeUtils.ToFMODVector(audioWorldPosition); VECTOR val3 = RuntimeUtils.ToFMODVector(Vector3.zero); ((Channel)(ref _activeChannel)).set3DAttributes(ref val2, ref val3); _lastAudioWorldPos = audioWorldPosition; } private void Update() { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) VideoPlayer val = ((_slots != null && _activeSlot >= 0 && _activeSlot < _slots.Length) ? _slots[_activeSlot].Player : null); if ((Object)(object)_screenRenderTexture != (Object)null && (Object)(object)val != (Object)null && (val.isPlaying || val.isPrepared)) { CompositeToScreen(_slots[_activeSlot].RenderTexture); } if ((Object)(object)_statusText != (Object)null && ((Component)_statusText).gameObject.activeSelf) { UpdateStatusTransform(); } if (!_activeChannelValid) { return; } UpdateAudioSpatialization(); _driftCheckTimer -= Time.unscaledDeltaTime; if (_driftCheckTimer > 0f) { return; } _driftCheckTimer = 2f; if ((Object)(object)val == (Object)null || !val.isPlaying) { return; } uint num = default(uint); ((Channel)(ref _activeChannel)).getPosition(ref num, (TIMEUNIT)1); double num2 = val.time * 1000.0; double num3 = num2 - (double)num; if (Math.Abs(num3) > 250.0) { ((Channel)(ref _activeChannel)).setPosition((uint)num2, (TIMEUNIT)1); ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)$"Theater drift correction: {num3:F1}ms → setPosition({num2:F0})"); } } } private void OnDestroy() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Current == (Object)(object)this) { Current = null; } StopActiveChannel(); if ((Object)(object)_screenMaterial != (Object)null) { for (int i = 0; i < _screenBindings.Length; i++) { _screenMaterial.SetTexture(_screenBindings[i].Name, _screenBindings[i].Texture); _screenMaterial.SetTextureScale(_screenBindings[i].Name, _screenBindings[i].Scale); _screenMaterial.SetTextureOffset(_screenBindings[i].Name, _screenBindings[i].Offset); } } if (_slots != null) { for (int j = 0; j < _slots.Length; j++) { VideoPlayer player = _slots[j].Player; if (player != null) { player.Stop(); } if ((Object)(object)_slots[j].RenderTexture != (Object)null) { _slots[j].RenderTexture.Release(); Object.Destroy((Object)(object)_slots[j].RenderTexture); } } } if (_sounds == null) { return; } for (int k = 0; k < _sounds.Length; k++) { if (_sounds[k].handle != IntPtr.Zero) { ((Sound)(ref _sounds[k])).release(); } } } private static int Wrap(int v, int n) { return (v % n + n) % n; } } internal sealed class VideoEntry { public string VideoPath; public string AudioPath; public string Name => Path.GetFileName(VideoPath); } internal static class VideoLibrary { private static readonly string[] VideoExtensions = new string[6] { ".mp4", ".webm", ".mov", ".ogv", ".mkv", ".m4v" }; private static readonly string[] AudioExtensions = new string[6] { ".ogg", ".wav", ".mp3", ".m4a", ".aac", ".flac" }; private static readonly string[] DedicatedSubfolders = new string[3] { "Videos", "Video", "video" }; public static List Entries { get; private set; } = new List(); public static List Videos => Entries.ConvertAll((VideoEntry e) => e.VideoPath); public static void ScanAll(string pluginsRoot, ManualLogSource log) { Entries.Clear(); if (!Directory.Exists(pluginsRoot)) { log.LogWarning((object)("Plugins root '" + pluginsRoot + "' does not exist.")); return; } HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); string[] directories = Directory.GetDirectories(pluginsRoot); foreach (string text in directories) { string[] dedicatedSubfolders = DedicatedSubfolders; foreach (string path in dedicatedSubfolders) { string path2 = Path.Combine(text, path); if (!Directory.Exists(path2)) { continue; } string[] files = Directory.GetFiles(path2); foreach (string text2 in files) { if (IsVideoFile(text2)) { AddEntry(text2, requireSidecar: false, seen, log); } } } dedicatedSubfolders = Directory.GetFiles(text); foreach (string text3 in dedicatedSubfolders) { if (IsVideoFile(text3)) { AddEntry(text3, requireSidecar: true, seen, log); } } } Entries = Entries.OrderBy((VideoEntry e) => Path.GetFileName(e.VideoPath), StringComparer.OrdinalIgnoreCase).ToList(); if (Entries.Count == 0) { log.LogInfo((object)"No video files found (looked in plugin Videos/, Video/, and plugin roots with sidecar audio)."); return; } int num = Entries.Count((VideoEntry e) => e.AudioPath != null); log.LogInfo((object)$"Theater loaded {Entries.Count} video(s) ({num} with sidecar audio):"); foreach (VideoEntry entry in Entries) { string text4 = ((entry.AudioPath != null) ? (" + " + Path.GetFileName(entry.AudioPath)) : " (silent — no sidecar)"); log.LogInfo((object)(" - " + entry.Name + text4)); } } private static void AddEntry(string file, bool requireSidecar, HashSet seen, ManualLogSource log) { if (seen.Add(Path.GetFullPath(file))) { string text = FindSidecarAudio(file); if (!requireSidecar || text != null) { Entries.Add(new VideoEntry { VideoPath = file, AudioPath = text }); } } } private static bool IsVideoFile(string path) { return Array.IndexOf(VideoExtensions, Path.GetExtension(path).ToLowerInvariant()) >= 0; } private static string FindSidecarAudio(string videoPath) { string directoryName = Path.GetDirectoryName(videoPath); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoPath); string[] audioExtensions = AudioExtensions; foreach (string text in audioExtensions) { string text2 = Path.Combine(directoryName, fileNameWithoutExtension + text); if (File.Exists(text2)) { return text2; } } return null; } } internal class VolumeSliderUi : MonoBehaviour { private static readonly int[] ScreenResolutionOptions = new int[3] { 1024, 1536, 2048 }; public static VolumeSliderUi Instance; private Slider _resolutionSlider; private TextMeshProUGUI _resolutionValueLabel; private Slider _volumeSlider; private Slider _overscanSlider; public static void EnsureExists(PauseMenu pauseMenu) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance != (Object)null) && !((Object)(object)pauseMenu == (Object)null) && !((Object)(object)pauseMenu.menuContainer == (Object)null)) { GameObject val = new GameObject("SBG-TheaterVolumeSlider", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(pauseMenu.menuContainer.transform, false); Instance = val.AddComponent(); } } public static void HandlePauseShown() { EnsureExists(SingletonBehaviour.Instance); if (!((Object)(object)Instance == (Object)null)) { Instance.SyncFromConfig(); Instance.SetVisible((Object)(object)TheaterController.Current != (Object)null); } } public static void HandlePauseHidden() { Instance?.SetVisible(visible: false); } private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)((Component)this).transform; val.anchorMin = new Vector2(0.5f, 0f); val.anchorMax = new Vector2(0.5f, 0f); val.pivot = new Vector2(0.5f, 0f); val.anchoredPosition = new Vector2(0f, 64f); val.sizeDelta = new Vector2(420f, 144f); GameObject val2 = new GameObject("Panel", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(((Component)this).transform, false); RectTransform component = val2.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Graphic)val2.GetComponent()).color = new Color(0f, 0f, 0f, 0.65f); (Slider, TextMeshProUGUI) tuple = CreateDiscreteSliderRow(val2.transform, "Screen res", 48f, ScreenResolutionOptions, Plugin.GetConfiguredScreenResolution(), delegate(int v) { Plugin.ScreenResolutionConfig.Value = v; TheaterController.Current?.ApplyConfiguredScreenResolution(); }); _resolutionSlider = tuple.Item1; _resolutionValueLabel = tuple.Item2; _volumeSlider = CreateSliderRow(val2.transform, "Theater volume", 0f, 0f, 1f, Plugin.VolumeConfig.Value, delegate(float v) { Plugin.VolumeConfig.Value = v; TheaterController.Current?.SetVolume(v); }); _overscanSlider = CreateSliderRow(val2.transform, "Screen fit", -48f, 0f, 0.25f, Plugin.OverscanCompensationConfig.Value, delegate(float v) { Plugin.OverscanCompensationConfig.Value = v; TheaterController.Current?.RefreshDisplayComposition(); }); SetVisible(visible: false); } private static Slider CreateSliderRow(Transform parent, string labelTextValue, float y, float min, float max, float value, UnityAction onChanged) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Expected O, but got Unknown //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(labelTextValue + " Label", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(0f, 0.5f); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(14f, y); component.sizeDelta = new Vector2(120f, 24f); TextMeshProUGUI component2 = val.GetComponent(); ((TMP_Text)component2).text = labelTextValue; ((TMP_Text)component2).fontSize = 16f; ((TMP_Text)component2).alignment = (TextAlignmentOptions)4097; ((Graphic)component2).color = Color.white; GameObject val2 = new GameObject(labelTextValue + " Slider", new Type[2] { typeof(RectTransform), typeof(Slider) }); val2.transform.SetParent(parent, false); RectTransform component3 = val2.GetComponent(); component3.anchorMin = new Vector2(0f, 0.5f); component3.anchorMax = new Vector2(1f, 0.5f); component3.pivot = new Vector2(0f, 0.5f); component3.anchoredPosition = new Vector2(140f, y); component3.sizeDelta = new Vector2(-160f, 16f); Slider component4 = val2.GetComponent(); component4.minValue = min; component4.maxValue = max; component4.value = value; GameObject val3 = new GameObject("Bg", new Type[2] { typeof(RectTransform), typeof(Image) }); val3.transform.SetParent(val2.transform, false); RectTransform component5 = val3.GetComponent(); component5.anchorMin = new Vector2(0f, 0.25f); component5.anchorMax = new Vector2(1f, 0.75f); component5.sizeDelta = Vector2.zero; ((Graphic)val3.GetComponent()).color = new Color(1f, 1f, 1f, 0.2f); GameObject val4 = new GameObject("Fill Area", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val2.transform, false); RectTransform component6 = val4.GetComponent(); component6.anchorMin = new Vector2(0f, 0.25f); component6.anchorMax = new Vector2(1f, 0.75f); component6.sizeDelta = new Vector2(-20f, 0f); component6.anchoredPosition = new Vector2(-5f, 0f); GameObject val5 = new GameObject("Fill", new Type[2] { typeof(RectTransform), typeof(Image) }); val5.transform.SetParent(val4.transform, false); RectTransform component7 = val5.GetComponent(); component7.sizeDelta = Vector2.zero; ((Graphic)val5.GetComponent()).color = new Color(0.4f, 0.85f, 1f, 1f); GameObject val6 = new GameObject("Handle Slide Area", new Type[1] { typeof(RectTransform) }); val6.transform.SetParent(val2.transform, false); RectTransform component8 = val6.GetComponent(); component8.anchorMin = new Vector2(0f, 0f); component8.anchorMax = new Vector2(1f, 1f); component8.sizeDelta = new Vector2(-20f, 0f); component8.anchoredPosition = new Vector2(-5f, 0f); GameObject val7 = new GameObject("Handle", new Type[2] { typeof(RectTransform), typeof(Image) }); val7.transform.SetParent(val6.transform, false); RectTransform component9 = val7.GetComponent(); component9.sizeDelta = new Vector2(20f, 20f); Image component10 = val7.GetComponent(); ((Graphic)component10).color = Color.white; ((Selectable)component4).targetGraphic = (Graphic)(object)component10; component4.fillRect = component7; component4.handleRect = component9; component4.direction = (Direction)0; ((UnityEvent)(object)component4.onValueChanged).AddListener(onChanged); return component4; } private static (Slider Slider, TextMeshProUGUI ValueLabel) CreateDiscreteSliderRow(Transform parent, string labelTextValue, float y, int[] options, int selectedValue, Action onChanged) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) Slider slider = CreateSliderRow(parent, labelTextValue, y, 0f, options.Length - 1, 0f, delegate { }); slider.wholeNumbers = true; GameObject val = new GameObject(labelTextValue + " Value", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(1f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(1f, 0.5f); component.anchoredPosition = new Vector2(-12f, y); component.sizeDelta = new Vector2(60f, 24f); TextMeshProUGUI valueText = val.GetComponent(); ((TMP_Text)valueText).fontSize = 16f; ((TMP_Text)valueText).alignment = (TextAlignmentOptions)4100; ((Graphic)valueText).color = Color.white; int num = 0; for (int i = 0; i < options.Length; i++) { if (options[i] == selectedValue) { num = i; break; } } slider.SetValueWithoutNotify((float)num); ((TMP_Text)valueText).text = options[num].ToString(); ((UnityEventBase)slider.onValueChanged).RemoveAllListeners(); ((UnityEvent)(object)slider.onValueChanged).AddListener((UnityAction)delegate(float v) { int num2 = Mathf.Clamp(Mathf.RoundToInt(v), 0, options.Length - 1); slider.SetValueWithoutNotify((float)num2); ((TMP_Text)valueText).text = options[num2].ToString(); onChanged(options[num2]); }); return (slider, valueText); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void SyncFromConfig() { if ((Object)(object)_resolutionSlider != (Object)null) { int configuredScreenResolution = Plugin.GetConfiguredScreenResolution(); int num = 0; for (int i = 0; i < ScreenResolutionOptions.Length; i++) { if (ScreenResolutionOptions[i] == configuredScreenResolution) { num = i; break; } } _resolutionSlider.SetValueWithoutNotify((float)num); if ((Object)(object)_resolutionValueLabel != (Object)null) { ((TMP_Text)_resolutionValueLabel).text = ScreenResolutionOptions[num].ToString(); } } Slider volumeSlider = _volumeSlider; if (volumeSlider != null) { volumeSlider.SetValueWithoutNotify(Plugin.VolumeConfig.Value); } Slider overscanSlider = _overscanSlider; if (overscanSlider != null) { overscanSlider.SetValueWithoutNotify(Plugin.OverscanCompensationConfig.Value); } } public void SetVisible(bool visible) { ((Component)this).gameObject.SetActive(visible); } } }