Skip to content

Commit 5dc7178

Browse files
committed
Add inline fix for validation messages
1 parent 945dc0b commit 5dc7178

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

Editor.Samples/Validators/Validators_ValidateInputSample.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,24 @@ public class Validators_ValidateInputSample : ScriptableObject
66
[ValidateInput(nameof(ValidateTexture))]
77
public Texture tex;
88

9+
[ValidateInput(nameof(ValidateNumber))]
10+
public int number;
11+
912
private TriValidationResult ValidateTexture()
1013
{
1114
if (tex == null) return TriValidationResult.Error("Tex is null");
1215
if (!tex.isReadable) return TriValidationResult.Warning("Tex must be readable");
1316
return TriValidationResult.Valid;
1417
}
18+
19+
private TriValidationResult ValidateNumber()
20+
{
21+
if (number == 1)
22+
{
23+
return TriValidationResult.Valid;
24+
}
25+
26+
return TriValidationResult.Error("Number must be equal 1")
27+
.WithFix(() => number = 1, "Set to 1");
28+
}
1529
}

Editor/Elements/TriInfoBoxElement.cs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using TriInspector.Utilities;
1+
using System;
2+
using TriInspector.Utilities;
23
using TriInspectorUnityInternalBridge;
34
using UnityEditor;
45
using UnityEngine;
@@ -7,22 +8,44 @@ namespace TriInspector.Elements
78
{
89
public class TriInfoBoxElement : TriElement
910
{
11+
private const int ActionSpacing = 5;
12+
private const int ActionWidth = 100;
13+
private const int ActionWidthWithSpacing = ActionWidth + ActionSpacing * 2;
14+
1015
private readonly GUIContent _message;
1116
private readonly Texture2D _icon;
1217
private readonly Color _color;
18+
private readonly Action _inlineAction;
19+
private readonly GUIContent _inlineActionContent;
1320

14-
public TriInfoBoxElement(string message, TriMessageType type = TriMessageType.None, Color? color = null)
21+
public TriInfoBoxElement(string message, TriMessageType type = TriMessageType.None, Color? color = null,
22+
Action inlineAction = null, GUIContent inlineActionContent = null)
1523
{
1624
var messageType = GetMessageType(type);
1725
_icon = EditorGUIUtilityProxy.GetHelpIcon(messageType);
1826
_message = new GUIContent(message);
1927
_color = color ?? GetColor(type);
28+
_inlineAction = inlineAction;
29+
_inlineActionContent = inlineActionContent ?? GUIContent.none;
2030
}
2131

2232
public override float GetHeight(float width)
2333
{
34+
var labelWidth = width;
35+
36+
if (_inlineAction != null)
37+
{
38+
labelWidth -= ActionWidthWithSpacing;
39+
}
40+
2441
var style = _icon == null ? Styles.InfoBoxContentNone : Styles.InfoBoxContent;
25-
var height = style.CalcHeight(_message, width);
42+
var height = style.CalcHeight(_message, labelWidth);
43+
44+
if (_inlineAction != null)
45+
{
46+
height = Mathf.Max(height, CalcActionHeight() + ActionSpacing * 2);
47+
}
48+
2649
return Mathf.Max(26, height);
2750
}
2851

@@ -33,21 +56,57 @@ public override void OnGUI(Rect position)
3356
GUI.Label(position, string.Empty, Styles.InfoBoxBg);
3457
}
3558

59+
var labelWidth = position.width;
60+
61+
if (_inlineAction != null)
62+
{
63+
labelWidth -= ActionWidthWithSpacing;
64+
}
65+
3666
if (_icon != null)
3767
{
68+
var labelRect = new Rect(position)
69+
{
70+
width = labelWidth,
71+
};
72+
3873
var iconRect = new Rect(position)
3974
{
4075
xMin = position.xMin + 4,
4176
width = 20,
4277
};
4378

44-
GUI.Label(position, _message, Styles.InfoBoxContent);
79+
GUI.Label(labelRect, _message, Styles.InfoBoxContent);
4580
GUI.DrawTexture(iconRect, _icon, ScaleMode.ScaleToFit);
4681
}
4782
else
4883
{
4984
GUI.Label(position, _message, Styles.InfoBoxContentNone);
5085
}
86+
87+
if (_inlineAction != null)
88+
{
89+
var fixHeight = CalcActionHeight();
90+
91+
var actionRect = new Rect(position)
92+
{
93+
xMax = position.xMax - ActionSpacing,
94+
xMin = position.xMax - ActionWidth - ActionSpacing,
95+
yMin = position.center.y - fixHeight / 2,
96+
yMax = position.center.y + fixHeight / 2,
97+
};
98+
99+
if (GUI.Button(actionRect, _inlineActionContent, Styles.InfoBoxInlineAction))
100+
{
101+
_inlineAction?.Invoke();
102+
}
103+
}
104+
}
105+
106+
107+
private float CalcActionHeight()
108+
{
109+
return Styles.InfoBoxInlineAction.CalcHeight(_inlineActionContent, ActionWidth);
51110
}
52111

53112
private static Color GetColor(TriMessageType type)
@@ -82,6 +141,7 @@ private static class Styles
82141
public static readonly GUIStyle InfoBoxBg;
83142
public static readonly GUIStyle InfoBoxContent;
84143
public static readonly GUIStyle InfoBoxContentNone;
144+
public static readonly GUIStyle InfoBoxInlineAction;
85145

86146
static Styles()
87147
{
@@ -97,6 +157,10 @@ static Styles()
97157
{
98158
padding = new RectOffset(26, 4, 4, 4),
99159
};
160+
InfoBoxInlineAction = new GUIStyle(GUI.skin.button)
161+
{
162+
wordWrap = true,
163+
};
100164
}
101165
}
102166
}

Editor/ValidatorsDrawer.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using TriInspector.Elements;
34
using UnityEditor;
45

@@ -61,11 +62,22 @@ private bool GenerateValidationResults()
6162

6263
foreach (var result in _validationResults)
6364
{
64-
AddChild(new TriInfoBoxElement(result.Message, result.MessageType));
65+
var infoBox = result.FixAction != null
66+
? new TriInfoBoxElement(result.Message, result.MessageType,
67+
inlineAction: () => ExecuteFix(result.FixAction),
68+
inlineActionContent: result.FixActionContent)
69+
: new TriInfoBoxElement(result.Message, result.MessageType);
70+
71+
AddChild(infoBox);
6572
}
6673

6774
return true;
6875
}
76+
77+
private void ExecuteFix(Action fixAction)
78+
{
79+
_property.ModifyAndRecordForUndo(targetIndex => fixAction?.Invoke());
80+
}
6981
}
7082
}
7183
}

Runtime/TriValidationResult.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
1-
namespace TriInspector
1+
using System;
2+
using UnityEngine;
3+
4+
namespace TriInspector
25
{
36
public readonly struct TriValidationResult
47
{
58
public static TriValidationResult Valid => new TriValidationResult(true, null, TriMessageType.None);
69

7-
public TriValidationResult(bool valid, string message, TriMessageType messageType)
10+
public TriValidationResult(bool valid, string message, TriMessageType messageType,
11+
Action fixAction = null, GUIContent fixActionContent = null)
812
{
913
IsValid = valid;
1014
Message = message;
1115
MessageType = messageType;
16+
FixAction = fixAction;
17+
FixActionContent = fixActionContent;
1218
}
1319

1420
public bool IsValid { get; }
1521
public string Message { get; }
1622
public TriMessageType MessageType { get; }
23+
public Action FixAction { get; }
24+
public GUIContent FixActionContent { get; }
25+
26+
public TriValidationResult WithFix(Action action, string name = null)
27+
{
28+
return new TriValidationResult(IsValid, Message, MessageType, action, new GUIContent(name));
29+
}
1730

1831
public static TriValidationResult Info(string error)
1932
{
2033
return new TriValidationResult(false, error, TriMessageType.Info);
2134
}
22-
35+
2336
public static TriValidationResult Error(string error)
2437
{
2538
return new TriValidationResult(false, error, TriMessageType.Error);

0 commit comments

Comments
 (0)