Technical Documentation: dbrizov/NaughtyAttributes
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (`README.md`)
NaughtyAttributes
NaughtyAttributes is an extension for the Unity Inspector.
It expands the range of attributes that Unity provides so that you can create powerful inspectors without the need of custom editors or property drawers. It also provides attributes that can be applied to non-serialized fields or functions.
Most of the attributes are implemented using Unity's CustomPropertyDrawer, so they will work in your custom editors.
The attributes that won't work in your custom editors are the meta attributes and some drawer attributes such asReorderableList, Button, ShowNonSerializedField and ShowNativeProperty.
If you want all of the attributes to work in your custom editors, however, you must inherit from NaughtyInspector and use the NaughtyEditorGUI.PropertyField_Layout function instead of EditorGUILayout.PropertyField.
Installation
NaughtyAttributes requires 2022.3 or later versions.
- The package is available on the openupm registry. You can install it via openupm-cli.
openupm add com.dbrizov.naughtyattributes- You can also install via git url by adding this entry in your manifest.json
"com.dbrizov.naughtyattributes": "https://github.com/dbrizov/NaughtyAttributes.git#upm"- You can also download it from the Asset Store
Overview
Special Attributes
AllowNesting
This attribute must be used in some cases when you want meta attributes to work inside serializable nested structs or classes.
You can check in which cases you need to use it here.
public class NaughtyComponent : MonoBehaviour
{
public MyStruct myStruct;
}
[System.Serializable]
public struct MyStruct
{
public bool enableFlag;
[EnableIf("enableFlag")]
[AllowNesting] // Because it's nested we need to explicitly allow nesting
public int integer;
}Drawer Attributes
Provide special draw options to serialized fields.
A field can have only one DrawerAttribute. If a field has more than one, only the bottom one will be used.
AnimatorParam
Select an Animator paramater via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
public Animator someAnimator;
[AnimatorParam("someAnimator")]
public int paramHash;
[AnimatorParam("someAnimator")]
public string paramName;
}Button
A method can be marked as a button. A button appears in the inspector and executes the method if clicked.
Works both with instance and static methods.
public class NaughtyComponent : MonoBehaviour
{
[Button]
private void MethodOne() { }
[Button("Button Text")]
private void MethodTwo() { }
}CurveRange
Set bounds and modify curve color for AnimationCurves
public class NaughtyComponent : MonoBehaviour
{
[CurveRange(-1, -1, 1, 1)]
public AnimationCurve curve;
[CurveRange(EColor.Orange)]
public AnimationCurve curve1;
[CurveRange(0, 0, 5, 5, EColor.Red)]
public AnimationCurve curve2;
}Dropdown
Provides an interface for dropdown value selection.
public class NaughtyComponent : MonoBehaviour
{
[Dropdown("intValues")]
public int intValue;
[Dropdown("StringValues")]
public string stringValue;
[Dropdown("GetVectorValues")]
public Vector3 vectorValue;
private int[] intValues = new int[] { 1, 2, 3, 4, 5 };
private List<string> StringValues { get { return new List<string>() { "A", "B", "C", "D", "E" }; } }
private DropdownList<Vector3> GetVectorValues()
{
return new DropdownList<Vector3>()
{
{ "Right", Vector3.right },
{ "Left", Vector3.left },
{ "Up", Vector3.up },
{ "Down", Vector3.down },
{ "Forward", Vector3.forward },
{ "Back", Vector3.back }
};
}
}EnumFlags
Provides dropdown interface for setting enum flags.
public enum Direction
{
None = 0,
Right = 1 << 0,
Left = 1 << 1,
Up = 1 << 2,
Down = 1 << 3
}
public class NaughtyComponent : MonoBehaviour
{
[EnumFlags]
public Direction flags;
}Expandable
Make scriptable objects expandable.
public class NaughtyComponent : MonoBehaviour
{
[Expandable]
public ScriptableObject scriptableObject;
}HorizontalLine
public class NaughtyComponent : MonoBehaviour
{
[HorizontalLine(color: EColor.Red)]
public int red;
[HorizontalLine(color: EColor.Green)]
public int green;
[HorizontalLine(color: EColor.Blue)]
public int blue;
}InfoBox
Used for providing additional information.
public class NaughtyComponent : MonoBehaviour
{
[InfoBox("This is my int", EInfoBoxType.Normal)]
public int myInt;
[InfoBox("This is my float", EInfoBoxType.Warning)]
public float myFloat;
[InfoBox("This is my vector", EInfoBoxType.Error)]
public Vector3 myVector;
}InputAxis
Select an input axis via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
[InputAxis]
public string inputAxis;
}Layer
Select a layer via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
[Layer]
public string layerName;
[Layer]
public int layerIndex;
}MinMaxSlider
A double slider. The min value is saved to the X property, and the max value is saved to the Y property of a Vector2 field.
public class NaughtyComponent : MonoBehaviour
{
[MinMaxSlider(0.0f, 100.0f)]
public Vector2 minMaxSlider;
}ProgressBar
public class NaughtyComponent : MonoBehaviour
{
[ProgressBar("Health", 300, EColor.Red)]
public int health = 250;
[ProgressBar("Mana", 100, EColor.Blue)]
public int mana = 25;
[ProgressBar("Stamina", 200, EColor.Green)]
public int stamina = 150;
}ReorderableList
Provides array type fields with an interface for easy reordering of elements.
public class NaughtyComponent : MonoBehaviour
{
[ReorderableList]
public int[] intArray;
[ReorderableList]
public List<float> floatArray;
}ResizableTextArea
A resizable text area where you can see the whole text.
Unlike Unity's Multiline and TextArea attributes where you can see only 3 rows of a given text, and in order to see it or modify it you have to manually scroll down to the desired row.
public class NaughtyComponent : MonoBehaviour
{
[ResizableTextArea]
public string resizableTextArea;
}Scene
Select a scene from the build settings via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
[Scene]
public string bootScene; // scene name
[Scene]
public int tutorialScene; // scene index
}ShowAssetPreview
Shows the texture preview of a given asset (Sprite, Prefab...).
public class NaughtyComponent : MonoBehaviour
{
[ShowAssetPreview]
public Sprite sprite;
[ShowAssetPreview(128, 128)]
public GameObject prefab;
}ShowNativeProperty
Shows native C# properties in the inspector.
All native properties are displayed at the bottom of the inspector after the non-serialized fields and before the method buttons.
It supports only certain types (bool, int, long, float, double, string, Vector2, Vector3, Vector4, Color, Bounds, Rect, UnityEngine.Object).
public class NaughtyComponent : MonoBehaviour
{
public List<Transform> transforms;
[ShowNativeProperty]
public int TransformsCount => transforms.Count;
}ShowNonSerializedField
Shows non-serialized fields in the inspector.
All non-serialized fields are displayed at the bottom of the inspector before the method buttons.
Keep in mind that if you change a non-static non-serialized field in the code - the value in the inspector will be updated after you press Play in the editor.
There is no such issue with static non-serialized fields because their values are updated at compile time.
It supports only certain types (bool, int, long, float, double, string, Vector2, Vector3, Vector4, Color, Bounds, Rect, UnityEngine.Object).
public class NaughtyComponent : MonoBehaviour
{
[ShowNonSerializedField]
private int myInt = 10;
[ShowNonSerializedField]
private const float PI = 3.14159f;
[ShowNonSerializedField]
private static readonly Vector3 CONST_VECTOR = Vector3.one;
}SortingLayer
Select a sorting layer via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
[SortingLayer]
public string layerName;
[SortingLayer]
public int layerId;
}Tag
Select a tag via dropdown interface.
public class NaughtyComponent : MonoBehaviour
{
[Tag]
public string tagField;
}Meta Attributes
Give the fields meta data. A field can have more than one meta attributes.
BoxGroup
Surrounds grouped fields with a box.
public class NaughtyComponent : MonoBehaviour
{
[BoxGroup("Integers")]
public int firstInt;
[BoxGroup("Integers")]
public int secondInt;
[BoxGroup("Floats")]
public float firstFloat;
[BoxGroup("Floats")]
public float secondFloat;
}Foldout
Makes a foldout group.
public class NaughtyComponent : MonoBehaviour
{
[Foldout("Integers")]
public int firstInt;
[Foldout("Integers")]
public int secondInt;
}EnableIf / DisableIf
public class NaughtyComponent : MonoBehaviour
{
public bool enableMyInt;
[EnableIf("enableMyInt")]
public int myInt;
[EnableIf("Enabled")]
public float myFloat;
[EnableIf("NotEnabled")]
public Vector3 myVector;
public bool Enabled() { return true; }
public bool NotEnabled => false;
}You can have more than one condition.
public class NaughtyComponent : MonoBehaviour
{
public bool flag0;
public bool flag1;
[EnableIf(EConditionOperator.And, "flag0", "flag1")]
public int enabledIfAll;
[EnableIf(EConditionOperator.Or, "flag0", "flag1")]
public int enabledIfAny;
}ShowIf / HideIf
public class NaughtyComponent : MonoBehaviour
{
public bool showInt;
[ShowIf("showInt")]
public int myInt;
[ShowIf("AlwaysShow")]
public float myFloat;
[ShowIf("NeverShow")]
public Vector3 myVector;
public bool AlwaysShow() { return true; }
public bool NeverShow => false;
}You can have more than one condition.
public class NaughtyComponent : MonoBehaviour
{
public bool flag0;
public bool flag1;
[ShowIf(EConditionOperator.And, "flag0", "flag1")]
public int showIfAll;
[ShowIf(EConditionOperator.Or, "flag0", "flag1")]
public int showIfAny;
}Label
Override default field label.
public class NaughtyComponent : MonoBehaviour
{
[Label("Short Name")]
public string veryVeryLongName;
[Label("RGB")]
public Vector3 vectorXYZ;
}OnValueChanged
Detects a value change and executes a callback.
Keep in mind that the event is detected only when the value is changed from the inspector.
If you want a runtime event, you should probably use an event/delegate and subscribe to it.
public class NaughtyComponent : MonoBehaviour
{
[OnValueChanged("OnValueChangedCallback")]
public int myInt;
private void OnValueChangedCallback()
{
Debug.Log(myInt);
}
}ReadOnly
Make a field read only.
public class NaughtyComponent : MonoBehaviour
{
[ReadOnly]
public Vector3 forwardVector = Vector3.forward;
}Validator Attributes
Used for validating the fields. A field can have infinite number of validator attributes.
MinValue / MaxValue
Clamps integer and float fields. The MinValue/MaxValue attributes can accept either a constant numeric value (e.g. 0, 1.5f) or the name of another field, property, or a parameterless function that returns a numeric value โ use nameof(...) to reference members safely. When a name is provided, the referenced member is evaluated to obtain the min/max value at edit-time/runtime.
public class NaughtyComponent : MonoBehaviour
{
[MinValue(0), MaxValue(10)]
public int myInt;
[MinValue(0.0f)]
public float myFloat;
[MinValue("minFloat"), MaxValue("maxFloat")]
public float myFloatThroughFieldName;
[MinValue(nameof(minFloatProperty)), MaxValue(nameof(maxFloatProperty))]
public float myFloatThroughPropertyName;
private float minFloat = -1;
private float maxFloat = 1;
private float minFloatProperty => minFloat;
private float maxFloatProperty => maxFloat;
}Required
Used to remind the developer that a given reference type field is required.
public class NaughtyComponent : MonoBehaviour
{
[Required]
public Transform myTransform;
[Required("Custom required text")]
public GameObject myGameObject;
}RequiredType
Used on game objects or components.
When used on a game object, it checks if the game object has a component of the required type.
When used on a component, it checks if the game object it is attached to has a component of the required type.
public class NaughtyComponent : MonoBehaviour
{
[RequiredType(typeof(Rigidbody))]
public GameObject gameObjectMustHaveRigidbody;
[RequiredType(typeof(Rigidbody))]
public Transform transformMustHaveRigidbody;
[RequiredType(typeof(IRequiredTypeTestInterface))]
public GameObject gameObjectMustHaveInterface;
[RequiredType(typeof(RequiredTypeTestTestObject))]
public GameObject gameObjectMustHaveComponent;
[RequiredType(showInfoMessageWhenEmpty: false, typeof(IRequiredTypeTestInterface))]
public GameObject shouldNotShowInfoMessageWhenEmpty;
[RequiredType(typeof(IRequiredTypeTestInterface), typeof(IRequiredTypeTestInterface2))]
public GameObject gameObjectMustHaveMultipleType;
[RequiredType(typeof(RequiredTypeTestTestObject))]
public RequiredTypeTest componentMustHaveAnotherComponent;
}ValidateInput
The most powerful ValidatorAttribute.
public class _NaughtyComponent : MonoBehaviour
{
[ValidateInput("IsNotNull")]
public Transform myTransform;
[ValidateInput("IsGreaterThanZero", "myInteger must be greater than zero")]
public int myInt;
private bool IsNotNull(Transform tr)
{
return tr != null;
}
private bool IsGreaterThanZero(int value)
{
return value > 0;
}
}Sphinx Src Credits (`docs/sphinx/src/credits.rst`)
.. _label-credits:
Credits
NaughtyAttributes is distributed under the MIT License. The assets this documentation site uses are credited below.
Unity trademarks
Unity and the Unity logo are trademarks or registered trademarks of Unity Technologies. They are used here only
to identify the engine these docs are for. NaughtyAttributes is not affiliated with, endorsed by, or sponsored by
Unity Technologies.
Fonts
Inter <https://github.com/rsms/inter>_ โ Copyright ยฉ 2016 The Inter Project Authors.
JetBrains Mono <https://github.com/JetBrains/JetBrainsMono>_ โ Copyright ยฉ 2020 The JetBrains Mono Project Authors.
Both are used unmodified under the SIL Open Font License, Version 1.1 <https://scripts.sil.org/OFL>_.
The full license text ships beside the font files, at _static/css/fonts/LICENSE.txt.
Stylesheet
The theme overrides in _static/css/custom.css are adapted from theGodot Engine documentation <https://github.com/godotengine/godot-docs>, which is licensed under theCreative Commons Attribution 3.0 Unported License <https://creativecommons.org/licenses/by/3.0/>.
Sphinx Src Index (`docs/sphinx/src/index.rst`)
Introduction
NaughtyAttributes is an open-source extension for the Unity Inspector.
It expands the range of attributes that Unity provides so that you can create powerful inspectors without the need of custom editors or property drawers.
It also provides attributes that can be applied to non-serialized fields or functions.
.. note::
Most of the attributes are implemented using Unity's CustomPropertyDrawer, so they will work in your custom editors.
The attributes that won't work in your custom editors are the :ref:label-meta-attributes and some :ref:label-drawer-attributes
such as :ref:label-reorderable-list, :ref:label-button, :ref:label-show-non-serialized-field and :ref:label-show-native-property.
If you want all of the attributes to work in your custom editors, however,
you must inherit from NaughtyInspector and use the NaughtyEditorGUI.PropertyField_Layout function instead of EditorGUILayout.PropertyField.
Contribute
If you want to contribute you can visit the GitHub Repo <https://github.com/dbrizov/NaughtyAttributes>_ and give me pull requests.
The project is using CRLF and Spaces instead of Tabs. It's a must that you respect the coding standard.
Donation
I am developing the project in my free time. If you like it you can support me by donating.
PayPal <https://paypal.me/dbrizov>_Buy Me A Coffee <https://www.buymeacoffee.com/dbrizov>_
.. toctree::
:maxdepth: 1
:caption: General
:name: sec-general
general/installation.. toctree::
:maxdepth: 1
:caption: Attributes
:name: sec-attributes
attributes/decorator_attributes/index
attributes/drawer_attributes/index
attributes/meta_attributes/index
attributes/validator_attributes/index
attributes/special_attributes/index.. toctree::
:maxdepth: 1
:caption: About
:name: sec-about
creditsStatic Css Fonts LICENSE (`docs/_static/css/fonts/LICENSE.txt`)
The font files in this directory are redistributed unmodified from their
upstream releases. Both are licensed under the SIL Open Font License,
Version 1.1, the full text of which follows.
Inter
Inter-Regular.woff2, Inter-Italic.woff2, Inter-Bold.woff2, Inter-BoldItalic.woff2
Version 4.001 (release v4.1)
Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
JetBrains Mono
JetBrainsMono-Regular.woff2, JetBrainsMono-Medium.woff2
Version 2.242 (release v2.242)
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION AND CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Sphinx Src General Installation (`docs/sphinx/src/general/installation.rst`)
Installation
.. note::
NaughtyAttributes requires Unity 2022.3 or later versions.
The package is available on the
openupm registry <https://openupm.com>. You can install it viaopenupm-cli <https://github.com/openupm/openupm-cli>::openupm add com.dbrizov.naughtyattributes
You can also install via git url by adding this entry in your
manifest.json::"com.dbrizov.naughtyattributes": "https://github.com/dbrizov/NaughtyAttributes.git#upm"
You can also download it from the
Asset Store <https://assetstore.unity.com/packages/tools/utilities/naughtyattributes-129996>_
Sphinx Src Attributes Decorator Attributes Horizontal Line (`docs/sphinx/src/attributes/decorator_attributes/horizontal_line.rst`)
HorizontalLine
Similar to Unity's Space attribute, but draws a horizontal line instead of an empty space.
You can control the hight (thickness) and color of the line::
public class NaughtyComponent : MonoBehaviour
{
[HorizontalLine(color: EColor.Red)]
public int red;
[HorizontalLine(color: EColor.Green)]
public int green;
[HorizontalLine(color: EColor.Blue)]
public int blue;
}.. image:: ../../../images/HorizontalLine_Inspector.png
Sphinx Src Attributes Decorator Attributes Index (`docs/sphinx/src/attributes/decorator_attributes/index.rst`)
.. _label-decorator-attributes:
Decorator Attributes
Decorator attributes draw additional GUI around a field, instead of replacing the way the field itself is drawn.
.. note::
Unlike :ref:label-drawer-attributes, a field can have more than one decorator attribute,
and can be combined with a drawer attribute.
.. toctree::
:maxdepth: 1
:name: toc-decorator-attributes
horizontal_line
info_boxSphinx Src Attributes Decorator Attributes Info Box (`docs/sphinx/src/attributes/decorator_attributes/info_box.rst`)
InfoBox
Used to provide additional information::
public class NaughtyComponent : MonoBehaviour
{
[InfoBox("This is my int", EInfoBoxType.Normal)]
public int myInt;
[InfoBox("This is my float", EInfoBoxType.Warning)]
public float myFloat;
[InfoBox("This is my vector", EInfoBoxType.Error)]
public Vector3 myVector;
}.. image:: ../../../images/InfoBox_Inspector.png
Sphinx Src Attributes Drawer Attributes Animator Param (`docs/sphinx/src/attributes/drawer_attributes/animator_param.rst`)
AnimatorParam
Select an Animator paramater via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
public Animator someAnimator;
[AnimatorParam("someAnimator")]
public int paramHash;
[AnimatorParam("someAnimator")]
public string paramName;
}.. image:: ../../../images/AnimatorParam_Inspector.png
Sphinx Src Attributes Drawer Attributes Button (`docs/sphinx/src/attributes/drawer_attributes/button.rst`)
.. _label-button:
Button
A method can be marked as a button. A button appears in the inspector and executes the method if clicked.
Works both with instance and static methods.
.. warning::
Doesn't work on methods that are nested inside serialized structs or classes.
::
public class NaughtyComponent : MonoBehaviour
{
[Button]
private void MethodOne(int parameter = 0) { } // Works with default parameters
[Button("Button Text")] // Specify button text
private void MethodTwo() { }
[Button(enabledMode: EButtonEnableMode.Editor)]
private void EnabledInEditorOnly() { }
[Button(enabledMode: EButtonEnableMode.Playmode)]
private void EnabledInPlaymodeOnly() { }
[Button] // When pressed and the target object is a MonoBehaviour, it will start the coroutine
private IEnumerator SomeCoroutine() { }
}.. image:: ../../../images/Button_Inspector.png
Sphinx Src Attributes Drawer Attributes Curve Range (`docs/sphinx/src/attributes/drawer_attributes/curve_range.rst`)
CurveRange
Can limit the x and y values of an animation curve, and/or change the color of the curve in the inspector::
public class NaughtyComponent : MonoBehaviour
{
[CurveRange(-1, -1, 1, 1)] // min.x = -1, min.y = -1, max.x = 1, max.y = 1
public AnimationCurve curve;
[CurveRange(EColor.Orange)]
public AnimationCurve curve1;
[CurveRange(0, 0, 5, 5, EColor.Red)]
public AnimationCurve curve2;
}.. image:: ../../../images/CurveRange_Inspector.png
Sphinx Src Attributes Drawer Attributes Dropdown (`docs/sphinx/src/attributes/drawer_attributes/dropdown.rst`)
Dropdown
Provides an interface for dropdown value selection.
The values of the dropdown can be provided by a field, property or function.
.. warning::
When nested inside a struct the value of the dropdown doesn't update.
This is because the value of the parent struct is updated via reflection.
In order for the value to be updated the struct needs to be boxed and then unboxed.
The sctruct is already passed as an object (boxed) to the dropdown drawer, but unfortunately in order
to unbox it I need to know the compile-time type of the struct, and I don't.
Nesting inside a class works as expected.
::
public class NaughtyComponent : MonoBehaviour
{
[Dropdown("intValues")]
public int intValue;
[Dropdown("StringValues")]
public string stringValue;
[Dropdown("GetVectorValues")]
public Vector3 vectorValue;
private int[] intValues = new int[] { 1, 2, 3, 4, 5 };
private List<string> StringValues { get { return new List<string>() { "A", "B", "C", "D", "E" }; } }
private DropdownList<Vector3> GetVectorValues()
{
return new DropdownList<Vector3>()
{
{ "Right", Vector3.right },
{ "Left", Vector3.left },
{ "Up", Vector3.up },
{ "Down", Vector3.down },
{ "Forward", Vector3.forward },
{ "Back", Vector3.back }
};
}
}.. image:: ../../../images/Dropdown_Inspector.gif
Sphinx Src Attributes Drawer Attributes Enum Flags (`docs/sphinx/src/attributes/drawer_attributes/enum_flags.rst`)
EnumFlags
Provides a dropdown interface for setting enum flags::
public enum Direction
{
None = 0,
Right = 1 << 0,
Left = 1 << 1,
Up = 1 << 2,
Down = 1 << 3
}
public class NaughtyComponent : MonoBehaviour
{
[EnumFlags]
public Direction flags;
}.. image:: ../../../images/EnumFlags_Inspector.png
Sphinx Src Attributes Drawer Attributes Expandable (`docs/sphinx/src/attributes/drawer_attributes/expandable.rst`)
Expandable
Make scriptable objects expandable::
public class NaughtyComponent : MonoBehaviour
{
[Expandable]
public ScriptableObject scriptableObject;
}.. image:: ../../../images/Expandable_Inspector.png
Sphinx Src Attributes Drawer Attributes Index (`docs/sphinx/src/attributes/drawer_attributes/index.rst`)
.. _label-drawer-attributes:
Drawer Attributes
Drawer attributes provide special draw options for the Unity Inspector.
They can be applied to serialized, and non-serialized fields, native C# properties, and functions.
.. note::
A field, property or function can have only one drawer attribute.
.. toctree::
:maxdepth: 1
:name: toc-drawer-attributes
animator_param
button
curve_range
dropdown
enum_flags
expandable
input_axis
layer
min_max_slider
progress_bar
reorderable_list
resizable_text_area
scene
show_asset_preview
show_native_property
show_non_serialized_field
sorting_layer
tagSphinx Src Attributes Drawer Attributes Input Axis (`docs/sphinx/src/attributes/drawer_attributes/input_axis.rst`)
InputAxis
Select an input axis via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
[InputAxis]
public string inputAxis;
}.. image:: ../../../images/InputAxis_Inspector.png
Sphinx Src Attributes Drawer Attributes Layer (`docs/sphinx/src/attributes/drawer_attributes/layer.rst`)
Layer
Select a layer via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
[Layer]
public string layerName;
[Layer]
public int layerIndex;
}.. image:: ../../../images/Layer_Inspector.png
Sphinx Src Attributes Drawer Attributes Min Max Slider (`docs/sphinx/src/attributes/drawer_attributes/min_max_slider.rst`)
.. _label-min-max-slider:
MinMaxSlider
A double slider.
The min value is saved to the x property, and the max value is saved to the y property of a Vector2 or a Vector2Int field::
public class NaughtyComponent : MonoBehaviour
{
[MinMaxSlider(0.0f, 100.0f)]
public Vector2 minMaxSlider;
}.. image:: ../../../images/MinMaxSlider_Inspector.png
Sphinx Src Attributes Drawer Attributes Progress Bar (`docs/sphinx/src/attributes/drawer_attributes/progress_bar.rst`)
ProgressBar
Draws a progress bar. Can be applied to an int or a float::
public class NaughtyComponent : MonoBehaviour
{
[ProgressBar("Health", 300, EColor.Red)]
public int health = 250;
[ProgressBar("Mana", 100, EColor.Blue)]
public int mana = 25;
[ProgressBar("Stamina", "maxStamina", EColor.Green)] // Dynamic max value constructor
public int stamina = 150;
public int maxStamina = 200;
}.. image:: ../../../images/ProgressBar_Inspector.png
Sphinx Src Attributes Drawer Attributes Reorderable List (`docs/sphinx/src/attributes/drawer_attributes/reorderable_list.rst`)
.. _label-reorderable-list:
ReorderableList
Provides array type fields with an interface for easy reordering of elements.
As of Unity 2020.2.x all lists are reorderable by default, so you no longer have to use this attribute.
.. warning::
Doesn't work on lists that are nested inside serialized structs of classes.
::
public class NaughtyComponent : MonoBehaviour
{
[ReorderableList]
public int[] intArray;
[ReorderableList]
public List<float> floatArray;
}.. image:: ../../../images/ReorderableList_Inspector.gif
Sphinx Src Attributes Drawer Attributes Resizable Text Area (`docs/sphinx/src/attributes/drawer_attributes/resizable_text_area.rst`)
ResizableTextArea
A resizable text area where you can see the whole text.
Unlike Unity's Multiline or TextArea attributes where you can see only 3 rows of a given text,
and in order to see it or modify it you have to manually scroll down to the desired row::
public class NaughtyComponent : MonoBehaviour
{
[ResizableTextArea]
public string resizableTextArea;
}.. image:: ../../../images/ResizableTextArea_Inspector.gif
Sphinx Src Attributes Drawer Attributes Scene (`docs/sphinx/src/attributes/drawer_attributes/scene.rst`)
Scene
Select a scene from the build settings via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
[Scene]
public string bootScene; // scene name
[Scene]
public int tutorialScene; // scene index
}.. image:: ../../../images/Scene_Inspector.png
Sphinx Src Attributes Drawer Attributes Show Asset Preview (`docs/sphinx/src/attributes/drawer_attributes/show_asset_preview.rst`)
ShowAssetPreview
Shows the texture preview of a given asset (Sprite, Prefab...)::
public class NaughtyComponent : MonoBehaviour
{
[ShowAssetPreview]
public Sprite sprite;
[ShowAssetPreview(128, 128)]
public GameObject prefab;
}.. image:: ../../../images/ShowAssetPreview_Inspector.png
Sphinx Src Attributes Drawer Attributes Show Native Property (`docs/sphinx/src/attributes/drawer_attributes/show_native_property.rst`)
.. _label-show-native-property:
ShowNativeProperty
Shows native C# properties in the inspector.
It supports only certain types bool, short, ushort, int, uint, long, ulong, float, double, string,Vector2, Vector3, Vector4, Vector2Int, Vector3Int, Color, Bounds, Rect, RectInt, UnityEngine.Object.
.. warning::
Doesn't work on properties that are nested inside serialized structs of classes.
::
public class NaughtyComponent : MonoBehaviour
{
public List transforms;
[ShowNativeProperty]
public int TransformsCount => transforms.Count;
}.. image:: ../../../images/ShowNativeProperty_Inspector.png
Sphinx Src Attributes Drawer Attributes Show Non Serialized Field (`docs/sphinx/src/attributes/drawer_attributes/show_non_serialized_field.rst`)
.. _label-show-non-serialized-field:
ShowNonSerializedField
Shows non-serialized fields in the inspector.
Keep in mind that if you change a non-static non-serialized field in the code - the value in the inspector will be updated after you press Play in the editor.
There is no such issue with static non-serialized fields because their values are updated at compile-time.
It supports only certain types bool, short, ushort, int, uint, long, ulong, float, double, string,Vector2, Vector3, Vector4, Vector2Int, Vector3Int, Color, Bounds, Rect, RectInt, UnityEngine.Object.
.. warning::
Doesn't work on non-serialized fields that are nested inside serialized structs of classes.
::
public class NaughtyComponent : MonoBehaviour
{
[ShowNonSerializedField]
private int myInt = 10;
[ShowNonSerializedField]
private const float PI = 3.14159f;
[ShowNonSerializedField]
private static readonly Vector3 CONST_VECTOR = Vector3.one;
}.. image:: ../../../images/ShowNonSerializedField_Inspector.png
Sphinx Src Attributes Drawer Attributes Sorting Layer (`docs/sphinx/src/attributes/drawer_attributes/sorting_layer.rst`)
SortingLayer
Select a sorting layer via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
[SortingLayer]
public string layerName;
[SortingLayer]
public int layerId;
}.. image:: ../../../images/SortingLayer_Inspector.png
Sphinx Src Attributes Drawer Attributes Tag (`docs/sphinx/src/attributes/drawer_attributes/tag.rst`)
Tag
Select a tag via dropdown interface::
public class NaughtyComponent : MonoBehaviour
{
[Tag]
public string tagField;
}.. image:: ../../../images/Tag_Inspector.png
Sphinx Src Attributes Meta Attributes Box Group (`docs/sphinx/src/attributes/meta_attributes/box_group.rst`)
BoxGroup
Can be used to group serialized fields.
.. warning::
Doesn't work on serialized fields that are nested inside serialized structs of classes.
::
public class NaughtyComponent : MonoBehaviour
{
[BoxGroup("Integers")]
public int firstInt;
[BoxGroup("Integers")]
public int secondInt;
[BoxGroup("Floats")]
public float firstFloat;
[BoxGroup("Floats")]
public float secondFloat;
}.. image:: ../../../images/BoxGroup_Inspector.png
Sphinx Src Attributes Meta Attributes Enable Disable If (`docs/sphinx/src/attributes/meta_attributes/enable_disable_if.rst`)
.. _label-enable-disable-if:
EnableIf / DisableIf
Can be used to make serialized fields or buttons readonly based on some condition.
The condition can be a field, property or function.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
public bool enableMyInt;
[EnableIf("enableMyInt")]
public int myInt;
[EnableIf("Enabled")]
public float myFloat;
[EnableIf("NotEnabled")]
public Vector3 myVector;
public bool Enabled() { return true; }
public bool NotEnabled => false;
}.. image:: ../../../images/EnableIf_Inspector.gif
You can have more than one condition::
public class NaughtyComponent : MonoBehaviour
{
public bool flag0;
public bool flag1;
[EnableIf(EConditionOperator.And, "flag0", "flag1")]
public int enabledIfAll;
[EnableIf(EConditionOperator.Or, "flag0", "flag1")]
public int enabledIfAny;
}An enum value can also be used as a condition::
public class NaughtyComponent : MonoBehaviour
{
public EMyEnum enumFlag;
[EnableIf("enumFlag", EMyEnum.Case0)]
public int enableIfEnum; // Will be enabled only if enumFlag == EMyEnum.Case0
}
public enum EMyEnum
{
Case0,
Case1,
Case2
}Sphinx Src Attributes Meta Attributes Foldout (`docs/sphinx/src/attributes/meta_attributes/foldout.rst`)
Foldout
Makes a foldout group.
.. warning::
Doesn't work on serialized fields that are nested inside serialized structs of classes.
::
public class NaughtyComponent : MonoBehaviour
{
[Foldout("Integers")]
public int firstInt;
[Foldout("Integers")]
public int secondInt;
}.. image:: ../../../images/Foldout_Inspector.gif
Sphinx Src Attributes Meta Attributes Index (`docs/sphinx/src/attributes/meta_attributes/index.rst`)
.. _label-meta-attributes:
Meta Attributes
Give fields or methods meta data. A field or method can have more than one meta attribute.
.. toctree::
:maxdepth: 1
:name: toc-meta-attributes
box_group
enable_disable_if
foldout
label
on_value_changed
read_only
show_hide_ifSphinx Src Attributes Meta Attributes Label (`docs/sphinx/src/attributes/meta_attributes/label.rst`)
Label
Override default field label.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[Label("Short Name")]
public string veryVeryLongName;
[Label("RGB")]
public Vector3 vectorXYZ;
}.. image:: ../../../images/Label_Inspector.png
Sphinx Src Attributes Meta Attributes On Value Changed (`docs/sphinx/src/attributes/meta_attributes/on_value_changed.rst`)
OnValueChanged
Detects a value change and executes a callback.
Keep in mind that the event is detected only when the value is changed from the inspector.
If you want a runtime event, you should probably use an event/delegate and subscribe to it.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[OnValueChanged("OnValueChangedCallback")]
public int myInt;
private void OnValueChangedCallback()
{
Debug.Log(myInt);
}
}Sphinx Src Attributes Meta Attributes Read Only (`docs/sphinx/src/attributes/meta_attributes/read_only.rst`)
ReadOnly
Make a serialized field readonly
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[ReadOnly]
public Vector3 forwardVector = Vector3.forward;
}.. image:: ../../../images/ReadOnly_Inspector.png
Sphinx Src Attributes Meta Attributes Show Hide If (`docs/sphinx/src/attributes/meta_attributes/show_hide_if.rst`)
ShowIf / HideIf
Can be used to show/hide serialized fields or buttons based on some condition.
The condition can be a field, property or function.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
public bool showInt;
[ShowIf("showInt")]
public int myInt;
[ShowIf("AlwaysShow")]
public float myFloat;
[ShowIf("NeverShow")]
public Vector3 myVector;
public bool AlwaysShow() { return true; }
public bool NeverShow => false;
}.. image:: ../../../images/ShowIf_Inspector.gif
You can have more than one condition::
public class NaughtyComponent : MonoBehaviour
{
public bool flag0;
public bool flag1;
[ShowIf(EConditionOperator.And, "flag0", "flag1")]
public int showIfAll;
[ShowIf(EConditionOperator.Or, "flag0", "flag1")]
public int showIfAny;
}An enum value can also be used as a condition::
public class NaughtyComponent : MonoBehaviour
{
public EMyEnum enumFlag;
[ShowIf("enumFlag", EMyEnum.Case0)]
public int enableIfEnum; // Will be shown only if enumFlag == EMyEnum.Case0
}
public enum EMyEnum
{
Case0,
Case1,
Case2
}Sphinx Src Attributes Special Attributes Allow Nesting (`docs/sphinx/src/attributes/special_attributes/allow_nesting.rst`)
.. _label-allow-nesting:
AllowNesting
By default :ref:label-drawer-attributes can be nested inside structs and classes.
:ref:label-meta-attributes and :ref:label-validator-attributes however are not drawers and don't support nesting out of the box.
If you want to use :ref:label-enable-disable-if attributes inside structs for instance, you have to use the AllowNesting attribute like so::
public class NaughtyComponent : MonoBehaviour
{
public MyStruct myStruct;
}
[System.Serializable]
public struct MyStruct
{
public bool enableFlag;
[EnableIf("enableFlag")]
[AllowNesting] // Because it's nested we need to explicitly allow nesting
public int integer;
}.. note::
The AllowNesting attribute is actually a drawer attribute. You can think of it as a DefaultDrawer attribute.
All it does is draw the serialized field with its default drawer. This is a bit of a hack you see.
The system is implemented in such a way that before a drawer's OnGUI function is called it applies the meta and validator attributes.
In order to trigger this behavoir we need some kind of a drawer. The AllowNesting is that drawer.
If for you are combining :ref:label-enable-disable-if with :ref:label-min-max-slider for instance,
you don't have to put the AllowNesting attribute, because you already marked the serialized field with the MinMaxSlider drawer.
Sphinx Src Attributes Special Attributes Index (`docs/sphinx/src/attributes/special_attributes/index.rst`)
Special Attributes
.. toctree::
:maxdepth: 1
:name: toc-special-attributes
allow_nestingSphinx Src Attributes Validator Attributes Index (`docs/sphinx/src/attributes/validator_attributes/index.rst`)
.. _label-validator-attributes:
Validator Attributes
Used for validating fields. A field can have infinite number of validator attributes.
.. toctree::
:maxdepth: 1
:name: toc-validator-attributes
min_max_value
required
required_type
validate_inputSphinx Src Attributes Validator Attributes Min Max Value (`docs/sphinx/src/attributes/validator_attributes/min_max_value.rst`)
MinValue / MaxValue
Can be used to limit the range of variables.
Can be applied to int, float, Vector2, Vector3, Vector4, Vector2Int, Vector3Int.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[MinValue(0), MaxValue(10)]
public int myInt;
[MinValue(0.0f)]
public float myFloat;
}.. image:: ../../../images/MinValueMaxValue_Inspector.gif
Sphinx Src Attributes Validator Attributes Required (`docs/sphinx/src/attributes/validator_attributes/required.rst`)
Required
Used to remind the user that a given reference type field is required.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[Required]
public Transform myTransform;
[Required("Custom required text")]
public GameObject myGameObject;
}.. image:: ../../../images/Required_Inspector.png
Sphinx Src Attributes Validator Attributes Required Type (`docs/sphinx/src/attributes/validator_attributes/required_type.rst`)
RequiredType
Used on game objects or components.
When used on a game object, it checks if the game object has a component of the required type.
When used on a component, it checks if the game object it is attached to has a component of the required type.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[RequiredType(typeof(Rigidbody))]
public GameObject gameObjectMustHaveRigidbody;
[RequiredType(typeof(Rigidbody))]
public Transform transformMustHaveRigidbody;
[RequiredType(typeof(IRequiredTypeTestInterface))]
public GameObject gameObjectMustHaveInterface;
[RequiredType(typeof(RequiredTypeTestTestObject))]
public GameObject gameObjectMustHaveComponent;
[RequiredType(showInfoMessageWhenEmpty: false, typeof(IRequiredTypeTestInterface))]
public GameObject shouldNotShowInfoMessageWhenEmpty;
[RequiredType(typeof(IRequiredTypeTestInterface), typeof(IRequiredTypeTestInterface2))]
public GameObject gameObjectMustHaveMultipleType;
[RequiredType(typeof(RequiredTypeTestTestObject))]
public RequiredTypeTest componentMustHaveAnotherComponent;
}.. image:: ../../../images/RequiredType_Inspector.png
Sphinx Src Attributes Validator Attributes Validate Input (`docs/sphinx/src/attributes/validator_attributes/validate_input.rst`)
ValidateInput
The most powerful ValidatorAttribute.
.. note::
If you want to use it on fields that are nested inside serialized structs or classes
you need to use the :ref:label-allow-nesting attribute.
::
public class NaughtyComponent : MonoBehaviour
{
[ValidateInput("IsNotNull")]
public Transform myTransform;
[ValidateInput("IsGreaterThanZero", "myInteger must be greater than zero")]
public int myInt;
private bool IsNotNull(Transform tr)
{
return tr != null;
}
private bool IsGreaterThanZero(int value)
{
return value > 0;
}
}.. image:: ../../../images/ValidateInput_Inspector.png
Sphinx Static Css Fonts LICENSE (`docs/sphinx/static/css/fonts/LICENSE.txt`)
The font files in this directory are redistributed unmodified from their
upstream releases. Both are licensed under the SIL Open Font License,
Version 1.1, the full text of which follows.
Inter
Inter-Regular.woff2, Inter-Italic.woff2, Inter-Bold.woff2, Inter-BoldItalic.woff2
Version 4.001 (release v4.1)
Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
JetBrains Mono
JetBrainsMono-Regular.woff2, JetBrainsMono-Medium.woff2
Version 2.242 (release v2.242)
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION AND CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
--- METRICS ---
- Files Extracted: 43
- Estimated Token Budget: ~13907 tokens
- Canonical Reference: https://codewiki.google/github.com/dbrizov/NaughtyAttributes