You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

220 lines
11 KiB

using System;
using System.Linq.Expressions;
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace UnityEditor.Rendering
{
internal static class TextureParameterHelper
{
static readonly Type k_ObjectFieldValidator = Type.GetType("UnityEditor.EditorGUI+ObjectFieldValidator,UnityEditor");
internal static Func<Object[], Type, SerializedProperty, int, Object> ValidateObjectFieldAssignment;
static Func<Rect, Rect, int, Object, Object, Type, Type, SerializedProperty, Delegate, bool, GUIStyle, Object> k_DoObjectField;
internal delegate Object ObjectFieldValidator(Object[] references, Type objType, SerializedProperty property, int options);
static TextureParameterHelper()
{
Type ObjectFieldValidatorOptions_Type = Type.GetType("UnityEditor.EditorGUI+ObjectFieldValidatorOptions,UnityEditor");
var typeParameter = Expression.Parameter(typeof(Type), "type");
var propertyParameter = Expression.Parameter(typeof(SerializedProperty), "property");
var intParameter = Expression.Parameter(typeof(int), "int");
// ValidateObjectFieldAssignment
MethodInfo validateObjectFieldAssignment_Info = Type.GetType("UnityEditor.EditorGUI,UnityEditor").GetMethod("ValidateObjectFieldAssignment", BindingFlags.Static | BindingFlags.NonPublic);
var referencesParameter = Expression.Parameter(typeof(Object[]), "references");
var optionsVariable = Expression.Parameter(ObjectFieldValidatorOptions_Type, "options");
var validateObjectFieldAssignment_Block = Expression.Block(
new[] { optionsVariable },
Expression.Assign(optionsVariable, Expression.Convert(intParameter, ObjectFieldValidatorOptions_Type)),
Expression.Call(validateObjectFieldAssignment_Info, referencesParameter, typeParameter, propertyParameter, optionsVariable)
);
var validateObjectFieldAssignment_Lambda = Expression.Lambda<Func<Object[], Type, SerializedProperty, int, Object>>(
validateObjectFieldAssignment_Block, referencesParameter, typeParameter, propertyParameter, intParameter);
ValidateObjectFieldAssignment = validateObjectFieldAssignment_Lambda.Compile();
// ObjectField
MethodInfo doObjectField_Info = Type.GetType("UnityEditor.EditorGUI,UnityEditor").GetMethod("DoObjectField", BindingFlags.Static | BindingFlags.NonPublic, null,
new Type[] { typeof(Rect), typeof(Rect), typeof(int), typeof(Object), typeof(Object), typeof(Type), typeof(Type), typeof(SerializedProperty), k_ObjectFieldValidator, typeof(bool), typeof(GUIStyle) }, null);
var positionParameter = Expression.Parameter(typeof(Rect), "position");
var rectParameter = Expression.Parameter(typeof(Rect), "rect");
var objectParameter = Expression.Parameter(typeof(Object), "object");
var unusedParameter = Expression.Parameter(typeof(Object), "unused");
var type2Parameter = Expression.Parameter(typeof(Type), "type2");
var boolParameter = Expression.Parameter(typeof(bool), "allowSceneObject");
var styleParameter = Expression.Parameter(typeof(GUIStyle), "style");
var validatorParameter = Expression.Parameter(typeof(Delegate), "validator");
var validatorVariable = Expression.Parameter(k_ObjectFieldValidator, "validator");
var doObjectField_Block = Expression.Block(
new[] { validatorVariable },
Expression.Assign(validatorVariable, Expression.Convert(validatorParameter, k_ObjectFieldValidator)),
Expression.Call(doObjectField_Info, positionParameter, rectParameter, intParameter, objectParameter, unusedParameter, typeParameter, type2Parameter, propertyParameter, validatorVariable, boolParameter, styleParameter)
);
var doObjectField_Lambda = Expression.Lambda<Func<Rect, Rect, int, Object, Object, Type, Type, SerializedProperty, Delegate, bool, GUIStyle, Object>>(
doObjectField_Block, positionParameter, rectParameter, intParameter, objectParameter, unusedParameter, typeParameter, type2Parameter, propertyParameter, validatorParameter, boolParameter, styleParameter);
k_DoObjectField = doObjectField_Lambda.Compile();
}
internal static Delegate CastValidator(ObjectFieldValidator validator)
{
return DelegateUtility.Cast(validator, k_ObjectFieldValidator);
}
internal static void DoObjectField(SerializedProperty property, GUIContent label, Type type1, Type type2, Delegate validator)
{
Rect r = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);
DoObjectField(r, property, label, type1, type2, validator);
}
internal static void DoObjectField(Rect r, SerializedProperty property, GUIContent label, Type type1, Type type2, Delegate validator)
{
int id = GUIUtility.GetControlID(FocusType.Keyboard, r);
r = EditorGUI.PrefixLabel(r, id, label);
k_DoObjectField(r, r, id, null, null, type1, type2, property, validator, false, EditorStyles.objectField);
}
internal const float kIndentPerLevel = 15;
internal static void GetRectsForMiniThumbnailField(Rect position, out Rect thumbRect, out Rect labelRect)
{
float x = EditorGUI.indentLevel * kIndentPerLevel;
thumbRect = new Rect(position.x + x, position.y, 32f, 18f);
float labelStartX = thumbRect.x + 2 * kIndentPerLevel; // label aligns with indent levels for being able to have the following labels align with this label
labelRect = new Rect(labelStartX, position.y, thumbRect.x + EditorGUIUtility.labelWidth - labelStartX, position.height);
}
internal static void MiniThumbnail(Rect r, SerializedProperty property, GUIContent label, Type type)
{
EditorGUI.BeginProperty(r, label, property);
GetRectsForMiniThumbnailField(r, out var thumbRect, out var labelRect);
EditorGUI.HandlePrefixLabel(r, labelRect, label, 0, EditorStyles.label);
EditorGUI.BeginChangeCheck();
int controlID = GUIUtility.GetControlID(12354, FocusType.Keyboard, r);
var value = k_DoObjectField(thumbRect, thumbRect, controlID, property.objectReferenceValue, null, type, typeof(RenderTexture), null, null, false, EditorStyles.objectField);
if (EditorGUI.EndChangeCheck())
property.objectReferenceValue = value;
EditorGUI.EndProperty();
}
}
[VolumeParameterDrawer(typeof(TextureParameter))]
sealed class TextureParameterDrawer : VolumeParameterDrawer
{
internal static bool HasGenuineNullSelection(Object[] references)
{
bool genuineNullSelection = true;
for (int i = 0; i < references.Length; ++i)
{
genuineNullSelection &= (references[i] == null);
}
return genuineNullSelection;
}
static Delegate validator = TextureParameterHelper.CastValidator((Object[] references, Type objType, SerializedProperty property, int options) =>
{
if (HasGenuineNullSelection(references)) return null;
// Accept RenderTextures of correct dimensions
Texture validated = (RenderTexture)TextureParameterHelper.ValidateObjectFieldAssignment(references, typeof(RenderTexture), property, options);
if (validated != null)
{
if (objType == typeof(Texture2D) && validated.dimension != TextureDimension.Tex2D) validated = null;
if (objType == typeof(Texture3D) && validated.dimension != TextureDimension.Tex3D) validated = null;
if (objType == typeof(Cubemap) && validated.dimension != TextureDimension.Cube) validated = null;
}
// Accept textures of correct type
if (validated == null)
validated = (Texture)TextureParameterHelper.ValidateObjectFieldAssignment(references, objType, property, options);
return validated ? validated : property.objectReferenceValue;
});
internal static bool TextureField(SerializedProperty property, GUIContent title, TextureDimension dimension)
{
if (property.propertyType != SerializedPropertyType.ObjectReference)
return false;
var rect = EditorGUILayout.GetControlRect();
EditorGUI.BeginProperty(rect, title, property);
switch (dimension)
{
case TextureDimension.Tex2D:
TextureParameterHelper.DoObjectField(rect, property, title, typeof(Texture2D), typeof(RenderTexture), validator);
break;
case TextureDimension.Tex3D:
TextureParameterHelper.DoObjectField(rect, property, title, typeof(Texture3D), typeof(RenderTexture), validator);
break;
case TextureDimension.Cube:
TextureParameterHelper.DoObjectField(rect, property, title, typeof(Cubemap), typeof(RenderTexture), validator);
break;
default:
EditorGUI.PropertyField(rect, property, title);
break;
}
EditorGUI.EndProperty();
return true;
}
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
var value = parameter.value;
var dimension = parameter.GetObjectRef<TextureParameter>().dimension;
return TextureField(value, title, dimension);
}
}
[VolumeParameterDrawer(typeof(Texture2DParameter))]
sealed class Texture2DParameterDrawer : VolumeParameterDrawer
{
/// <summary>Draws the parameter in the editor.</summary>
/// <param name="parameter">The parameter to draw.</param>
/// <param name="title">The label and tooltip of the parameter.</param>
/// <returns><c>true</c> if the input parameter is valid, <c>false</c> otherwise</returns>
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
return TextureParameterDrawer.TextureField(parameter.value, title, TextureDimension.Tex2D);
}
}
[VolumeParameterDrawer(typeof(Texture3DParameter))]
sealed class Texture3DParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
return TextureParameterDrawer.TextureField(parameter.value, title, TextureDimension.Tex3D);
}
}
[VolumeParameterDrawer(typeof(CubemapParameter))]
sealed class CubemapParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
return TextureParameterDrawer.TextureField(parameter.value, title, TextureDimension.Cube);
}
}
[VolumeParameterDrawer(typeof(NoInterpCubemapParameter))]
sealed class NoInterpCubemapParameterDrawer : VolumeParameterDrawer
{
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title)
{
return TextureParameterDrawer.TextureField(parameter.value, title, TextureDimension.Cube);
}
}
}