using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using InterprocessLib;
using Microsoft.CodeAnalysis;
using ReFract.Shared;
using Renderite.Shared;
using Renderite.Unity;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
[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("Noble")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ee3e5f831ac7344dd0428b7fb2892aa037ae0923")]
[assembly: AssemblyProduct("Re:Fract // Reloaded (for Unity)")]
[assembly: AssemblyTitle("ReFract_Unity")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/noblereign/ReFract-ReLoaded")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ReFract.Shared
{
public enum ReFractCommandValueType : byte
{
Int,
Float,
Bool,
Color,
Vector2,
Vector4,
String
}
public struct ReFractColor
{
public float r;
public float g;
public float b;
public float a;
public override string ToString()
{
return $"({r}, {g}, {b}, {a})";
}
}
public struct ReFractVector2
{
public float x;
public float y;
public override string ToString()
{
return $"({x}, {y})";
}
}
public struct ReFractVector4
{
public float x;
public float y;
public float z;
public float w;
public override string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
}
public class ReFractCommand : RendererCommand
{
public int RenderTextureId;
public bool IsRemoveAlphaCommand;
public string CameraName = "";
public string ComponentName = "";
public string ParameterName = "";
public ReFractCommandValueType ValueType;
public int IntValue;
public float FloatValue;
public bool BoolValue;
public ReFractColor ColorValue;
public ReFractVector2 Vector2Value;
public ReFractVector4 Vector4Value;
public string StringValue = "";
public override void Pack(ref MemoryPacker packer)
{
((MemoryPacker)(ref packer)).Write<int>(RenderTextureId);
((MemoryPacker)(ref packer)).Write<bool>(IsRemoveAlphaCommand);
((MemoryPacker)(ref packer)).Write(CameraName);
((MemoryPacker)(ref packer)).Write(ComponentName);
((MemoryPacker)(ref packer)).Write(ParameterName);
((MemoryPacker)(ref packer)).Write<byte>((byte)ValueType);
switch (ValueType)
{
case ReFractCommandValueType.Int:
((MemoryPacker)(ref packer)).Write<int>(IntValue);
break;
case ReFractCommandValueType.Float:
((MemoryPacker)(ref packer)).Write<float>(FloatValue);
break;
case ReFractCommandValueType.Bool:
((MemoryPacker)(ref packer)).Write<bool>(BoolValue);
break;
case ReFractCommandValueType.Color:
((MemoryPacker)(ref packer)).Write<float>(ColorValue.r);
((MemoryPacker)(ref packer)).Write<float>(ColorValue.g);
((MemoryPacker)(ref packer)).Write<float>(ColorValue.b);
((MemoryPacker)(ref packer)).Write<float>(ColorValue.a);
break;
case ReFractCommandValueType.Vector2:
((MemoryPacker)(ref packer)).Write<float>(Vector2Value.x);
((MemoryPacker)(ref packer)).Write<float>(Vector2Value.y);
break;
case ReFractCommandValueType.Vector4:
((MemoryPacker)(ref packer)).Write<float>(Vector4Value.x);
((MemoryPacker)(ref packer)).Write<float>(Vector4Value.y);
((MemoryPacker)(ref packer)).Write<float>(Vector4Value.z);
((MemoryPacker)(ref packer)).Write<float>(Vector4Value.w);
break;
case ReFractCommandValueType.String:
((MemoryPacker)(ref packer)).Write(StringValue);
break;
}
}
public override void Unpack(ref MemoryUnpacker unpacker)
{
((MemoryUnpacker)(ref unpacker)).Read<int>(ref RenderTextureId);
((MemoryUnpacker)(ref unpacker)).Read<bool>(ref IsRemoveAlphaCommand);
((MemoryUnpacker)(ref unpacker)).Read(ref CameraName);
((MemoryUnpacker)(ref unpacker)).Read(ref ComponentName);
((MemoryUnpacker)(ref unpacker)).Read(ref ParameterName);
((MemoryUnpacker)(ref unpacker)).Read<ReFractCommandValueType>(ref ValueType);
switch (ValueType)
{
case ReFractCommandValueType.Int:
((MemoryUnpacker)(ref unpacker)).Read<int>(ref IntValue);
break;
case ReFractCommandValueType.Float:
((MemoryUnpacker)(ref unpacker)).Read<float>(ref FloatValue);
break;
case ReFractCommandValueType.Bool:
((MemoryUnpacker)(ref unpacker)).Read<bool>(ref BoolValue);
break;
case ReFractCommandValueType.Color:
((MemoryUnpacker)(ref unpacker)).Read<float>(ref ColorValue.r);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref ColorValue.g);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref ColorValue.b);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref ColorValue.a);
break;
case ReFractCommandValueType.Vector2:
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector2Value.x);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector2Value.y);
break;
case ReFractCommandValueType.Vector4:
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector4Value.x);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector4Value.y);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector4Value.z);
((MemoryUnpacker)(ref unpacker)).Read<float>(ref Vector4Value.w);
break;
case ReFractCommandValueType.String:
((MemoryUnpacker)(ref unpacker)).Read(ref StringValue);
break;
}
}
}
internal class ReFractConfig
{
public readonly ConfigEntry<bool> debugLogging;
public readonly ConfigEntry<bool> forceRemoveAlpha;
public ReFractConfig(ConfigFile cfg)
{
cfg.SaveOnConfigSet = false;
debugLogging = cfg.Bind<bool>("General", "Debug logging", false, "Whether or not to print debug logging. This can make your log files grow incredibly quickly, only enable it if you really need it");
forceRemoveAlpha = cfg.Bind<bool>("General", "Always reset alpha channel", false, "By default, Re:Fract embeds the depth data of photos in the alpha channel. If you're using a camera without the option to disable that behavior, you can force it to happen here.");
ClearOrphanedEntries(cfg);
cfg.Save();
cfg.SaveOnConfigSet = true;
}
private static void ClearOrphanedEntries(ConfigFile cfg)
{
((Dictionary<ConfigDefinition, string>)AccessTools.Property(typeof(ConfigFile), "OrphanedEntries").GetValue(cfg)).Clear();
}
}
}
namespace ReFract.Unity
{
public static class Introspection
{
public delegate void RefAction<T1, T2>(ref T1 obj, T2 value);
public static Dictionary<Type, Dictionary<string, RefAction<object, object>>> _cachedSetters = new Dictionary<Type, Dictionary<string, RefAction<object, object>>>();
public static Dictionary<Type, Dictionary<string, Action<object, object>>> _cachedPropSetters = new Dictionary<Type, Dictionary<string, Action<object, object>>>();
private static void DoDebugLog(string input)
{
if (Plugin.BoundConfig.debugLogging.Value)
{
Debug.Log((object)input);
}
}
public static RefAction<object, object>? GetFieldSetter(Type obj, string fieldName, Func<Type, FieldInfo, ILGenerator, bool>? ilOverride = null)
{
try
{
return _cachedSetters[obj][fieldName];
}
catch
{
if (obj == null || fieldName == null || fieldName.Length == 0)
{
return null;
}
DoDebugLog("Introspection : Getting field");
FieldInfo field = obj.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
DoDebugLog("Introspection : Field is " + ((field == null) ? "null" : "not null"));
if (field == null)
{
return null;
}
DoDebugLog("Introspection : Field is " + field.Name);
RefAction<object, object> dynamicMethod = GetDynamicMethod(obj, field, ilOverride);
DoDebugLog("Introspection : Delegate is " + ((dynamicMethod == null) ? "null" : ("not null & " + dynamicMethod.GetType().ToString())));
if (dynamicMethod == null)
{
return null;
}
if (!_cachedSetters.ContainsKey(obj))
{
_cachedSetters.Add(obj, new Dictionary<string, RefAction<object, object>>());
}
_cachedSetters[obj].Add(fieldName, dynamicMethod);
DoDebugLog("Introspection : Added delegate to dictionary at " + obj.ToString() + "." + fieldName);
return dynamicMethod;
}
}
public static Action<object, object>? GetPropSetter(Type obj, string propName)
{
try
{
return _cachedPropSetters[obj][propName];
}
catch
{
if (obj == null || propName == null || propName.Length == 0)
{
return null;
}
DoDebugLog("Introspection : Getting property of " + obj.ToString() + " with name " + propName);
PropertyInfo property = obj.GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
DoDebugLog("Introspection : Property is " + ((property == null) ? "null" : "not null"));
if (property == null)
{
return null;
}
DoDebugLog("Introspection : Property is " + property.Name);
Action<object, object> dynamicPropMethod = GetDynamicPropMethod(obj, property);
DoDebugLog("Introspection : Delegate is " + ((dynamicPropMethod == null) ? "null" : ("not null & " + dynamicPropMethod.GetType().ToString())));
if (dynamicPropMethod == null)
{
return null;
}
if (!_cachedPropSetters.ContainsKey(obj))
{
_cachedPropSetters.Add(obj, new Dictionary<string, Action<object, object>>());
}
_cachedPropSetters[obj].Add(propName, dynamicPropMethod);
DoDebugLog("Introspection : Added delegate to dictionary at " + obj.ToString() + "." + propName);
return dynamicPropMethod;
}
}
public static RefAction<object, object> GetDynamicMethod(Type obj, FieldInfo field, Func<Type, FieldInfo, ILGenerator, bool>? ilOverride = null)
{
DynamicMethod dynamicMethod = new DynamicMethod("", null, new Type[2]
{
typeof(object).MakeByRefType(),
typeof(object)
}, restrictedSkipVisibility: true);
ILGenerator iLGenerator = dynamicMethod.GetILGenerator(256);
Label label = iLGenerator.DefineLabel();
iLGenerator.DefineLabel();
Label label2 = iLGenerator.DefineLabel();
Label label3 = iLGenerator.DefineLabel();
if (ilOverride == null || !ilOverride(obj, field, iLGenerator))
{
iLGenerator.Emit(OpCodes.Ldarg_1);
iLGenerator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("GetType"));
iLGenerator.Emit(OpCodes.Ldtoken, typeof(int));
iLGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
iLGenerator.Emit(OpCodes.Ceq);
iLGenerator.Emit(OpCodes.Brfalse, label2);
iLGenerator.Emit(OpCodes.Ldtoken, field.FieldType);
iLGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
iLGenerator.Emit(OpCodes.Call, typeof(Type).GetProperty("IsEnum").GetGetMethod());
iLGenerator.Emit(OpCodes.Brtrue, label3);
iLGenerator.MarkLabel(label2);
iLGenerator.Emit(OpCodes.Ldarg_1);
iLGenerator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("GetType"));
iLGenerator.Emit(OpCodes.Ldtoken, field.FieldType);
iLGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
iLGenerator.Emit(OpCodes.Ceq);
iLGenerator.Emit(OpCodes.Brfalse, label);
iLGenerator.MarkLabel(label3);
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldind_Ref);
iLGenerator.Emit(OpCodes.Castclass, obj);
iLGenerator.Emit(OpCodes.Ldarg_1);
iLGenerator.Emit(OpCodes.Unbox_Any, field.FieldType);
iLGenerator.Emit(OpCodes.Stfld, field);
iLGenerator.Emit(OpCodes.Ret);
iLGenerator.MarkLabel(label);
iLGenerator.Emit(OpCodes.Ldstr, $"[Re:Fract] Introspection : Wrong type for field \"{field.Name}\" which takes \"{field.FieldType}\"");
iLGenerator.Emit(OpCodes.Call, typeof(Debug).GetMethod("LogWarning", new Type[1] { typeof(string) }));
iLGenerator.Emit(OpCodes.Ret);
DoDebugLog("Introspection : Generated dynamic method with default IL");
}
DoDebugLog("Introspection : Creation of DynamicMethod was successful for " + obj.ToString() + "." + field.Name);
return (RefAction<object, object>)dynamicMethod.CreateDelegate(typeof(RefAction<, >).MakeGenericType(typeof(object), typeof(object)));
}
public static Action<object, object>? GetDynamicPropMethod(Type obj, PropertyInfo prop)
{
if (obj == null || prop == null || !prop.CanWrite)
{
return null;
}
MethodInfo setMethod = prop.GetSetMethod(nonPublic: true);
if (setMethod == null)
{
return null;
}
DynamicMethod dynamicMethod = new DynamicMethod("", null, new Type[2]
{
typeof(object),
typeof(object)
}, restrictedSkipVisibility: true);
ILGenerator iLGenerator = dynamicMethod.GetILGenerator(256);
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Castclass, obj);
iLGenerator.Emit(OpCodes.Ldarg_1);
iLGenerator.Emit(OpCodes.Unbox_Any, prop.PropertyType);
iLGenerator.Emit(OpCodes.Call, setMethod);
iLGenerator.Emit(OpCodes.Ret);
DoDebugLog("Introspection : Created delegate for property " + prop.Name);
return (Action<object, object>)dynamicMethod.CreateDelegate(typeof(Action<object, object>));
}
}
public class ReFractVolumeTracker : MonoBehaviour
{
public GameObject VolumeObject;
private void OnDestroy()
{
if ((Object)(object)VolumeObject != (Object)null)
{
Object.Destroy((Object)(object)VolumeObject);
return;
}
Transform val = ((Component)this).transform.Find("ReFract_Volume");
if ((Object)(object)val != (Object)null)
{
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
}
[BepInPlugin("dog.glacier.ReFractUnity", "Re:Fract // Reloaded (for Unity)", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(CameraRenderer), "Render")]
public static class CameraRenderer_Patch
{
private static FieldInfo _cameraField;
private static FieldInfo _camera360Field;
private static Camera FindSourceCamera(CameraRenderTask task)
{
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Invalid comparison between Unknown and I4
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Invalid comparison between Unknown and I4
//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)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor(task.position.x, task.position.y, task.position.z);
Quaternion val2 = default(Quaternion);
((Quaternion)(ref val2))..ctor(task.rotation.x, task.rotation.y, task.rotation.z, task.rotation.w);
Camera result = null;
float num = float.MaxValue;
foreach (List<Camera> value in _cameraCache.Values)
{
if (value == null)
{
continue;
}
foreach (Camera item in value)
{
if ((Object)(object)item == (Object)null)
{
continue;
}
if (item.orthographic)
{
if ((int)task.parameters.projection != 1 || Mathf.Abs(item.orthographicSize - task.parameters.orthographicSize) > 0.01f)
{
continue;
}
}
else if ((int)task.parameters.projection == 1 || (task.parameters.fov < 180f && Mathf.Abs(item.fieldOfView - task.parameters.fov) > 5f))
{
continue;
}
float num2 = Vector3.Distance(((Component)item).transform.position, val);
float num3 = Quaternion.Angle(((Component)item).transform.rotation, val2);
if (num2 < 2f && num3 < 15f && num2 < num)
{
num = num2;
result = item;
}
}
}
return result;
}
private static Camera GetCaptureCamera(CameraRenderTask task)
{
if (task.parameters.fov >= 180f)
{
if (_camera360Field == null)
{
_camera360Field = AccessTools.Field(typeof(CameraRenderer), "camera360");
}
object value = _camera360Field.GetValue(null);
if (value == null)
{
return null;
}
object? obj = AccessTools.Property(value.GetType(), "Camera")?.GetValue(value);
return (Camera)((obj is Camera) ? obj : null);
}
if (_cameraField == null)
{
_cameraField = AccessTools.Field(typeof(CameraRenderer), "camera");
}
object? value2 = _cameraField.GetValue(null);
return (Camera)((value2 is Camera) ? value2 : null);
}
[HarmonyPrefix]
public static void Prefix(CameraRenderTask task, out Camera __state)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
__state = null;
Camera captureCamera = GetCaptureCamera(task);
if ((Object)(object)captureCamera == (Object)null)
{
return;
}
Camera val = (__state = FindSourceCamera(task));
PostProcessVolume component = ((Component)captureCamera).gameObject.GetComponent<PostProcessVolume>();
Transform val2 = ((Component)captureCamera).transform.Find("ReFract_Volume");
PostProcessVolume val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<PostProcessVolume>() : null);
if ((Object)(object)val != (Object)null)
{
Debug.Log((object)$"[Re:Fract] Syncing PostProcess from '{((Object)val).GetInstanceID()}' to Capture Camera.");
PostProcessVolume componentInChildren = ((Component)val).GetComponentInChildren<PostProcessVolume>();
if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.profile != (Object)null)
{
int num = LayerMask.NameToLayer("Ignore Raycast");
if ((Object)(object)val3 == (Object)null)
{
GameObject val4 = new GameObject("ReFract_Volume");
val4.transform.SetParent(((Component)captureCamera).transform, false);
val4.layer = num;
val3 = val4.AddComponent<PostProcessVolume>();
BoxCollider obj = val4.AddComponent<BoxCollider>();
((Collider)obj).isTrigger = true;
obj.size = Vector3.one * 0.01f;
val3.isGlobal = false;
}
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
}
((Behaviour)val3).enabled = true;
PostProcessProfile val5 = Object.Instantiate<PostProcessProfile>(componentInChildren.profile);
MotionBlur setting = val5.GetSetting<MotionBlur>();
if ((Object)(object)setting != (Object)null)
{
((ParameterOverride<bool>)(object)((PostProcessEffectSettings)setting).enabled).value = false;
}
val3.profile = val5;
val3.weight = componentInChildren.weight;
PostProcessLayer component2 = ((Component)captureCamera).GetComponent<PostProcessLayer>();
if ((Object)(object)component2 != (Object)null)
{
component2.volumeLayer = LayerMask.op_Implicit(LayerMask.op_Implicit(component2.volumeLayer) | (1 << num));
component2.volumeTrigger = ((Component)captureCamera).transform;
}
}
}
else
{
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
}
if ((Object)(object)val3 != (Object)null)
{
((Behaviour)val3).enabled = false;
}
}
}
[HarmonyPostfix]
public static void Postfix(CameraRenderTask task, Camera __state)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__state == (Object)null || (Object)(object)__state.targetTexture == (Object)null || (!(_removeAlphaCameras.TryGetValue(((Object)__state.targetTexture).GetInstanceID(), out var value) && value) && !BoundConfig.forceRemoveAlpha.Value))
{
return;
}
try
{
Span<byte> span = RenderingManager.Instance.SharedMemory.AccessData<byte>(task.resultData);
int num = 3;
if (((object)(TextureFormat)(ref task.parameters.textureFormat)).ToString().IndexOf("ARGB", StringComparison.OrdinalIgnoreCase) >= 0)
{
num = 0;
}
for (int i = num; i < span.Length; i += 4)
{
span[i] = byte.MaxValue;
}
}
catch (Exception arg)
{
Debug.LogError((object)$"[Re:Fract] Failed to remove alpha: {arg}");
}
}
}
[CompilerGenerated]
private sealed class <WaitForCameraAndApply>d__15 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ReFractCommand command;
public Plugin <>4__this;
private int <i>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitForCameraAndApply>d__15(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
Plugin plugin = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<i>5__2 = 0;
break;
case 1:
<>1__state = -1;
<i>5__2++;
break;
}
if (<i>5__2 < 5)
{
<>2__current = null;
<>1__state = 1;
return true;
}
RenderTextureAsset asset = RenderingManager.Instance.RenderTextures.GetAsset(command.RenderTextureId);
if ((Object)(object)((asset != null) ? asset.Texture : null) == (Object)null)
{
return false;
}
if (command.IsRemoveAlphaCommand)
{
_removeAlphaCameras[((Object)asset.Texture).GetInstanceID()] = command.BoolValue;
}
List<Camera> list = FindCamerasRenderingTo(asset.Texture);
if (list.Count > 0)
{
_cameraCache[command.RenderTextureId] = list;
DoDebugLog($"[Re:Fract] Found {list.Count} cameras after waiting.");
foreach (Camera item in list)
{
plugin.EnsurePostProcessVolume(item);
if (!command.IsRemoveAlphaCommand)
{
plugin.ApplyCommand(item, command);
}
}
}
else
{
Debug.LogWarning((object)"[Re:Fract] ...still no camera found after waiting.");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private Messenger _msg;
private static readonly Dictionary<int, List<Camera>> _cameraCache = new Dictionary<int, List<Camera>>();
private static readonly Dictionary<int, bool> _removeAlphaCameras = new Dictionary<int, bool>();
private readonly ConcurrentQueue<Action> _mainThreadQueue = new ConcurrentQueue<Action>();
public static Dictionary<string, Type> TypeLookups = new Dictionary<string, Type>
{
{
"AmbientOcclusion",
typeof(AmbientOcclusion)
},
{
"AutoExposure",
typeof(AutoExposure)
},
{
"Bloom",
typeof(Bloom)
},
{
"ChromaticAberration",
typeof(ChromaticAberration)
},
{
"ColorGrading",
typeof(ColorGrading)
},
{
"DepthOfField",
typeof(DepthOfField)
},
{
"Grain",
typeof(Grain)
},
{
"LensDistortion",
typeof(LensDistortion)
},
{
"MotionBlur",
typeof(MotionBlur)
},
{
"ScreenSpaceReflections",
typeof(ScreenSpaceReflections)
},
{
"Vignette",
typeof(Vignette)
},
{
"AmplifyOcclusionBase",
typeof(AmplifyOcclusionBase)
}
};
internal static ReFractConfig BoundConfig { get; private set; } = null;
private void Awake()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
Debug.Log((object)"[Re:Fract] Binding configs");
BoundConfig = new ReFractConfig(((BaseUnityPlugin)this).Config);
Debug.Log((object)"[Re:Fract] Setting up interprocess");
_msg = new Messenger("dog.glacier.ReFract", new List<Type>(1) { typeof(ReFractCommand) }, (List<Type>)null);
_msg.ReceiveObject<ReFractCommand>("SetVariable", (Action<ReFractCommand>)HandleSetVariable);
BepInExExtensions.SyncConfigEntry<bool>(_msg, BoundConfig.debugLogging);
BepInExExtensions.SyncConfigEntry<bool>(_msg, BoundConfig.forceRemoveAlpha);
Debug.Log((object)"[Re:Fract] Running harmony patches!");
new Harmony("dog.glacier.ReFractUnity").PatchAll();
}
private void Update()
{
Action result;
while (_mainThreadQueue.TryDequeue(out result))
{
result();
}
}
private static void DoDebugLog(string input)
{
if (BoundConfig.debugLogging.Value)
{
Debug.Log((object)input);
}
}
private void HandleSetVariable(ReFractCommand command)
{
ReFractCommand command2 = command;
_mainThreadQueue.Enqueue(delegate
{
HandleSetVariableInternal(command2);
});
}
private void HandleSetVariableInternal(ReFractCommand command)
{
DoDebugLog($"[Re:Fract] Received command for RT ID: {command.RenderTextureId}");
if (command.RenderTextureId == 0)
{
Debug.LogWarning((object)"[Re:Fract] ERROR: Command has a zero RenderTextureId. Ignoring.");
return;
}
RenderTextureAsset asset = RenderingManager.Instance.RenderTextures.GetAsset(command.RenderTextureId);
if ((Object)(object)((asset != null) ? asset.Texture : null) != (Object)null && command.IsRemoveAlphaCommand)
{
int instanceID = ((Object)asset.Texture).GetInstanceID();
DoDebugLog($"[Re:Fract] Setting RemoveAlpha for Unity Texture {instanceID} (Resonite {command.RenderTextureId}) to {command.BoolValue}");
_removeAlphaCameras[instanceID] = command.BoolValue;
}
if (!_cameraCache.TryGetValue(command.RenderTextureId, out List<Camera> value) || value == null)
{
DoDebugLog($"[Re:Fract] Camera for {command.RenderTextureId} not in cache or is null. Searching...");
if ((Object)(object)((asset != null) ? asset.Texture : null) == (Object)null)
{
if (command.IsRemoveAlphaCommand)
{
((MonoBehaviour)this).StartCoroutine(WaitForCameraAndApply(command));
}
return;
}
DoDebugLog($"[Re:Fract] Found render texture asset for {command.RenderTextureId}");
value = FindCamerasRenderingTo(asset.Texture);
if (value.Count == 0)
{
Debug.LogWarning((object)"[Re:Fract] ...but no camera was found. Waiting a few frames...");
((MonoBehaviour)this).StartCoroutine(WaitForCameraAndApply(command));
return;
}
_cameraCache[command.RenderTextureId] = value;
DoDebugLog($"[Re:Fract] Found and cached {value.Count} cameras for ID {command.RenderTextureId}");
}
else
{
DoDebugLog($"[Re:Fract] Using cached cameras for ID {command.RenderTextureId}");
if (command.IsRemoveAlphaCommand && value.Count > 0 && (Object)(object)value[0].targetTexture != (Object)null)
{
_removeAlphaCameras[((Object)value[0].targetTexture).GetInstanceID()] = command.BoolValue;
}
}
value.RemoveAll((Camera c) => (Object)(object)c == (Object)null);
if (value.Count == 0)
{
Debug.LogWarning((object)$"[Re:Fract] ERROR: All cached cameras for {command.RenderTextureId} were destroyed. Removing from cache.");
if ((Object)(object)((asset != null) ? asset.Texture : null) != (Object)null)
{
_removeAlphaCameras.Remove(((Object)asset.Texture).GetInstanceID());
}
_cameraCache.Remove(command.RenderTextureId);
return;
}
foreach (Camera item in value)
{
EnsurePostProcessVolume(item);
if (!command.IsRemoveAlphaCommand)
{
ApplyCommand(item, command);
}
}
}
[IteratorStateMachine(typeof(<WaitForCameraAndApply>d__15))]
private IEnumerator WaitForCameraAndApply(ReFractCommand command)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitForCameraAndApply>d__15(0)
{
<>4__this = this,
command = command
};
}
private void EnsurePostProcessVolume(Camera camera)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_0326: Unknown result type (might be due to invalid IL or missing references)
ReFractVolumeTracker reFractVolumeTracker = ((Component)camera).gameObject.GetComponent<ReFractVolumeTracker>();
if ((Object)(object)reFractVolumeTracker == (Object)null)
{
reFractVolumeTracker = ((Component)camera).gameObject.AddComponent<ReFractVolumeTracker>();
}
int num = LayerMask.NameToLayer("Ignore Raycast");
PostProcessLayer component = ((Component)camera).gameObject.GetComponent<PostProcessLayer>();
if ((Object)(object)component != (Object)null)
{
component.volumeTrigger = ((Component)camera).transform;
int num2 = 1 << num;
if ((LayerMask.op_Implicit(component.volumeLayer) & num2) == 0)
{
DoDebugLog($"[Re:Fract] PostProcessLayer volumeLayer mask mismatch. Adding layer {num} (Ignore Raycast).");
component.volumeLayer = LayerMask.op_Implicit(LayerMask.op_Implicit(component.volumeLayer) | num2);
}
}
PostProcessVolume component2 = ((Component)camera).GetComponent<PostProcessVolume>();
if ((Object)(object)component2 != (Object)null)
{
Object.Destroy((Object)(object)component2);
}
BoxCollider component3 = ((Component)camera).GetComponent<BoxCollider>();
if ((Object)(object)component3 != (Object)null)
{
Object.Destroy((Object)(object)component3);
}
Transform val = ((Component)camera).transform.Find("ReFract_Volume");
if ((Object)(object)val == (Object)null)
{
GameObject val2 = new GameObject("ReFract_Volume");
val2.transform.SetParent(((Component)camera).transform, false);
val2.layer = num;
val = val2.transform;
}
reFractVolumeTracker.VolumeObject = ((Component)val).gameObject;
PostProcessVolume val3 = ((Component)val).GetComponent<PostProcessVolume>();
if ((Object)(object)val3 == (Object)null)
{
DoDebugLog("[Re:Fract] Creating PostProcessVolume on child of '" + ((Object)camera).name + "'.");
val3 = ((Component)val).gameObject.AddComponent<PostProcessVolume>();
}
val3.isGlobal = false;
if ((Object)(object)((Component)val).GetComponent<BoxCollider>() == (Object)null)
{
BoxCollider obj = ((Component)val).gameObject.AddComponent<BoxCollider>();
((Collider)obj).isTrigger = true;
obj.size = Vector3.one * 0.01f;
}
string text = $"ReFract_Profile_{((Object)camera).GetInstanceID()}";
if ((Object)(object)val3.profile == (Object)null)
{
DoDebugLog("[Re:Fract] PostProcessVolume on '" + ((Object)camera).name + "' has no profile. Creating one and adding all settings.");
PostProcessProfile val4 = ScriptableObject.CreateInstance<PostProcessProfile>();
((Object)val4).name = text;
val3.profile = val4;
foreach (Type value in TypeLookups.Values)
{
if (typeof(PostProcessEffectSettings).IsAssignableFrom(value))
{
DoDebugLog("[Re:Fract] Adding setting '" + value.Name + "' to new profile.");
val3.profile.AddSettings(value);
}
}
}
else if (((Object)val3.profile).name != text)
{
DoDebugLog("[Re:Fract] Ensuring unique profile for '" + ((Object)camera).name + "'.");
PostProcessProfile val5 = Object.Instantiate<PostProcessProfile>(val3.profile);
((Object)val5).name = text;
val3.profile = val5;
foreach (Type value2 in TypeLookups.Values)
{
if (typeof(PostProcessEffectSettings).IsAssignableFrom(value2) && !val5.HasSettings(value2))
{
val5.AddSettings(value2);
}
}
}
ColorGrading val6 = default(ColorGrading);
if (val3.profile.TryGetSettings<ColorGrading>(ref val6))
{
((ParameterOverride<GradingMode>)(object)val6.gradingMode).value = (GradingMode)1;
((ParameterOverride)val6.gradingMode).overrideState = true;
}
}
private void ApplyCommand(Camera camera, ReFractCommand command)
{
DoDebugLog("[Re:Fract] Searching for component '" + command.ComponentName + "' on camera '" + ((Object)camera).name + "'");
object obj = null;
if (!TypeLookups.TryGetValue(command.ComponentName, out Type value))
{
Debug.LogWarning((object)("[Re:Fract] Unsupported Type " + command.ComponentName));
return;
}
if (typeof(PostProcessEffectSettings).IsAssignableFrom(value))
{
PostProcessVolume componentInChildren = ((Component)camera).GetComponentInChildren<PostProcessVolume>();
if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.profile != (Object)null)
{
foreach (PostProcessEffectSettings setting in componentInChildren.profile.settings)
{
if (((object)setting).GetType() == value)
{
obj = setting;
break;
}
}
if (obj == null)
{
obj = componentInChildren.profile.AddSettings(value);
}
}
}
else
{
obj = ((Component)camera).GetComponent(value);
}
if (obj == null)
{
Debug.LogWarning((object)("[Re:Fract] ERROR: Camera '" + ((Object)camera).name + "' does not have or could not create component '" + command.ComponentName + "'"));
return;
}
DoDebugLog("[Re:Fract] Found target '" + command.ComponentName + "'");
object valueFromCommand = GetValueFromCommand(command);
Type type = obj.GetType();
if (command.ParameterName.EndsWith("!"))
{
string text = command.ParameterName.Substring(0, command.ParameterName.Length - 1);
DoDebugLog($"[Re:Fract] Attempting to set property '{text}' on '{command.ComponentName} ({type.FullName})' to value '{valueFromCommand}'");
Action<object, object> propSetter = Introspection.GetPropSetter(type, text);
if (propSetter != null)
{
propSetter(obj, valueFromCommand);
DoDebugLog("[Re:Fract] SUCCESS: Set property '" + text + "'.");
return;
}
Debug.LogWarning((object)("[Re:Fract] ERROR: Could not find writable property '" + text + "' on component '" + command.ComponentName + "'"));
return;
}
DoDebugLog($"[Re:Fract] Attempting to set '{command.ParameterName}' on '{command.ComponentName} ({type.FullName})' to value '{valueFromCommand}'");
FieldInfo field = type.GetField(command.ParameterName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && typeof(ParameterOverride).IsAssignableFrom(field.FieldType))
{
object value2 = field.GetValue(obj);
if (value2 != null)
{
Type type2 = value2.GetType();
bool flag = false;
FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.Public);
if (field2 != null)
{
try
{
field2.SetValue(value2, valueFromCommand);
DoDebugLog("[Re:Fract] Set 'value' field on ParameterOverride '" + command.ParameterName + "'.");
flag = true;
}
catch (Exception arg)
{
Debug.LogWarning((object)$"[Re:Fract] Failed to set ParameterOverride field value: {arg}");
}
}
if (!flag)
{
PropertyInfo property = type2.GetProperty("value");
if (property != null && property.CanWrite)
{
try
{
property.SetValue(value2, valueFromCommand);
DoDebugLog("[Re:Fract] Set 'value' property on ParameterOverride '" + command.ParameterName + "'.");
flag = true;
}
catch (Exception arg2)
{
Debug.LogWarning((object)$"[Re:Fract] Failed to set ParameterOverride property value: {arg2}");
}
}
}
if (flag)
{
FieldInfo field3 = type2.GetField("overrideState", BindingFlags.Instance | BindingFlags.Public);
if (field3 != null)
{
field3.SetValue(value2, true);
DoDebugLog("[Re:Fract] SUCCESS: Activated override for '" + command.ParameterName + "'.");
}
else
{
Debug.LogWarning((object)("[Re:Fract] Could not find 'overrideState' field on '" + type2.Name + "'. The setting may not apply visually."));
}
return;
}
}
}
Action<object, object> propSetter2 = Introspection.GetPropSetter(type, command.ParameterName);
if (propSetter2 != null)
{
propSetter2(obj, valueFromCommand);
DoDebugLog("[Re:Fract] SUCCESS: Set property '" + command.ParameterName + "'.");
return;
}
Introspection.RefAction<object, object> fieldSetter = Introspection.GetFieldSetter(type, command.ParameterName);
if (fieldSetter != null)
{
fieldSetter(ref obj, valueFromCommand);
DoDebugLog("[Re:Fract] SUCCESS: Set field '" + command.ParameterName + "'.");
return;
}
Debug.LogWarning((object)("[Re:Fract] ERROR: Could not find writable property or field '" + command.ParameterName + "' on component '" + command.ComponentName + "'"));
}
private static object GetValueFromCommand(ReFractCommand command)
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
return command.ValueType switch
{
ReFractCommandValueType.Int => command.IntValue,
ReFractCommandValueType.Float => command.FloatValue,
ReFractCommandValueType.Bool => command.BoolValue,
ReFractCommandValueType.Color => (object)new Color(command.ColorValue.r, command.ColorValue.g, command.ColorValue.b, command.ColorValue.a),
ReFractCommandValueType.Vector2 => (object)new Vector2(command.Vector2Value.x, command.Vector2Value.y),
ReFractCommandValueType.Vector4 => (object)new Vector4(command.Vector4Value.x, command.Vector4Value.y, command.Vector4Value.z, command.Vector4Value.w),
ReFractCommandValueType.String => command.StringValue,
_ => throw new ArgumentOutOfRangeException(),
};
}
private static List<Camera> FindCamerasRenderingTo(RenderTexture target)
{
DoDebugLog(string.Format("[Re:Fract] Searching for RenderTexture {0} @ {1}", Object.op_Implicit((Object)(object)target) ? ((Object)target).name : "NULL TARGET", Object.op_Implicit((Object)(object)target) ? ((object)((Object)target).GetInstanceID()) : "N/A"));
Camera[] array = Object.FindObjectsOfType<Camera>();
List<Camera> list = new List<Camera>();
Camera[] array2 = array;
foreach (Camera val in array2)
{
DoDebugLog(string.Format("[Re:Fract] Camera {0} @ {1} --> {2} @ {3}...", ((Object)val).name, ((Object)val).GetInstanceID(), Object.op_Implicit((Object)(object)val.targetTexture) ? ((Object)val.targetTexture).name : "NULL TARGET", Object.op_Implicit((Object)(object)val.targetTexture) ? ((object)((Object)val.targetTexture).GetInstanceID()) : "N/A"));
if ((Object)(object)val.targetTexture == (Object)(object)target)
{
list.Add(val);
}
}
if (list.Count == 0)
{
Debug.LogWarning((object)"[Re:Fract] No camera found rendering to the specified RenderTexture.");
}
return list;
}
}
}