Skip to content

Instantly share code, notes, and snippets.

@nomnomab
Created February 2, 2022 23:17
Show Gist options
  • Save nomnomab/4437e74f34524bdb69213f30ff6ac4fc to your computer and use it in GitHub Desktop.
Save nomnomab/4437e74f34524bdb69213f30ff6ac4fc to your computer and use it in GitHub Desktop.
Constrains a string field's length
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class MaxLengthAttribute : PropertyAttribute {
public readonly uint Length;
public MaxLengthAttribute(uint length) {
Length = length;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(MaxLengthAttribute))]
public class MaxLengthAttributeEditor : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
if (property.propertyType == SerializedPropertyType.String) {
MaxLengthAttribute attr = (MaxLengthAttribute)attribute;
string value = property.stringValue;
if (value.Length > attr.Length) {
value = value.Substring(0, (int)attr.Length);
property.stringValue = value;
property.serializedObject.ApplyModifiedProperties();
}
}
EditorGUI.PropertyField(position, property, label);
}
}
#endif
@Meh0
Copy link

Meh0 commented Feb 3, 2022

Works as expected in Unity 2020.3 LTS ๐Ÿ‘

At first I put it in an Editor folder to get rid of the UNITY_EDITOR directives, but didn't know the PropertyAttribute HAS TO live in a regular folder. So went back to a single file.

Tweaked it a bunch to match a little bit more the "offical pattern". For example here the MinAttribute for numbers :
https://github.com/Unity-Technologies/UnityCsReference/blob/e740821767d2290238ea7954457333f06e952bad/Runtime/Export/PropertyDrawer/PropertyAttribute.cs#L99

Ended up with this result :

using UnityEngine;
using System;

#if UNITY_EDITOR
using UnityEditor;
#endif

[System.AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
public class MaxLengthAttribute : PropertyAttribute {
    public readonly int Value;

    public MaxLengthAttribute(int value) {
        Value = value;
    }

    public static implicit operator int(MaxLengthAttribute a) => a.Value;
}

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(MaxLengthAttribute))]
public class MaxLengthAttributeEditor : PropertyDrawer {
    private int _maxLength {
        get => attribute as MaxLengthAttribute;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        if (property.propertyType == SerializedPropertyType.String) {
            EditorGUI.BeginChangeCheck();
            EditorGUI.PropertyField(position, property, label);
            if (EditorGUI.EndChangeCheck()) {
                if (property.stringValue.Length > _maxLength) {
                    property.stringValue = property.stringValue.Substring(0, _maxLength);
                }
            }
        } else {
            EditorGUI.LabelField(position, label.text, string.Format(
                L10n.Tr("MaxLengthAttribute not implemented for {0}"),
                (SerializedPropertyType)property.propertyType
            ));
        }
    }
}
#endif

Will refactor it later to properly split them in their respective PropertyAttribute & Editor/PropertyDrawer folder/file (that would be supplied if I need more)

Thanks Nomnom, you put me on the right track. Helped me achieve intended result, and jumpstart with custom editor without learning everything upfront :)

@nomnomab
Copy link
Author

nomnomab commented Feb 3, 2022

Neato ๐Ÿ‘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment