using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AnimatedCybergrindTextures.Components;
using AnimatedCybergrindTextures.Utils;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.Video;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AnimatedCybergrindTextures")]
[assembly: AssemblyDescription("ULTRAKILL mod for using videos as Cybergrind textures")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AnimatedCybergrindTextures")]
[assembly: AssemblyCopyright("Copyright © 2024 Flazhik")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5C47D081-54C6-459C-AAE5-883E54B2C7F1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AnimatedCybergrindTextures
{
[BepInProcess("ULTRAKILL.exe")]
[BepInPlugin("dev.flazhik.animatedcgtextures", "AnimatedCybergrindTextures", "1.0.0")]
public class AnimatedCybergrindTextures : BaseUnityPlugin
{
private static Harmony _harmony;
private void Awake()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
MonoSingleton<AssetsManager>.Instance.LoadAssets();
MonoSingleton<AssetsManager>.Instance.RegisterAssets();
_harmony = new Harmony("dev.flazhik.animatedcgtextures");
_harmony.PatchAll();
}
}
[ConfigureSingleton(/*Could not decode attribute arguments.*/)]
public class AssetsManager : MonoSingleton<AssetsManager>
{
private const BindingFlags Flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly Dictionary<string, Object> Prefabs = new Dictionary<string, Object>();
private AssetBundle _bundle;
public void LoadAssets()
{
_bundle = AssetBundle.LoadFromMemory(Resources.AnimatedCybergrindTextures);
}
public void RegisterAssets()
{
string[] allAssetNames = _bundle.GetAllAssetNames();
foreach (string text in allAssetNames)
{
Prefabs.Add(text, _bundle.LoadAsset<Object>(text));
}
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
for (int i = 0; i < types.Length; i++)
{
CheckType(types[i]);
}
}
private static void CheckType(IReflect type)
{
type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).ToList().ForEach(ProcessField);
}
private static void ProcessField(FieldInfo field)
{
//IL_004a: 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)
if (!field.FieldType.IsArray && field.IsStatic)
{
ExternalAsset customAttribute = field.GetCustomAttribute<ExternalAsset>();
UltrakillAsset customAttribute2 = field.GetCustomAttribute<UltrakillAsset>();
if (customAttribute != null)
{
field.SetValue(null, Prefabs[customAttribute.Path]);
}
else if (customAttribute2 != null)
{
field.SetValue(null, Addressables.LoadAssetAsync<GameObject>((object)customAttribute2.Path).WaitForCompletion());
}
}
}
}
public static class Configuration
{
private static readonly ConfigFile Config = new ConfigFile(Path.Combine(Paths.ConfigPath, "AnimatedCybergrindTextures", "config.cfg"), true);
public static readonly ConfigEntry<float> PreviewLoadingTimeout = Config.Bind<float>("VideoPlayer", "PreviewTimeout", 5f, "Timeout for a video preview loading attempt in seconds");
public static readonly ConfigEntry<int> SkyboxWidth = Config.Bind<int>("Skybox", "Width", 1920, "Width of a skybox texture");
public static readonly ConfigEntry<int> SkyboxHeight = Config.Bind<int>("Skybox", "Height", 960, "Height of a skybox texture");
public static readonly ConfigEntry<int> SkyboxColorDepth = Config.Bind<int>("Skybox", "Depth", 24, "Color depth used by skybox video player");
public static readonly ConfigEntry<int> TileSize = Config.Bind<int>("Tiles", "Size", 100, "Width and height of a texture of a single tile on the grid");
public static readonly ConfigEntry<int> TileColorDepth = Config.Bind<int>("Tiles", "Depth", 24, "Color depth used by tiles video player");
}
internal static class PluginInfo
{
public const string GUID = "dev.flazhik.animatedcgtextures";
public const string NAME = "AnimatedCybergrindTextures";
public const string VERSION = "1.0.0";
}
[AttributeUsage(AttributeTargets.Field)]
public class ExternalAsset : Attribute
{
public string Path { get; }
public ExternalAsset(string path = "")
{
Path = path;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class UltrakillAsset : Attribute
{
public string Path { get; }
public UltrakillAsset(string path = "")
{
Path = path;
}
}
[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[DebuggerNonUserCode]
[CompilerGenerated]
internal class Resources
{
private static ResourceManager resourceMan;
private static CultureInfo resourceCulture;
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static ResourceManager ResourceManager
{
get
{
if (resourceMan == null)
{
resourceMan = new ResourceManager("AnimatedCybergrindTextures.Resources", typeof(Resources).Assembly);
}
return resourceMan;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
internal static byte[] AnimatedCybergrindTextures => (byte[])ResourceManager.GetObject("AnimatedCybergrindTextures", resourceCulture);
internal Resources()
{
}
}
}
namespace AnimatedCybergrindTextures.Utils
{
public static class GenericUtils
{
public const string CustomGridKey = "cyberGrind.customGrid";
public const string CustomSkyboxKey = "cyberGrind.customSkybox";
private static readonly List<string> VideoExtensions = new List<string>
{
".asf", ".avi", ".dv", ".m4v", ".mov", ".mp4", ".mpg", ".mpeg", ".ogv", ".vp8",
".webm", ".wmv"
};
public static VideoPlayer InitVideoPlayer(Transform parent)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
VideoPlayer obj = Object.Instantiate<GameObject>(new GameObject("AnimatedTexturesPlayer"), parent, true).AddComponent<VideoPlayer>();
obj.isLooping = true;
obj.SetDirectAudioMute((ushort)0, true);
return obj;
}
public static bool HasVideoExtension(string key)
{
return VideoExtensions.Contains(new FileInfo(key).Extension.ToLower());
}
public static string KeyToUrl(string key)
{
return "file://" + new FileInfo(key).FullName;
}
}
public static class ReflectionUtils
{
private const BindingFlags BindingFlagsFields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
public static object GetPrivate<T>(T instance, Type classType, string field)
{
FieldInfo field2 = classType.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (!(field2 != null))
{
return null;
}
return field2.GetValue(instance);
}
}
}
namespace AnimatedCybergrindTextures.Patches
{
[HarmonyPatch(typeof(CustomTextures))]
public class CustomTexturesPatch
{
private const string AdditionalOptions = "/FirstRoom/Room/CyberGrindSettings/Canvas/CustomTextures/Panel/AdditionalOptions";
private const string DisableSkyboxRotationKey = "cyberGrind.customSkybox.disableSpin";
[ExternalAsset("Assets/Textures/animated_icon.png")]
private static Texture2D _animatedIcon;
[ExternalAsset("Assets/Elements/SkyboxToggle.prefab")]
private static GameObject _skyboxToggleTemplate;
[UltrakillAsset("b433c919446768d4a9e64494c6bfd084")]
private static GameObject _shopClick;
[HarmonyPrefix]
[HarmonyPatch(typeof(CustomTextures), "Start")]
public static bool CustomTextures_Start_Prefix(CustomTextures __instance, Material[] ___gridMaterials, Material ___skyMaterial, OutdoorLightMaster ___olm, GameObject ___itemButtonTemplate, Dictionary<string, Texture2D> ___imageCache)
{
GameObject gameObject = ((Component)MonoSingleton<EndlessGrid>.Instance).gameObject;
AnimatedTexturesManager animatedTexturesManager = default(AnimatedTexturesManager);
if (gameObject.TryGetComponent<AnimatedTexturesManager>(ref animatedTexturesManager))
{
return true;
}
animatedTexturesManager = gameObject.AddComponent<AnimatedTexturesManager>();
AsyncTexturePreviewLoader asyncTexturePreviewLoader = gameObject.AddComponent<AsyncTexturePreviewLoader>();
animatedTexturesManager.gridMaterials = ___gridMaterials;
animatedTexturesManager.skyboxMaterial = ___skyMaterial;
animatedTexturesManager.olm = ___olm;
asyncTexturePreviewLoader.OriginalCache = ___imageCache;
AddAnimatedIcon(___itemButtonTemplate);
animatedTexturesManager.skyboxRotationToggle = AddSkyboxRotationToggle(___olm);
return true;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CustomTextures), "Start")]
public static void CustomTextures_Start_Postfix(CustomTextures __instance, Material[] ___gridMaterials, Material ___skyMaterial)
{
PrefsManager instance = MonoSingleton<PrefsManager>.Instance;
AnimatedTexturesManager animatedTexturesManager = AnimatedTextures();
for (int i = 0; i < 3; i++)
{
string stringLocal = instance.GetStringLocal(string.Format("{0}_{1}", "cyberGrind.customGrid", i), (string)null);
if (!string.IsNullOrEmpty(stringLocal))
{
animatedTexturesManager.SetGridTexture(stringLocal, i);
}
}
string stringLocal2 = instance.GetStringLocal("cyberGrind.customSkybox", (string)null);
if (!string.IsNullOrEmpty(stringLocal2))
{
animatedTexturesManager.SetSkyboxTexture(stringLocal2);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CustomTextures), "BuildLeaf")]
public static bool CustomTextures_BuildLeaf_Prefix(CustomTextures __instance, FileInfo file, GameObject ___itemButtonTemplate, Transform ___itemParent, ref Action __result)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
GameObject btn = Object.Instantiate<GameObject>(___itemButtonTemplate, ___itemParent, false);
((UnityEventBase)btn.GetComponent<Button>().onClick).RemoveAllListeners();
((UnityEvent)btn.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
__instance.SetTexture(file.FullName);
});
btn.SetActive(true);
if (!GenericUtils.HasVideoExtension(file.FullName))
{
foreach (Transform item in btn.transform)
{
((Component)item).gameObject.SetActive(false);
}
}
if ((Object)(object)AsyncTextureLoader() != (Object)null)
{
AsyncTextureLoader().LoadPreview(file.FullName, btn);
}
__result = delegate
{
Object.Destroy((Object)(object)btn);
};
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CustomTextures), "SetTexture")]
public static bool CustomTextures_SetTexture_Prefix(string key, CustomTextures __instance, bool ___editBase, bool ___editTop, bool ___editTopRow)
{
if (!GenericUtils.HasVideoExtension(key))
{
return true;
}
string editMode = ReflectionUtils.GetPrivate<CustomTextures>(__instance, typeof(CustomTextures), "currentEditMode").ToString();
AnimatedTextures().SetTexture(key, editMode, ___editBase, ___editTop, ___editTopRow);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CustomTextures), "SetEditMode")]
public static void CustomTextures_SetEditMode_Postfix(int m, CustomTextures __instance)
{
AnimatedTextures().skyboxRotationToggle.SetActive(m == 2);
}
private static void AddAnimatedIcon(GameObject template)
{
//IL_0005: 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)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: 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_0088: 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_00b2: 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)
GameObject val = new GameObject("Animated Icon");
val.transform.parent = template.transform;
Image val2 = val.AddComponent<Image>();
RectTransform component = val.GetComponent<RectTransform>();
Sprite sprite = Sprite.Create(_animatedIcon, new Rect(0f, 0f, (float)((Texture)_animatedIcon).width, (float)((Texture)_animatedIcon).height), new Vector2(0.5f, 0.5f), 100f);
val2.sprite = sprite;
val.transform.localPosition = new Vector3(15f, 20f, 0f);
component.sizeDelta = new Vector2(32f, 32f);
((Transform)component).localScale = Vector2.op_Implicit(new Vector2(1f, 1f));
}
private static GameObject AddSkyboxRotationToggle(OutdoorLightMaster olm)
{
GameObject obj = Object.Instantiate<GameObject>(_skyboxToggleTemplate, GameObject.Find("/FirstRoom/Room/CyberGrindSettings/Canvas/CustomTextures/Panel/AdditionalOptions").transform);
obj.AddComponent<HudOpenEffect>();
obj.SetActive(false);
bool boolLocal = MonoSingleton<PrefsManager>.Instance.GetBoolLocal("cyberGrind.customSkybox.disableSpin", true);
olm.dontRotateSkybox = boolLocal;
Toggle componentInChildren = obj.GetComponentInChildren<Toggle>();
obj.gameObject.AddComponent<ShopButton>().clickSound = _shopClick;
componentInChildren.isOn = olm.dontRotateSkybox;
((UnityEvent<bool>)(object)componentInChildren.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value)
{
Object.Instantiate<GameObject>(_shopClick);
MonoSingleton<PrefsManager>.Instance.SetBoolLocal("cyberGrind.customSkybox.disableSpin", value);
olm.dontRotateSkybox = value;
});
return obj;
}
private static AnimatedTexturesManager AnimatedTextures()
{
return ((Component)MonoSingleton<EndlessGrid>.Instance).gameObject.GetComponent<AnimatedTexturesManager>();
}
private static AsyncTexturePreviewLoader AsyncTextureLoader()
{
return ((Component)MonoSingleton<EndlessGrid>.Instance).gameObject.GetComponent<AsyncTexturePreviewLoader>();
}
}
}
namespace AnimatedCybergrindTextures.Components
{
public class AnimatedTexturesManager : MonoBehaviour
{
public Material[] gridMaterials;
public RenderTexture[] gridTextures;
public Material skyboxMaterial;
public RenderTexture skyboxTexture;
public VideoPlayer[] gridPlayers;
public VideoPlayer skyboxPlayer;
public OutdoorLightMaster olm;
public GameObject skyboxRotationToggle;
private void Awake()
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
gridTextures = (RenderTexture[])(object)new RenderTexture[3];
gridPlayers = (VideoPlayer[])(object)new VideoPlayer[3];
skyboxTexture = new RenderTexture(Configuration.SkyboxWidth.Value, Configuration.SkyboxHeight.Value, Configuration.SkyboxColorDepth.Value);
skyboxPlayer = GenericUtils.InitVideoPlayer(((Component)this).transform);
skyboxPlayer.targetTexture = skyboxTexture;
for (int i = 0; i < 3; i++)
{
gridTextures[i] = new RenderTexture(Configuration.TileSize.Value, Configuration.TileSize.Value, Configuration.TileColorDepth.Value);
gridPlayers[i] = GenericUtils.InitVideoPlayer(((Component)this).transform);
gridPlayers[i].targetTexture = gridTextures[i];
}
}
public void SetTexture(string key, string editMode, bool editBase, bool editTop, bool editTopRow)
{
if (!GenericUtils.HasVideoExtension(key))
{
return;
}
if (!(editMode == "Grid"))
{
if (editMode == "Skybox")
{
SetSkyboxTexture(key);
}
return;
}
for (int i = 0; i < gridMaterials.Length; i++)
{
if (gridPlayers[i].url != null)
{
gridPlayers[i].Stop();
}
if ((editBase || i != 0) && (editTop || i != 1) && (editTopRow || i != 2))
{
MonoSingleton<PrefsManager>.Instance.SetStringLocal(string.Format("{0}_{1}", "cyberGrind.customGrid", i), key);
gridPlayers[i].url = GenericUtils.KeyToUrl(key);
gridPlayers[i].Prepare();
gridPlayers[i].frame = 0L;
gridMaterials[i].mainTexture = (Texture)(object)gridTextures[i];
}
if (gridPlayers[i].url != null)
{
gridPlayers[i].Play();
}
}
}
public void SetGridTexture(string key, int index)
{
if (GenericUtils.HasVideoExtension(key))
{
if (gridPlayers[index].url != null)
{
gridPlayers[index].Stop();
}
gridPlayers[index].url = GenericUtils.KeyToUrl(key);
gridPlayers[index].Prepare();
gridPlayers[index].frame = 0L;
gridMaterials[index].mainTexture = (Texture)(object)gridTextures[index];
if (gridPlayers[index].url != null)
{
gridPlayers[index].Play();
}
}
}
public void SetSkyboxTexture(string key)
{
if (GenericUtils.HasVideoExtension(key))
{
if ((Object)(object)skyboxPlayer != (Object)null)
{
skyboxPlayer.Stop();
}
skyboxPlayer.url = GenericUtils.KeyToUrl(key);
skyboxPlayer.Prepare();
skyboxPlayer.frame = 0L;
skyboxMaterial.mainTexture = (Texture)(object)skyboxTexture;
skyboxPlayer.Play();
olm.UpdateSkyboxMaterial();
MonoSingleton<PrefsManager>.Instance.SetStringLocal("cyberGrind.customSkybox", key);
}
}
}
public class AsyncTexturePreviewLoader : MonoBehaviour
{
public Dictionary<string, Texture2D> OriginalCache;
public void LoadPreview(string key, GameObject button)
{
((MonoBehaviour)this).StartCoroutine(GenericUtils.HasVideoExtension(key) ? LoadVideoPreview(key, Callback) : LoadTexture(key, Callback));
void Callback(Texture2D tex)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)tex == (Object)null))
{
Sprite val = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), new Vector2(0.5f, 0.5f), 100f);
((Texture)val.texture).filterMode = (FilterMode)0;
button.GetComponent<Image>().sprite = val;
}
}
}
private IEnumerator LoadTexture(string key, Action<Texture2D> callback)
{
if (OriginalCache.TryGetValue(key, out var value))
{
callback(value);
yield break;
}
UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(GenericUtils.KeyToUrl(key));
try
{
yield return uwr.SendWebRequest();
if (uwr.error != null)
{
Debug.Log((object)uwr.error);
yield break;
}
Texture2D content = DownloadHandlerTexture.GetContent(uwr);
((Texture)content).filterMode = (FilterMode)0;
OriginalCache[key] = content;
callback(content);
}
finally
{
((IDisposable)uwr)?.Dispose();
}
}
private IEnumerator LoadVideoPreview(string key, Action<Texture2D> callback)
{
float timeout = Configuration.PreviewLoadingTimeout.Value;
VideoPlayer previewPlayer = GenericUtils.InitVideoPlayer(((Component)this).transform);
if (previewPlayer.url != null)
{
previewPlayer.Stop();
}
previewPlayer.url = GenericUtils.KeyToUrl(key);
previewPlayer.Prepare();
while (!previewPlayer.isPrepared)
{
yield return null;
timeout -= Time.deltaTime;
if (timeout <= 0f)
{
break;
}
}
if ((Object)(object)previewPlayer != (Object)null && !previewPlayer.isPrepared)
{
Object.Destroy((Object)(object)((Component)previewPlayer).gameObject);
yield break;
}
Texture texture2 = previewPlayer.texture;
int width = texture2.width;
int height = texture2.height;
Texture2D texture = new Texture2D(width, height, (TextureFormat)4, false);
RenderTexture renderTexture = new RenderTexture(width, height, 24);
previewPlayer.targetTexture = renderTexture;
previewPlayer.sendFrameReadyEvents = true;
previewPlayer.frame = (int)previewPlayer.frameCount / 2;
previewPlayer.Play();
previewPlayer.Pause();
previewPlayer.frameReady += (FrameReadyEventHandler)delegate
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
RenderTexture.active = renderTexture;
texture.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0);
texture.Apply();
RenderTexture.active = null;
Object.Destroy((Object)(object)((Component)previewPlayer).gameObject);
callback(texture);
};
}
}
}