// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Core.Attributes
{
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
///
/// Specifies the type of message displayed in the inspector when a field is null.
///
public enum WNotNullMessageType
{
///
/// Displays as a warning (yellow) in the inspector.
///
Warning = 0,
///
/// Displays as an error (red) in the inspector.
///
Error = 1,
}
///
/// Validates that a field is not null. Displays a warning or error in the inspector when the field is null,
/// and throws an when
/// is called on an object containing a null field marked with this attribute.
///
///
///
/// public class PlayerController : MonoBehaviour
/// {
/// [WNotNull]
/// public Rigidbody2D rb;
///
/// [WNotNull(WNotNullMessageType.Error, "Audio source is required for sound effects")]
/// public AudioSource audioSource;
///
/// private void Awake()
/// {
/// this.CheckForNulls();
/// }
/// }
///
///
[AttributeUsage(AttributeTargets.Field)]
public sealed class WNotNullAttribute : PropertyAttribute
{
///
/// The type of message to display in the inspector when the field is null.
///
public WNotNullMessageType MessageType { get; }
///
/// An optional custom message to display in the inspector when the field is null.
/// If null or empty, a default message will be generated based on the field name.
///
public string CustomMessage { get; }
///
/// Creates a new WNotNull attribute with default settings (warning message type, auto-generated message).
///
public WNotNullAttribute()
: this(WNotNullMessageType.Warning, null) { }
///
/// Creates a new WNotNull attribute with the specified message type and auto-generated message.
///
/// The type of message to display when null.
public WNotNullAttribute(WNotNullMessageType messageType)
: this(messageType, null) { }
///
/// Creates a new WNotNull attribute with default message type (warning) and a custom message.
///
/// The custom message to display when null.
public WNotNullAttribute(string customMessage)
: this(WNotNullMessageType.Warning, customMessage) { }
///
/// Creates a new WNotNull attribute with the specified message type and custom message.
///
/// The type of message to display when null.
/// The custom message to display when null.
public WNotNullAttribute(WNotNullMessageType messageType, string customMessage)
{
MessageType = messageType;
CustomMessage = customMessage;
}
}
public static class WNotNullAttributeExtensions
{
public static void CheckForNulls(this object o)
{
#if UNITY_EDITOR
if (o == null || (o is UnityEngine.Object unityObj && unityObj == null))
{
return;
}
IEnumerable properties =
Helper.ReflectionHelpers.GetFieldsWithAttribute(o.GetType());
foreach (FieldInfo field in properties)
{
object fieldValue = field.GetValue(o);
switch (fieldValue)
{
case UnityEngine.Object unityObject when unityObject == null:
throw new ArgumentNullException(field.Name);
case null:
throw new ArgumentNullException(field.Name);
}
}
#endif
}
}
}