Skip to content

Instantly share code, notes, and snippets.

@zudl
Created March 5, 2020 10:10
Show Gist options
  • Save zudl/c79f0ca84e79f8ece3b4bf9d11c7176c to your computer and use it in GitHub Desktop.
Save zudl/c79f0ca84e79f8ece3b4bf9d11c7176c to your computer and use it in GitHub Desktop.
#if UNITY_EDITOR && ODIN_INSPECTOR
using System;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEngine.AddressableAssets;
using Sirenix.Utilities.Editor;
using UnityEngine;
#if ODIN_VALIDATOR
using System.Reflection;
using Sirenix.OdinInspector.Editor.Validation;
using Utils.OdinInspector;
[assembly: RegisterValidator(typeof(RequiredAssetReferenceValidator<>))]
#endif
namespace Utils.OdinInspector {
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class RequiredAssetReferenceAttribute : Attribute {
public string ErrorMessage = "AssetReference is required!";
public InfoMessageType MessageType;
public RequiredAssetReferenceAttribute() => this.MessageType = InfoMessageType.Error;
public RequiredAssetReferenceAttribute(string errorMessage, InfoMessageType messageType) {
this.ErrorMessage = errorMessage;
this.MessageType = messageType;
}
public RequiredAssetReferenceAttribute(string errorMessage) {
this.ErrorMessage = errorMessage;
this.MessageType = InfoMessageType.Error;
}
public RequiredAssetReferenceAttribute(InfoMessageType messageType) => this.MessageType = messageType;
}
public sealed class RequiredAttributeForAssetReferenceDrawer<T> : OdinAttributeDrawer<RequiredAttribute, T> {
protected override void DrawPropertyLayout(GUIContent label) {
var valueType = this.ValueEntry.TypeOfValue;
if (typeof(AssetReference).IsAssignableFrom(valueType))
SirenixEditorGUI.ErrorMessageBox("[Required] is not suitable for AssetReference, please use [RequiredAssetReference]");
this.CallNextDrawer(label);
}
}
#if !ODIN_VALIDATOR
public sealed class RequiredAssetReferenceAttributeDrawer<T> : OdinAttributeDrawer<RequiredAssetReferenceAttribute, T> where T : AssetReference {
protected override void DrawPropertyLayout(GUIContent label) {
if (ValueEntry.SmartValue.RuntimeKeyIsValid() == false) {
if (Attribute.MessageType == InfoMessageType.Error)
SirenixEditorGUI.ErrorMessageBox(Attribute.ErrorMessage);
else if (Attribute.MessageType == InfoMessageType.Warning)
SirenixEditorGUI.WarningMessageBox(Attribute.ErrorMessage);
else if (Attribute.MessageType == InfoMessageType.Info)
SirenixEditorGUI.InfoMessageBox(Attribute.ErrorMessage);
}
try {
this.CallNextDrawer(label);
}
catch (ArgumentException aex) {
// When deleting valid asset reference:
// ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint
// So lets hack
if (aex.Message.StartsWith("Getting control") == false)
throw aex;
}
}
}
#else
/// <summary>
/// Validator and ErrorBox drawer
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class RequiredAssetReferenceValidator<T> : AttributeValidator<RequiredAssetReferenceAttribute, T> where T : AssetReference {
protected override void Validate(object parentInstance, T memberValue, MemberInfo member, ValidationResult result) {
if (memberValue.RuntimeKeyIsValid()) {
result.ResultType = ValidationResultType.Valid;
}
else if (Attribute.MessageType != InfoMessageType.Info) {
result.ResultType = Attribute.MessageType == InfoMessageType.Error ? ValidationResultType.Error : ValidationResultType.Warning;
result.Message = Attribute.ErrorMessage;
}
}
}
#endif
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment