mirror of
https://github.com/codewriter-packages/Tri-Inspector.git
synced 2025-01-22 00:08:51 -05:00
Integration with Odin Inspector and Validator
This commit is contained in:
parent
b258813852
commit
892cfdf07d
@ -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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
Editor.Integrations/Odin/OdinFieldDrawer.cs
Normal file
69
Editor.Integrations/Odin/OdinFieldDrawer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
Editor.Integrations/Odin/OdinFieldValidator.cs
Normal file
50
Editor.Integrations/Odin/OdinFieldValidator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
3
Editor.Integrations/Odin/OdinFieldValidator.cs.meta
Normal file
3
Editor.Integrations/Odin/OdinFieldValidator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50b3a32d5da945fbbdf9a981a9de5f86
|
||||
timeCreated: 1653119957
|
54
Editor.Integrations/Odin/OdinObjectDrawer.cs
Normal file
54
Editor.Integrations/Odin/OdinObjectDrawer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
3
Editor.Integrations/Odin/OdinObjectDrawer.cs.meta
Normal file
3
Editor.Integrations/Odin/OdinObjectDrawer.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a211e55ec804aa4b8554563e98d9b04
|
||||
timeCreated: 1653129453
|
52
Editor.Integrations/Odin/OdinObjectValidator.cs
Normal file
52
Editor.Integrations/Odin/OdinObjectValidator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
3
Editor.Integrations/Odin/OdinObjectValidator.cs.meta
Normal file
3
Editor.Integrations/Odin/OdinObjectValidator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbb0d53e419644038a32323fb3083fb3
|
||||
timeCreated: 1653123315
|
33
Editor.Integrations/Odin/TriOdinExtensions.cs
Normal file
33
Editor.Integrations/Odin/TriOdinExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
3
Editor.Integrations/Odin/TriOdinExtensions.cs.meta
Normal file
3
Editor.Integrations/Odin/TriOdinExtensions.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c13b27eaa04b477db49de9a0582608b5
|
||||
timeCreated: 1653124004
|
@ -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()
|
||||
|
@ -1,11 +0,0 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace TriInspector.Editors
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TriMonoBehaviour), true, isFallback = true)]
|
||||
internal sealed class TriMonoBehaviourEditor : TriEditor
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54df0926814e4714b27ffbe0191516f5
|
||||
timeCreated: 1652774156
|
@ -1,10 +0,0 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace TriInspector.Editors
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TriScriptableObject), true, isFallback = true)]
|
||||
internal sealed class TriScriptableObjectEditor : TriEditor
|
||||
{
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a26587373eeb4f0fb8f99540b0ac352d
|
||||
timeCreated: 1652774174
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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]
|
||||
|
@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 468b264c3e164c0681760c3d98451466
|
||||
timeCreated: 1638857169
|
||||
guid: 9bb1d443163b4a26908eb26ba297c1d6
|
||||
timeCreated: 1653126491
|
67
Editor/TriPropertyTreeForSerializedObject.cs
Normal file
67
Editor/TriPropertyTreeForSerializedObject.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
3
Editor/TriPropertyTreeForSerializedObject.cs.meta
Normal file
3
Editor/TriPropertyTreeForSerializedObject.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 468b264c3e164c0681760c3d98451466
|
||||
timeCreated: 1638857169
|
64
README.md
64
README.md
@ -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
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace TriInspector
|
||||
{
|
||||
public abstract class TriMonoBehaviour : MonoBehaviour
|
||||
{
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f57eec47cca7485680d88d6daf43db8d
|
||||
timeCreated: 1652774059
|
@ -1,8 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace TriInspector
|
||||
{
|
||||
public abstract class TriScriptableObject : ScriptableObject
|
||||
{
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a07f45c37367452280cda2001e97816e
|
||||
timeCreated: 1652774082
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user