Integration with Odin Inspector and Validator

This commit is contained in:
VladV 2022-05-21 11:49:12 +03:00
parent b258813852
commit 892cfdf07d
28 changed files with 439 additions and 300 deletions

View File

@ -1,40 +0,0 @@
using System;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities.Editor;
using UnityEditor;
using UnityEngine;
namespace TriInspector.Editor.Integrations.Odin
{
[DrawerPriority(0.0, 0.0, 6000.0)]
public class DrawWithTriInspectorDrawer<T> : OdinAttributeDrawer<DrawWithTriInspectorAttribute, T>, IDisposable
{
private TriPropertyTreeForOdin<T> _propertyTree;
protected override void Initialize()
{
base.Initialize();
_propertyTree = new TriPropertyTreeForOdin<T>(ValueEntry);
}
public void Dispose()
{
_propertyTree?.Dispose();
}
protected override void DrawPropertyLayout(GUIContent label)
{
var propertyState = ValueEntry.Property.State;
propertyState.Expanded = SirenixEditorGUI.Foldout(propertyState.Expanded, label);
if (propertyState.Expanded)
{
EditorGUI.indentLevel++;
_propertyTree.Draw();
EditorGUI.indentLevel--;
}
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities.Editor;
using TriInspector.Utilities;
using UnityEngine;
namespace TriInspector.Editor.Integrations.Odin
{
[DrawerPriority(0.0, 10000.0, 1.0)]
public class OdinFieldDrawer<T> : OdinAttributeDrawer<DrawWithTriInspectorAttribute, T>, IDisposable
{
private TriPropertyTree _propertyTree;
public override bool CanDrawTypeFilter(Type type)
{
if (typeof(UnityEngine.Object).IsAssignableFrom(type))
{
return false;
}
return true;
}
protected override bool CanDrawAttributeValueProperty(InspectorProperty property)
{
if (property.IsTreeRoot)
{
return false;
}
return true;
}
protected override void Initialize()
{
base.Initialize();
_propertyTree = new TriPropertyTreeForOdin<T>(ValueEntry);
_propertyTree.Initialize(TriEditorMode.None);
}
public void Dispose()
{
_propertyTree?.Dispose();
}
protected override void DrawPropertyLayout(GUIContent label)
{
var propertyState = ValueEntry.Property.State;
propertyState.Expanded = SirenixEditorGUI.Foldout(propertyState.Expanded, label);
if (propertyState.Expanded)
{
using (TriGuiHelper.PushIndentLevel())
{
_propertyTree.Update();
if (_propertyTree.ValidationRequired)
{
_propertyTree.RunValidation();
}
_propertyTree.Draw();
}
}
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector.Editor.Validation;
using TriInspector.Editor.Integrations.Odin;
[assembly: RegisterValidator(typeof(OdinFieldValidator<>))]
namespace TriInspector.Editor.Integrations.Odin
{
public class OdinFieldValidator<T> : AttributeValidator<DrawWithTriInspectorAttribute, T>, IDisposable
{
private TriPropertyTreeForOdin<T> _propertyTree;
public override RevalidationCriteria RevalidationCriteria { get; }
= RevalidationCriteria.OnValueChangeOrChildValueChange;
public override bool CanValidateProperty(InspectorProperty property)
{
if (typeof(UnityEngine.Object).IsAssignableFrom(property.Info.TypeOfValue))
{
return false;
}
if (property.IsTreeRoot)
{
return false;
}
return true;
}
protected override void Initialize()
{
_propertyTree = new TriPropertyTreeForOdin<T>(ValueEntry);
_propertyTree.Initialize(TriEditorMode.None);
}
public void Dispose()
{
_propertyTree.Dispose();
}
protected override void Validate(ValidationResult result)
{
_propertyTree.Update();
_propertyTree.RunValidation();
_propertyTree.CopyValidationResultsTo(result);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 50b3a32d5da945fbbdf9a981a9de5f86
timeCreated: 1653119957

View File

@ -0,0 +1,54 @@
using System;
using Sirenix.OdinInspector.Editor;
using UnityEngine;
namespace TriInspector.Editor.Integrations.Odin
{
[DrawerPriority(0.0, 10000.0, 1.0)]
public class OdinObjectDrawer<T> : OdinAttributeDrawer<DrawWithTriInspectorAttribute, T>, IDisposable
where T : UnityEngine.Object
{
private TriPropertyTree _propertyTree;
protected override bool CanDrawAttributeValueProperty(InspectorProperty property)
{
if (!property.IsTreeRoot)
{
return false;
}
if (property.Tree.UnitySerializedObject == null)
{
return false;
}
return true;
}
protected override void Initialize()
{
base.Initialize();
var serializedObject = Property.Tree.UnitySerializedObject;
_propertyTree = new TriPropertyTreeForSerializedObject(serializedObject);
_propertyTree.Initialize(TriEditorMode.None);
}
public void Dispose()
{
_propertyTree?.Dispose();
}
protected override void DrawPropertyLayout(GUIContent label)
{
_propertyTree.Update();
if (_propertyTree.ValidationRequired)
{
_propertyTree.RunValidation();
}
_propertyTree.Draw();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a211e55ec804aa4b8554563e98d9b04
timeCreated: 1653129453

View File

@ -0,0 +1,52 @@
using System;
using Sirenix.OdinInspector.Editor;
using Sirenix.OdinInspector.Editor.Validation;
using TriInspector.Editor.Integrations.Odin;
using UnityEditor;
[assembly: RegisterValidator(typeof(OdinObjectValidator<>))]
namespace TriInspector.Editor.Integrations.Odin
{
public class OdinObjectValidator<T> : AttributeValidator<DrawWithTriInspectorAttribute, T>, IDisposable
where T : UnityEngine.Object
{
private TriPropertyTreeForSerializedObject _propertyTree;
private SerializedObject _serializedObject;
public override RevalidationCriteria RevalidationCriteria { get; }
= RevalidationCriteria.OnValueChangeOrChildValueChange;
public override bool CanValidateProperty(InspectorProperty property)
{
if (!property.IsTreeRoot)
{
return false;
}
return true;
}
protected override void Initialize()
{
_serializedObject = new SerializedObject(ValueEntry.SmartValue);
_propertyTree = new TriPropertyTreeForSerializedObject(_serializedObject);
_propertyTree.Initialize(TriEditorMode.None);
}
public void Dispose()
{
_propertyTree.Dispose();
_serializedObject.Dispose();
}
protected override void Validate(ValidationResult result)
{
_serializedObject.Update();
_propertyTree.Update();
_propertyTree.RunValidation();
_propertyTree.CopyValidationResultsTo(result);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bbb0d53e419644038a32323fb3083fb3
timeCreated: 1653123315

View File

@ -0,0 +1,33 @@
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor.Validation;
namespace TriInspector.Editor.Integrations.Odin
{
internal static class TriOdinExtensions
{
public static void CopyValidationResultsTo(this TriPropertyTree tree, ValidationResult result)
{
tree.EnumerateValidationResults((property, triResult) => result.Add(triResult));
}
private static void Add(this ValidationResult result, TriValidationResult src)
{
var severity = src.GetOdinValidatorSeverity();
result.Add(severity, src.Message);
}
private static ValidatorSeverity GetOdinValidatorSeverity(this TriValidationResult result)
{
switch (result.MessageType)
{
case TriMessageType.Error:
return ValidatorSeverity.Error;
case TriMessageType.Warning:
return ValidatorSeverity.Warning;
}
return ValidatorSeverity.Ignore;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c13b27eaa04b477db49de9a0582608b5
timeCreated: 1653124004

View File

@ -1,41 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using TriInspector.Elements;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace TriInspector.Editor.Integrations.Odin
{
public class TriPropertyTreeForOdin<T> : ITriPropertyParent, ITriPropertyTree
public class TriPropertyTreeForOdin<T> : TriPropertyTree
{
private readonly IPropertyValueEntry<T> _odinValueEntry;
private readonly InspectorProperty _odinProperty;
private readonly IReadOnlyList<TriProperty> _triProperties;
private readonly TriInspectorElement _triInspectorElement;
private readonly SerializedProperty _serializedProperty;
private bool _validationRequired;
public TriPropertyTreeForOdin(IPropertyValueEntry<T> odinValueEntry)
{
_odinValueEntry = odinValueEntry;
_odinProperty = odinValueEntry.Property;
_serializedProperty = _odinProperty.Tree.GetUnityPropertyForPath(_odinProperty.Path, out _);
TargetObjectType = _odinProperty.Tree.TargetType;
TargetsCount = _odinProperty.Tree.WeakTargets.Count;
TargetIsPersistent = _odinProperty.Tree.WeakTargets[0] is Object obj &&
obj != null && EditorUtility.IsPersistent(obj);
_serializedProperty = _odinProperty.Tree.GetUnityPropertyForPath(_odinProperty.Path, out _);
UpdateEmittedScriptableObject();
UpdateAfterValueModification();
_serializedProperty.serializedObject.SetIsDifferentCacheDirty();
_serializedProperty.serializedObject.Update();
_triProperties = TriTypeDefinition.GetCached(odinValueEntry.TypeOfValue)
_odinProperty.Update();
Properties = TriTypeDefinition.GetCached(odinValueEntry.TypeOfValue)
.Properties
.Select((propertyDefinition, index) =>
{
@ -43,49 +38,22 @@ namespace TriInspector.Editor.Integrations.Odin
return new TriProperty(this, this, propertyDefinition, index, serializedProperty);
})
.ToList();
_triInspectorElement = new TriInspectorElement(odinValueEntry.TypeOfValue, _triProperties);
_triInspectorElement.AttachInternal();
_triProperties.ForEach(it => it.Update());
_triProperties.ForEach(it => it.RunValidation());
}
public void Draw()
public override void Update()
{
UpdateEmittedScriptableObject();
_triProperties.ForEach(it => it.Update());
if (_validationRequired)
{
_validationRequired = false;
_triProperties.ForEach(it => it.RunValidation());
}
_triInspectorElement.Update();
var width = EditorGUIUtility.currentViewWidth;
var height = _triInspectorElement.GetHeight(width);
var rect = GUILayoutUtility.GetRect(width, height);
_triInspectorElement.OnGUI(rect);
base.Update();
}
public Type TargetObjectType { get; }
public int TargetsCount { get; }
public bool TargetIsPersistent { get; }
public void Dispose()
{
_triInspectorElement?.DetachInternal();
}
public void ForceCreateUndoGroup()
public override void ForceCreateUndoGroup()
{
_odinProperty.RecordForUndo(forceCompleteObjectUndo: true);
Undo.FlushUndoRecordObjects();
}
public void PrepareForValueModification()
public override void PrepareForValueModification()
{
var dirty = false;
dirty |= _odinValueEntry.ApplyChanges();
@ -94,12 +62,12 @@ namespace TriInspector.Editor.Integrations.Odin
if (dirty)
{
_validationRequired = true;
GUIHelper.RequestRepaint();
RequestValidation();
RequestRepaint();
}
}
public void UpdateAfterValueModification()
public override void UpdateAfterValueModification()
{
UpdateEmittedScriptableObject();
@ -109,21 +77,25 @@ namespace TriInspector.Editor.Integrations.Odin
_odinProperty.Update();
}
public void RequestRepaint()
public override void RequestRepaint()
{
base.RequestRepaint();
GUIHelper.RequestRepaint();
}
public object GetValue(int targetIndex)
public override object GetValue(int targetIndex)
{
return _odinValueEntry.Values[targetIndex];
}
public void NotifyValueChanged(TriProperty property)
public override void NotifyValueChanged(TriProperty property)
{
ApplyEmittedScriptableObject();
_odinValueEntry.Values.ForceMarkDirty();
RequestValidation();
}
private void UpdateEmittedScriptableObject()

View File

@ -1,11 +0,0 @@
using UnityEditor;
namespace TriInspector.Editors
{
[CanEditMultipleObjects]
[CustomEditor(typeof(TriMonoBehaviour), true, isFallback = true)]
internal sealed class TriMonoBehaviourEditor : TriEditor
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 54df0926814e4714b27ffbe0191516f5
timeCreated: 1652774156

View File

@ -1,10 +0,0 @@
using UnityEditor;
namespace TriInspector.Editors
{
[CanEditMultipleObjects]
[CustomEditor(typeof(TriScriptableObject), true, isFallback = true)]
internal sealed class TriScriptableObjectEditor : TriEditor
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: a26587373eeb4f0fb8f99540b0ac352d
timeCreated: 1652774174

View File

@ -9,7 +9,7 @@ namespace TriInspector
{
private static readonly Stack<Editor> EditorStack = new Stack<Editor>();
private TriPropertyTree _inspector;
private TriPropertyTreeForSerializedObject _inspector;
private TriEditorMode _editorMode;
@ -39,7 +39,14 @@ namespace TriInspector
return;
}
_inspector = TriPropertyTree.Create(serializedObject, _editorMode);
if (serializedObject.targetObject == null)
{
EditorGUILayout.HelpBox("Script is missing", MessageType.Warning);
return;
}
_inspector = new TriPropertyTreeForSerializedObject(serializedObject);
_inspector.Initialize(_editorMode);
}
serializedObject.UpdateIfRequiredOrScript();
@ -59,8 +66,6 @@ namespace TriInspector
{
if (_inspector.ValidationRequired)
{
_inspector.ValidationRequired = false;
_inspector.RunValidation();
}
}
@ -73,7 +78,7 @@ namespace TriInspector
Profiler.BeginSample("TriInspector.DoLayout()");
try
{
_inspector.DoLayout();
_inspector.Draw();
}
finally
{
@ -88,8 +93,6 @@ namespace TriInspector
if (_inspector.RepaintRequired)
{
_inspector.RepaintRequired = false;
Repaint();
}
}

View File

@ -27,7 +27,7 @@ namespace TriInspector
private string _isExpandedPrefsKey;
internal TriProperty(
ITriPropertyTree propertyTree,
TriPropertyTree propertyTree,
ITriPropertyParent parent,
TriPropertyDefinition definition,
int propertyIndex,
@ -219,7 +219,7 @@ namespace TriInspector
: throw new InvalidOperationException("Cannot read ArrayElementProperties for " + PropertyType);
[PublicAPI]
public ITriPropertyTree PropertyTree { get; }
public TriPropertyTree PropertyTree { get; }
[PublicAPI]
[CanBeNull]
@ -388,6 +388,25 @@ namespace TriInspector
}
}
internal void EnumerateValidationResults(Action<TriProperty, TriValidationResult> call)
{
if (_validationResults != null)
{
foreach (var result in _validationResults)
{
call.Invoke(this, result);
}
}
if (_childrenProperties != null)
{
foreach (var childrenProperty in _childrenProperties)
{
childrenProperty.EnumerateValidationResults(call);
}
}
}
[PublicAPI]
public bool TryGetSerializedProperty(out SerializedProperty serializedProperty)
{

View File

@ -1,34 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using TriInspector.Elements;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace TriInspector
{
public sealed class TriPropertyTree : ITriPropertyParent, ITriPropertyTree
public abstract class TriPropertyTree : ITriPropertyParent
{
private readonly TriEditorMode _mode;
private readonly TriInspectorElement _inspectorElement;
private TriInspectorElement _inspectorElement;
private TriEditorMode _mode;
private TriPropertyTree([NotNull] SerializedObject serializedObject, TriEditorMode mode)
public IReadOnlyList<TriProperty> Properties { get; protected set; }
public bool IsInlineEditor => (_mode & TriEditorMode.InlineEditor) != 0;
public Type TargetObjectType { get; protected set; }
public int TargetsCount { get; protected set; }
public bool TargetIsPersistent { get; protected set; }
public bool ValidationRequired { get; private set; }
public bool RepaintRequired { get; private set; }
public void Initialize(TriEditorMode mode)
{
SerializedObject = serializedObject ?? throw new ArgumentNullException(nameof(serializedObject));
TargetObjects = serializedObject.targetObjects;
TargetObjectType = TargetObjects[0].GetType();
Properties = TriTypeDefinition.GetCached(TargetObjectType)
.Properties
.Select((propertyDefinition, index) =>
{
var serializedProperty = serializedObject.FindProperty(propertyDefinition.Name);
return new TriProperty(this, this, propertyDefinition, index, serializedProperty);
})
.ToList();
_mode = mode;
_inspectorElement = new TriInspectorElement(TargetObjectType, Properties);
_inspectorElement.AttachInternal();
@ -37,37 +32,7 @@ namespace TriInspector
RunValidation();
}
[PublicAPI]
public IReadOnlyList<TriProperty> Properties { get; }
[PublicAPI]
public Object[] TargetObjects { get; }
[PublicAPI]
public Type TargetObjectType { get; }
[PublicAPI]
public int TargetsCount => TargetObjects.Length;
private SerializedObject SerializedObject { get; }
public bool IsInlineEditor => (_mode & TriEditorMode.InlineEditor) != 0;
public bool TargetIsPersistent => TargetObjects[0] is var targetObject &&
targetObject != null && !EditorUtility.IsPersistent(targetObject);
internal bool RepaintRequired { get; set; }
internal bool ValidationRequired { get; set; }
object ITriPropertyParent.GetValue(int targetIndex) => TargetObjects[targetIndex];
internal static TriPropertyTree Create(SerializedObject scriptableObject,
TriEditorMode mode = TriEditorMode.None)
{
return new TriPropertyTree(scriptableObject, mode);
}
public void Dispose()
public virtual void Dispose()
{
if (!_inspectorElement.IsAttached)
{
@ -77,7 +42,7 @@ namespace TriInspector
_inspectorElement.DetachInternal();
}
internal void Update()
public virtual void Update()
{
foreach (var property in Properties)
{
@ -85,8 +50,10 @@ namespace TriInspector
}
}
internal void RunValidation()
public void RunValidation()
{
ValidationRequired = false;
foreach (var property in Properties)
{
property.RunValidation();
@ -95,8 +62,10 @@ namespace TriInspector
RequestRepaint();
}
internal void DoLayout()
public void Draw()
{
RepaintRequired = false;
_inspectorElement.Update();
var width = EditorGUIUtility.currentViewWidth;
var height = _inspectorElement.GetHeight(width);
@ -104,38 +73,15 @@ namespace TriInspector
_inspectorElement.OnGUI(rect);
}
public void ForceCreateUndoGroup()
public void EnumerateValidationResults(Action<TriProperty, TriValidationResult> call)
{
Undo.RegisterCompleteObjectUndo(TargetObjects, "Inspector");
Undo.FlushUndoRecordObjects();
}
public void PrepareForValueModification()
{
if (SerializedObject.ApplyModifiedProperties())
foreach (var triProperty in Properties)
{
RequestValidation();
RequestRepaint();
triProperty.EnumerateValidationResults(call);
}
}
public void UpdateAfterValueModification()
{
SerializedObject.SetIsDifferentCacheDirty();
SerializedObject.Update();
}
public void NotifyValueChanged(TriProperty property)
{
foreach (var targetObject in TargetObjects)
{
EditorUtility.SetDirty(targetObject);
}
RequestValidation();
}
public void RequestRepaint()
public virtual void RequestRepaint()
{
RepaintRequired = true;
}
@ -143,19 +89,15 @@ namespace TriInspector
public void RequestValidation()
{
ValidationRequired = true;
RequestRepaint();
}
}
public interface ITriPropertyTree : IDisposable
{
Type TargetObjectType { get; }
int TargetsCount { get; }
bool TargetIsPersistent { get; }
void ForceCreateUndoGroup();
void PrepareForValueModification();
void UpdateAfterValueModification();
void RequestRepaint();
public abstract object GetValue(int targetIndex);
public abstract void NotifyValueChanged(TriProperty property);
public abstract void ForceCreateUndoGroup();
public abstract void PrepareForValueModification();
public abstract void UpdateAfterValueModification();
}
[Flags]

View File

@ -1,3 +1,3 @@
fileFormatVersion: 2
guid: 468b264c3e164c0681760c3d98451466
timeCreated: 1638857169
guid: 9bb1d443163b4a26908eb26ba297c1d6
timeCreated: 1653126491

View File

@ -0,0 +1,67 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using UnityEditor;
namespace TriInspector
{
public sealed class TriPropertyTreeForSerializedObject : TriPropertyTree
{
private readonly SerializedObject _serializedObject;
public TriPropertyTreeForSerializedObject([NotNull] SerializedObject serializedObject)
{
_serializedObject = serializedObject ?? throw new ArgumentNullException(nameof(serializedObject));
TargetObjectType = _serializedObject.targetObject.GetType();
TargetsCount = _serializedObject.targetObjects.Length;
TargetIsPersistent = _serializedObject.targetObject is var targetObject &&
targetObject != null && !EditorUtility.IsPersistent(targetObject);
Properties = TriTypeDefinition.GetCached(TargetObjectType)
.Properties
.Select((propertyDefinition, index) =>
{
var serializedProperty = serializedObject.FindProperty(propertyDefinition.Name);
return new TriProperty(this, this, propertyDefinition, index, serializedProperty);
})
.ToList();
}
public override object GetValue(int targetIndex)
{
return _serializedObject.targetObjects[targetIndex];
}
public override void ForceCreateUndoGroup()
{
Undo.RegisterCompleteObjectUndo(_serializedObject.targetObjects, "Inspector");
Undo.FlushUndoRecordObjects();
}
public override void PrepareForValueModification()
{
if (_serializedObject.ApplyModifiedProperties())
{
RequestValidation();
RequestRepaint();
}
}
public override void UpdateAfterValueModification()
{
_serializedObject.SetIsDifferentCacheDirty();
_serializedObject.Update();
}
public override void NotifyValueChanged(TriProperty property)
{
foreach (var targetObject in _serializedObject.targetObjects)
{
EditorUtility.SetDirty(targetObject);
}
RequestValidation();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 468b264c3e164c0681760c3d98451466
timeCreated: 1638857169

View File

@ -20,6 +20,7 @@ _Advanced inspector attributes for Unity_
- [Property Processors](#Property-Processors)
- [Integrations](#Integrations)
- [Odin Inspector](#Odin-Inspector)
- [Odin Validator](#Odin-Validator)
- [License](#License)
## How to Install
@ -644,65 +645,16 @@ 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:
- Use TriMonoBehaviour instead of MonoBehaviour
- Use TriScriptableObject instead of ScriptableObject
- Mark serializable classes with DrawWithTriInspector
In order for the interface to be rendered by Tri instead of Odin,
it is necessary to mark classes with `[DrawWithTriInspector]` attribute.
```csharp
public class ThisBehaviourDrawnByOdin : MonoBehaviour
{
[Sirenix.OdinInspector.InfoBox("Will be drawn by Odin Inspector as usual")]
[Sirenix.OdinInspector.BoxGroup("box", LabelText = "Box Group")]
public Texture tex;
### Odin Validator
[Sirenix.OdinInspector.InfoBox("Will be drawn by Odin Inspector as usual")]
public ThisClassDrawnByOdin odin;
Tri Inspector is integrated with the Odin Validator
so all validation results from Tri attributes will be shown
in the Odin Validator window.
[Sirenix.OdinInspector.InfoBox("This class marked with [DrawWithTriInspector] " +
"so will be drawn by Tri Inspector")]
public ThisClassDrawnByTri tri;
}
[DeclareBoxGroup("box", Title = "Box Group")]
public class ThisBehaviourDrawnByTri : TriMonoBehaviour
{
[TriInspector.InfoBox("Parent class inherits from TriMonoBehaviour " +
"so all fields will be drawn by Tri Inspector")]
[TriInspector.Group("box")]
public Texture tex;
[TriInspector.InfoBox("It is impossible to draw Odin inside Tri, " +
"so this field will be drawn by Tri too")]
public ThisClassDrawnByOdin wrong;
[TriInspector.InfoBox("Will be drawn by Tri Inspector too")]
// This field drawn by Tri Inspector
public ThisClassDrawnByTri tri;
}
[Serializable]
public class ThisClassDrawnByOdin
{
[Sirenix.OdinInspector.LabelText("Float Field")]
public float f;
[Sirenix.OdinInspector.ListDrawerSettings(Expanded = true)]
public List<Material> materials;
}
[Serializable, DrawWithTriInspector]
public class ThisClassDrawnByTri
{
[TriInspector.LabelText("Float Field")]
public float f;
[TriInspector.ListDrawerSettings(AlwaysExpanded = true)]
public List<Material> materials;
}
```
![Odin-Inspector-Integration](https://user-images.githubusercontent.com/26966368/169118626-dc5e5f10-2274-4232-967b-2811fb7fd34b.png)
![Odin-Validator-Integration](https://user-images.githubusercontent.com/26966368/169645537-d8f0b50f-46af-4804-95e8-337ff3b5ae83.png)
## License

View File

@ -1,8 +0,0 @@
using UnityEngine;
namespace TriInspector
{
public abstract class TriMonoBehaviour : MonoBehaviour
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: f57eec47cca7485680d88d6daf43db8d
timeCreated: 1652774059

View File

@ -1,8 +0,0 @@
using UnityEngine;
namespace TriInspector
{
public abstract class TriScriptableObject : ScriptableObject
{
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: a07f45c37367452280cda2001e97816e
timeCreated: 1652774082

View File

@ -2,7 +2,7 @@
"name": "com.codewriter.triinspector",
"displayName": "Tri Inspector",
"description": "Better inspector and validator for Unity",
"version": "1.0.1",
"version": "1.0.2",
"unity": "2020.3",
"author": "CodeWriter (https://github.com/orgs/codewriter-packages)",
"homepage": "https://github.com/codewriter-packages/Tri-Inspector#readme",