Go to file
2022-07-02 09:37:09 +03:00
Editor Fix csharp syntax 2022-06-06 15:08:45 +03:00
Editor.Extras Nicify property name in MissingReference validator message 2022-07-02 09:29:13 +03:00
Editor.Integrations Add Odin 3.0.x support 2022-06-06 19:35:24 +03:00
Runtime Closes #5 - Add AssetsOnly attribute 2022-06-10 15:34:49 +03:00
Unity.InternalAPIEditorBridge.012 Fix #11 - Fix compilation error in Unity 2021.3 and newer 2022-07-02 09:27:26 +03:00
.editorconfig initial commot 2022-01-05 14:59:05 +03:00
.gitignore initial commot 2022-01-05 14:59:05 +03:00
Editor.Extras.meta initial commot 2022-01-05 14:59:05 +03:00
Editor.Integrations.meta Add OdinInspector integration 2022-05-18 20:03:06 +03:00
Editor.meta initial commot 2022-01-05 14:59:05 +03:00
Installer.unitypackage Access to unity internal with InternalsVisibleTo instead of reflection 2022-05-08 14:31:18 +03:00
Installer.unitypackage.meta Access to unity internal with InternalsVisibleTo instead of reflection 2022-05-08 14:31:18 +03:00
LICENSE.md Add license 2022-01-05 15:45:02 +03:00
LICENSE.md.meta Add license 2022-01-05 15:45:02 +03:00
package.json Up version 2022-07-02 09:37:09 +03:00
package.json.meta initial commot 2022-01-05 14:59:05 +03:00
README.md Closes #5 - Add AssetsOnly attribute 2022-06-10 15:34:49 +03:00
README.md.meta Update readme 2022-01-05 16:14:54 +03:00
Runtime.meta initial commot 2022-01-05 14:59:05 +03:00
Unity.InternalAPIEditorBridge.012.meta Access to unity internal with InternalsVisibleTo instead of reflection 2022-05-08 14:31:18 +03:00

Tri Inspector Github license Unity 2020.3 GitHub package.json version openupm

Advanced inspector attributes for Unity

Tri-Inspector-Demo

How to Install

Library distributed as git package (How to install package from git URL)
Git URL: https://github.com/codewriter-packages/Tri-Inspector.git

After package installation run the Installer by double clicking on it. TriInspector-Installer

Roadmap GitHub Repo stars

Each star ★ on the project page brings new features closer. See roadmap and more info here.

Attributes

Misc

ShowInInspector

Shows non-serialized property in the inspector.

ShowInInspector

private float _field;

[ShowInInspector]
public float ReadOnlyProperty => _field;

[ShowInInspector]
public float EditableProperty
{
    get => _field;
    set => _field = value;
}

PropertyOrder

Changes property order in the inspector.

PropertyOrder

public float first;

[PropertyOrder(0)]
public float second;

ReadOnly

Makes property non-editable in the inspector.

ReadOnly

[ReadOnly]
public Vector3 vec;

OnValueChanged

Invokes callback on property modification.

[OnValueChanged(nameof(OnMaterialChanged))]
public Material mat; 

private void OnMaterialChanged()
{
    Debug.Log("Material changed!");
}

Validation

Tri Inspector has some builtin validators such as missing reference and type mismatch error. Additionally you can mark out your code with validation attributes or even write own validators.

Builtin-Validators

Required

Required

[Required]
public Material mat;

ValidateInput

ValidateInput

[ValidateInput(nameof(ValidateTexture))]
public Texture tex;

private TriValidationResult ValidateTexture()
{
    if (tex == null) return TriValidationResult.Error("Tex is null");
    if (!tex.isReadable) return TriValidationResult.Warning("Tex must be readable");
    return TriValidationResult.Valid;
}

InfoBox

InfoBox

[Title("InfoBox Message Types")]
[InfoBox("Default info box")]
public int a;

[InfoBox("None info box", TriMessageType.None)]
public int b;

[InfoBox("Warning info box", TriMessageType.Warning)]
public int c;

[InfoBox("Error info box", TriMessageType.Error)]
public int d;

[InfoBox("$" + nameof(DynamicInfo), visibleIf: nameof(VisibleInEditMode))]
public Vector3 vec;

private string DynamicInfo => "Dynamic info box: " + DateTime.Now.ToLongTimeString();

private bool VisibleInEditMode => !Application.isPlaying;

AssetsOnly

AssetsOnly

[AssetsOnly]
public GameObject obj;

Styling

Title

Title

[Title("My Title")]
public string val;

[Title("$" + nameof(_myTitleField))]
public Rect rect;

[Title("$" + nameof(MyTitleProperty))]
public Vector3 vec;

[Title("Button Title")]
[Button]
public void MyButton()
{
}

private string _myTitleField = "Serialized Title";

private string MyTitleProperty => DateTime.Now.ToLongTimeString();

HideLabel

HideLabel

[Title("Wide Vector")]
[HideLabel]
public Vector3 vector;

[Title("Wide String")]
[HideLabel]
public string str;

LabelText

LabelText

[LabelText("Custom Label")]
public int val;

[LabelText("$" + nameof(DynamicLabel))]
public Vector3 vec;

public string DynamicLabel => DateTime.Now.ToShortTimeString();

LabelWidth

LabelWidth

public int defaultWidth;

[LabelWidth(40)]
public int thin;

[LabelWidth(300)]
public int customInspectorVeryLongPropertyName;

GUIColor

GUIColor

[GUIColor(0.8f, 1.0f, 0.6f)]
public Vector3 vec;

[GUIColor(0.6f, 0.9f, 1.0f)]
[Button]
public void BlueButton() { }

[GUIColor(1.0f, 0.6f, 0.6f)]
[Button]
public void RedButton() { }

Indent

Indent

[Title("Custom Indent")]
[Indent]
public int a;

[Indent(2)]
public int b;

[Indent(3)]
public int c;

[Indent(4)]
public int d;

PropertySpace

PropertySpace

[Space, PropertyOrder(0)]
public Vector3 vecField;

[ShowInInspector, PropertyOrder(1)]
[PropertySpace(SpaceBefore = 10, SpaceAfter = 30)]
public Rect RectProperty { get; set; }

[PropertyOrder(2)]
public bool b;

PropertyTooltip

PropertyTooltip

[PropertyTooltip("This is tooltip")]
public Rect rect;

[PropertyTooltip("$" + nameof(DynamicTooltip))]
public Vector3 vec;

public string DynamicTooltip => DateTime.Now.ToShortTimeString();

InlineEditor

InlineEditor

[InlineEditor]
public Material mat;

InlineProperty

InlineProperty

public MinMax rangeFoldout;

[InlineProperty(LabelWidth = 40)]
public MinMax rangeInline;

[Serializable]
public class MinMax
{
    public int min;
    public int max;
}

Collections

ListDrawerSettings

ListDrawerSettings

[ListDrawerSettings(Draggable = true,
                    HideAddButton = false,
                    HideRemoveButton = false,
                    AlwaysExpanded = false)]
public List<Material> list;

[ListDrawerSettings(Draggable = false, AlwaysExpanded = true)]
public Vector3[] vectors;

TableList

TableList

[TableList(Draggable = true,
           HideAddButton = false,
           HideRemoveButton = false,
           AlwaysExpanded = false)]
public List<TableItem> table;

[Serializable]
public class TableItem
{
    [Required]
    public Texture icon;
    public string description;

    [Group("Combined"), LabelWidth(16)]
    public string A, B, C;

    [Button, Group("Actions")]
    public void Test1() { }

    [Button, Group("Actions")]
    public void Test2() { }
}

Conditionals

ShowIf

ShowIf

public Material material;
public bool toggle;
public SomeEnum someEnum;

[ShowIf(nameof(material), null)]
public Vector3 showWhenMaterialIsNull;

[ShowIf(nameof(toggle))]
public Vector3 showWhenToggleIsTrue;

[ShowIf(nameof(toggle), false)]
public Vector3 showWhenToggleIsFalse;

[ShowIf(nameof(someEnum), SomeEnum.Two)]
public Vector3 showWhenSomeEnumIsTwo;

public enum SomeEnum { One, Two, Three }

HideIf

public bool visible;

[HideIf(nameof(visible))]
public float val;

EnableIf

public bool visible;

[EnableIf(nameof(visible))]
public float val;

DisableIf

public bool visible;

[DisableIf(nameof(visible))]
public float val;

HideInPlayMode / ShowInPlayMode

[HideInPlayMode] [ShowInPlayMode]

DisableInPlayMode / EnableInPlayMode

[DisableInPlayMode] [EnableInPlayMode]

HideInEditMode / ShowInEditMode

[HideInEditMode] [ShowInEditMode]

DisableInEditMode / EnableInEditMode

[DisableInEditMode] [EnableInEditMode]

Buttons

Button

Button

[Button("Click me!")]
private void DoButton()
{
    Debug.Log("Button clicked!");
}

EnumToggleButtons

EnumToggleButtons

[EnumToggleButtons] public SomeEnum someEnum;
[EnumToggleButtons] public SomeFlags someFlags;

public enum SomeEnum { One, Two, Three }

[Flags] public enum SomeFlags
{
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    AB = A | B,
    BC = B | C,
}

Debug

ShowDrawerChain

ShowDrawerChain

[ShowDrawerChain]
[Indent]
[PropertySpace]
[Title("Custom Title")]
[GUIColor(1.0f, 0.8f, 0.8f)]
public Vector3 vec;

Groups

Groups

[DeclareHorizontalGroup("header")]
[DeclareBoxGroup("header/left", Title = "My Left Box")]
[DeclareVerticalGroup("header/right")]
[DeclareBoxGroup("header/right/top", Title = "My Right Box")]
[DeclareTabGroup("header/right/tabs")]
[DeclareBoxGroup("body")]
public class GroupDemo : MonoBehaviour
{
    [Group("header/left")] public bool prop1;
    [Group("header/left")] public int prop2;
    [Group("header/left")] public string prop3;
    [Group("header/left")] public Vector3 prop4;

    [Group("header/right/top")] public string rightProp;

    [Group("body")] public string body1;
    [Group("body")] public string body2;

    [Group("header/right/tabs"), Tab("One")] public float tabOne;
    [Group("header/right/tabs"), Tab("Two")] public float tabTwo;
    [Group("header/right/tabs"), Tab("Three")] public float tabThree;

    [Group("header/right"), Button("Click me!")]
    public void MyButton()
    {
    }
}

Customization

Custom Drawers

Custom Value Drawer
using TriInspector;
using UnityEditor;
using UnityEngine;

[assembly: RegisterTriValueDrawer(typeof(BoolDrawer), TriDrawerOrder.Fallback)]

public class BoolDrawer : TriValueDrawer<bool>
{
    public override float GetHeight(float width, TriValue<bool> propertyValue, TriElement next)
    {
        return EditorGUIUtility.singleLineHeight;
    }

    public override void OnGUI(Rect position, TriValue<bool> propertyValue, TriElement next)
    {
        var value = propertyValue.Value;

        EditorGUI.BeginChangeCheck();

        value = EditorGUI.Toggle(position, propertyValue.Property.DisplayNameContent, value);

        if (EditorGUI.EndChangeCheck())
        {
            propertyValue.Value = value;
        }
    }
}
Custom Attribute Drawer
using TriInspector;
using UnityEditor;
using UnityEngine;

[assembly: RegisterTriAttributeDrawer(typeof(LabelWidthDrawer), TriDrawerOrder.Decorator)]

public class LabelWidthDrawer : TriAttributeDrawer<LabelWidthAttribute>
{
    public override void OnGUI(Rect position, TriProperty property, TriElement next)
    {
        var oldLabelWidth = EditorGUIUtility.labelWidth;

        EditorGUIUtility.labelWidth = Attribute.Width;
        next.OnGUI(position);
        EditorGUIUtility.labelWidth = oldLabelWidth;
    }
}
Custom Group Drawer
using TriInspector;
using TriInspector.Elements;

[assembly: RegisterTriGroupDrawer(typeof(TriBoxGroupDrawer))]

public class TriBoxGroupDrawer : TriGroupDrawer<DeclareBoxGroupAttribute>
{
    public override TriPropertyCollectionBaseElement CreateElement(DeclareBoxGroupAttribute attribute)
    {
        // ...
    }
}

Validators

Custom Value Validator
using TriInspector;

[assembly: RegisterTriValueValidator(typeof(MissingReferenceValidator<>))]

public class MissingReferenceValidator<T> : TriValueValidator<T>
    where T : UnityEngine.Object
{
    public override TriValidationResult Validate(TriValue<T> propertyValue)
    {
        // ...
    }
}
Custom Attribute Validators
using TriInspector;

[assembly: RegisterTriAttributeValidator(typeof(RequiredValidator), ApplyOnArrayElement = true)]

public class RequiredValidator : TriAttributeValidator<RequiredAttribute>
{
    public override TriValidationResult Validate(TriProperty property)
    {
        // ...
    }
}

Property Processors

Custom Property Hide Processor
using TriInspector;
using UnityEngine;

[assembly: RegisterTriPropertyHideProcessor(typeof(HideInPlayModeProcessor))]

public class HideInPlayModeProcessor : TriPropertyHideProcessor<HideInPlayModeAttribute>
{
    public override bool IsHidden(TriProperty property)
    {
        return Application.isPlaying;
    }
}
Custom Property Disable Processor
using TriInspector;
using UnityEngine;

[assembly: RegisterTriPropertyDisableProcessor(typeof(DisableInPlayModeProcessor))]

public class DisableInPlayModeProcessor : TriPropertyDisableProcessor<DisableInPlayModeAttribute>
{
    public override bool IsDisabled(TriProperty property)
    {
        return Application.isPlaying;
    }
}

Integrations

Odin Inspector

Tri Inspector is able to work in compatibility mode with Odin Inspector. In this mode, the primary interface will be drawn by the Odin Inspector. However, parts of the interface can be rendered by the Tri Inspector.

In order for the interface to be rendered by Tri instead of Odin, it is necessary to mark classes with [DrawWithTriInspector] attribute.

Alternatively, you can mark the entire assembly with an attribute [assembly:DrawWithTriInspector] to draw all types in the assembly using the Tri Inspector.

Odin Validator

Tri Inspector is integrated with the Odin Validator so all validation results from Tri attributes will be shown in the Odin Validator window.

Odin-Validator-Integration

License

Tri-Inspector is MIT licensed.