diff --git a/ReFract.cs b/ReFract.cs index 11d50fe..8009904 100644 --- a/ReFract.cs +++ b/ReFract.cs @@ -2,16 +2,14 @@ using NeosModLoader; using FrooxEngine; using BaseX; -using CodeX; using UnityEngine; using Camera = FrooxEngine.Camera; using Component = FrooxEngine.Component; using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; +using System.Text; using System.Reflection; using UnityEngine.Rendering.PostProcessing; using System.Reflection.Emit; -using System.Collections.Generic; using UnityNeos; namespace ReFract; @@ -24,6 +22,7 @@ public class ReFract : NeosMod public static string DynVarCamKeyString => "Re.Fract_Camera_"; public static string ReFractTag => "Re:FractCameraSpace"; public static Dictionary TypeLookups = new Dictionary(); + public static Type[] SupportedTypes = new Type[] { typeof(bool), typeof(int), typeof(float), typeof(float2), typeof(float3), typeof(float4), typeof(color) }; // This is an override for Introspection - which generates accessor delegates for fields because reflection is slow and I hate it. // Specifically so it can handle Unity's ParameterOverride types. @@ -112,8 +111,54 @@ public override void OnEngineInit() } TypeLookups.Add("AmplifyOcclusionBase", typeof(AmplifyOcclusionBase)); // Include this specifically since it does post processing, but is not part of the bundle stack // TypeLookups will be used to easily get a type from one specified in a dynamic variable name string - + harmony.PatchAll(); + + // Optional code for generating a supported types list + + // StringBuilder sb = new StringBuilder(); + // Func GetTrueFieldType = (type) => { + // if (type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(ParameterOverride<>)) + // { + // return type.BaseType.GetGenericArguments()[0]; + // } + // Msg($"Re:Fract : Type \"{type.Name}\" ({type.BaseType}) is not a ParameterOverride type!"); + // return type; + // }; + + // foreach (Type t in TypeLookups.Values) + // { + // sb.AppendLine($"## {t.Name}:"); + // FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public); + // PropertyInfo[] props = t.GetProperties(BindingFlags.Instance | BindingFlags.Public); + // sb.AppendLine("### Fields"); + // foreach (PropertyInfo prop in props) + // { + // if (prop.CanWrite && prop.CanRead && prop.Name == "enabled") + // { + // sb.AppendLine($"- {prop.Name}! ({prop.PropertyType.Name})"); + // } + // } + // foreach (FieldInfo field in fields) + // { + // if ((SupportedTypes.Contains(GetTrueFieldType(field.FieldType)) || GetTrueFieldType(field.FieldType).IsEnum) && field.Name != "active") + // { + // sb.Append($"- {field.Name} ({(GetTrueFieldType(field.FieldType).IsEnum ? "Int32" : GetTrueFieldType(field.FieldType).Name)})"); + // if (GetTrueFieldType(field.FieldType).IsEnum) + // { + // sb.Append($" - Enum values: "); + // foreach (object val in Enum.GetValues(GetTrueFieldType(field.FieldType))) + // { + // sb.Append($"{val.ToString()} ({(int)val}), "); + // } + // } + // sb.AppendLine(); + // } + // } + // sb.AppendLine(); + // } + + // File.WriteAllText("ReFract_TypeLookups.txt", sb.ToString()); } [HarmonyPatch] public class DynamicVariableBase_Patch diff --git a/Usage.md b/Usage.md new file mode 100644 index 0000000..2649332 --- /dev/null +++ b/Usage.md @@ -0,0 +1,43 @@ +# Proper usage of Re:Fract + +## For a list of effects you can modify, please see: [Variables.md](Variables.md) + +## How do I start editing a camera? + +Easy! Simply create a DynamicVariableSpace and add a DynamicReferenceVariable of type `Camera` in it somewhere, then drop in the camera you wish to modify. Since they're dynamic variables, they needn't be on the same slot. + +Next, you'll need to name your camera something special so Re:Fract can pick up on it. +To mark a camera, simply change the variable name to something such as the following: `Re.Fract_Camera_MyCameraNameHere` + +This will mark your camera with whatever name you choose to replace "MyCameraNameHere" with. + +[Image Here] + +## How do I edit a post processing effect on a camera? + +The process for modifying a variable on the camera is also fairly straightforward. + +To actually modify a variable, you'll want to create a DynamicValueVariable with a type that corresponds to the type of whatever parameter it is you're editing on a given post processing effect - except in the case of it being an enum, which you'll always use an int for. + +The naming scheme for value variables follows this setup: `Re.Fract_MyCameraNameHere_EffectNameHere_FieldOrPropertyNameHere` + +So for example, if I wanted to enable or disable the bloom, I would use: `Re.Fract_MyCameraNameHere_Bloom_enabled` as the variable name on a `DynamicValueVariable` of type `bool`. +And similarly, if I wanted to change the bloom intensity I would set up a `DynamicValueVariable` of type `float` and set its name to `Re.Fract_MyCameraNameHere_Bloom_intensity`. + +You can see some examples of what this looks like in-game with the following screenshot showing a setup for the `DepthOfField` effect. + +Note that when you first create a variable and set its name, the effect does not automatically update on the camera, simply update the value in the variable to apply any changes. + +[Image here] + + +## Supplementary Information + +Some effects (Currently just AmplifyOcclusionBase and whatever future ones that are potentially exposed) have a special property you need to set to enable or disable them. +You can reference actual properties by simply appending an exclaimation mark to the end of the field name. Example `Re.Fract_MyCameraNameHere_AmplifyOcclusionBase_enabled!` + +As stated above, since these are all dynamic variables none of them need to be on the same slot as the camera, they just need to be anywhere within a dynamic variable space. They can be driven, written to, or otherwise manipulated as any normal variable can. I recommend not having duplicate value-holding variables (DynamicValueVariables or DynamicFields for example) as that will create duplicate work. Each variable you add will modify the post processing effect, so make sure you only use one per effect parameter. + +Also since you can define camera names, you can manipulate multiple cameras within a single variable space by simply substituting `MyCameraNameHere` with multiple different names and camera/value variables that reference that name. +For instance, if I have variables that are called `Re.Fract_Camera_MyCamera1` and `re.Fract_Camera_MyCamera2`, you can - for example - change the bloom separately for each camera by making dynamic variables that are named `Re.Fract_MyCamera1_Bloom_enabled` and `Re.Fract_MyCamera2_Bloom_enabled` and so on. + diff --git a/Variables.md b/Variables.md new file mode 100644 index 0000000..e8db95b --- /dev/null +++ b/Variables.md @@ -0,0 +1,152 @@ +## AmbientOcclusion: +### Fields +- mode (Int32) - Enum values: ScalableAmbientObscurance (0), MultiScaleVolumetricObscurance (1), +- intensity (Single) +- ambientOnly (Boolean) +- noiseFilterTolerance (Single) +- blurTolerance (Single) +- upsampleTolerance (Single) +- thicknessModifier (Single) +- directLightingStrength (Single) +- radius (Single) +- quality (Int32) - Enum values: Lowest (0), Low (1), Medium (2), High (3), Ultra (4), +- enabled (Boolean) + +## AutoExposure: +### Fields +- minLuminance (Single) +- maxLuminance (Single) +- keyValue (Single) +- eyeAdaptation (Int32) - Enum values: Progressive (0), Fixed (1), +- speedUp (Single) +- speedDown (Single) +- enabled (Boolean) + +## Bloom: +### Fields +- intensity (Single) +- threshold (Single) +- softKnee (Single) +- clamp (Single) +- diffusion (Single) +- anamorphicRatio (Single) +- fastMode (Boolean) +- dirtIntensity (Single) +- enabled (Boolean) + +## ChromaticAberration: +### Fields +- intensity (Single) +- fastMode (Boolean) +- enabled (Boolean) + +## ColorGrading: +### Fields +- gradingMode (Int32) - Enum values: LowDefinitionRange (0), HighDefinitionRange (1), External (2), +- tonemapper (Int32) - Enum values: None (0), Neutral (1), ACES (2), Custom (3), +- toneCurveToeStrength (Single) +- toneCurveToeLength (Single) +- toneCurveShoulderStrength (Single) +- toneCurveShoulderLength (Single) +- toneCurveShoulderAngle (Single) +- toneCurveGamma (Single) +- ldrLutContribution (Single) +- temperature (Single) +- tint (Single) +- hueShift (Single) +- saturation (Single) +- brightness (Single) +- postExposure (Single) +- contrast (Single) +- mixerRedOutRedIn (Single) +- mixerRedOutGreenIn (Single) +- mixerRedOutBlueIn (Single) +- mixerGreenOutRedIn (Single) +- mixerGreenOutGreenIn (Single) +- mixerGreenOutBlueIn (Single) +- mixerBlueOutRedIn (Single) +- mixerBlueOutGreenIn (Single) +- mixerBlueOutBlueIn (Single) +- enabled (Boolean) + +## DepthOfField: +### Fields +- focusDistance (Single) +- aperture (Single) +- focalLength (Single) +- kernelSize (Int32) - Enum values: Small (0), Medium (1), Large (2), VeryLarge (3), +- enabled (Boolean) + +## Grain: +### Fields +- colored (Boolean) +- intensity (Single) +- size (Single) +- lumContrib (Single) +- enabled (Boolean) + +## LensDistortion: +### Fields +- intensity (Single) +- intensityX (Single) +- intensityY (Single) +- centerX (Single) +- centerY (Single) +- scale (Single) +- enabled (Boolean) + +## MotionBlur: +### Fields +- shutterAngle (Single) +- sampleCount (Int32) +- enabled (Boolean) + +## ScreenSpaceReflections: +### Fields +- preset (Int32) - Enum values: Lower (0), Low (1), Medium (2), High (3), Higher (4), Ultra (5), Overkill (6), Custom (7), +- maximumIterationCount (Int32) +- resolution (Int32) - Enum values: Downsampled (0), FullSize (1), Supersampled (2), +- thickness (Single) +- maximumMarchDistance (Single) +- distanceFade (Single) +- vignette (Single) +- enabled (Boolean) + +## Vignette: +### Fields +- mode (Int32) - Enum values: Classic (0), Masked (1), +- intensity (Single) +- smoothness (Single) +- roundness (Single) +- rounded (Boolean) +- opacity (Single) +- enabled (Boolean) + +## AmplifyOcclusionBase: +### Fields +- enabled! (Boolean) +- ApplyMethod (Int32) - Enum values: PostEffect (0), Deferred (1), Debug (2), +- SampleCount (Int32) - Enum values: Low (0), Medium (1), High (2), VeryHigh (3), +- PerPixelNormals (Int32) - Enum values: None (0), Camera (1), GBuffer (2), GBufferOctaEncoded (3), +- Intensity (Single) +- Radius (Single) +- PowerExponent (Single) +- Bias (Single) +- Thickness (Single) +- Downsample (Boolean) +- CacheAware (Boolean) +- FadeEnabled (Boolean) +- FadeStart (Single) +- FadeLength (Single) +- FadeToIntensity (Single) +- FadeToRadius (Single) +- FadeToPowerExponent (Single) +- FadeToThickness (Single) +- BlurEnabled (Boolean) +- BlurRadius (Int32) +- BlurPasses (Int32) +- BlurSharpness (Single) +- FilterEnabled (Boolean) +- FilterBlending (Single) +- FilterResponse (Single) +