using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Newtonsoft.Json.Serialization;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
using Object = UnityEngine.Object;
namespace Needle.Engine
{
///
/// Add to FileReference field to specify the allowed type and extensions
///
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class)]
public class FileReferenceTypeAttribute : Attribute
{
public readonly Type AllowedType;
/** File types that aren't allowed to be assigned */
public readonly Type[] ExcludedTypes;
public readonly string[] AllowedExtensions;
public FileReferenceTypeAttribute()
{
}
public FileReferenceTypeAttribute(Type type = null, params string[] allowedExtensions)
{
this.AllowedType = type;
this.AllowedExtensions = allowedExtensions;
}
public FileReferenceTypeAttribute(Type type = null, Type[] excludedTypes = null, params string[] allowedExtensions)
{
this.AllowedType = type;
this.AllowedExtensions = allowedExtensions;
this.ExcludedTypes = excludedTypes;
}
}
///
/// Add the FileReferenceType attribute to specify the allowed type and extensions
///
[Serializable]
public class FileReference
{
public enum FileReferenceMode {
Object = 0,
Path = 1,
}
public FileReferenceMode Mode = FileReferenceMode.Object;
[FormerlySerializedAs("Texture")]
public Object File;
public string String;
}
// TODO: should we also exclude Texture3D here?
[Serializable, FileReferenceType(typeof(Texture), new[]{typeof(RenderTexture)})]
public class ImageReference : FileReference
{
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(FileReference), true)]
[CustomPropertyDrawer(typeof(ImageReference), true)]
public class FileReferenceDrawer : PropertyDrawer
{
private static readonly Dictionary> cachedAttributes =
new Dictionary>();
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (cachedAttributes.TryGetValue(property, out var list))
{
if (TryValidateCustomAttributes(list, position, property, label, true))
return;
}
else
{
if (TryValidateCustomAttributes(fieldInfo.GetCustomAttributes(typeof(FileReferenceTypeAttribute)),
position, property, label))
return;
if (TryValidateCustomAttributes(fieldInfo.FieldType.GetCustomAttributes(), position, property, label))
return;
}
var mode = property.FindPropertyRelative(nameof(FileReference.Mode));
var modeRect = new Rect(position);
modeRect.width = 60;
position.width -= modeRect.width;
modeRect.x = position.x + position.width;
EditorGUI.PropertyField(modeRect, mode, GUIContent.none);
switch ((FileReference.FileReferenceMode)mode.intValue)
{
case FileReference.FileReferenceMode.Object:
EditorGUI.PropertyField(position, property.FindPropertyRelative(nameof(FileReference.File)), label);
break;
case FileReference.FileReferenceMode.Path:
EditorGUI.PropertyField(position, property.FindPropertyRelative(nameof(FileReference.String)), label);
break;
}
}
private static bool TryValidateCustomAttributes(
IEnumerable