Skip to content

Commit

Permalink
Merge pull request #46 from arimger/develop
Browse files Browse the repository at this point in the history
Develop - 0.11.3
  • Loading branch information
arimger authored Jun 5, 2022
2 parents 1076212 + 7180aa5 commit 4cd14d0
Show file tree
Hide file tree
Showing 28 changed files with 288 additions and 61 deletions.
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ csharp_preferred_modifier_order = private,protected,internal,public,static,exter
csharp_prefer_braces = true:silent
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:silent
csharp_style_inlined_variable_declaration = true:silent
###############################
# C# Formatting Rules #
###############################
Expand Down
11 changes: 11 additions & 0 deletions Assets/Editor Toolbox/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.11.3 [05.06.2022]

### Added:
- 'ApplyCondition' property to decorators (possibility to apply property condition state (disabled/hidden) to associated decorators
- Begin/EndVerticalAttribute
- Optional labels property ('OptionHandle') for the PresetAttribute

### Changed:
- Fix overriding labels in ReorderableLists
- Fix drawing MinMaxSlider in indentations

## 0.11.1 [08.05.2022]

### Added:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

namespace Toolbox.Editor.Drawers
{
using Toolbox.Editor.Internal;

[CustomPropertyDrawer(typeof(MinMaxSliderAttribute))]
public class MinMaxSliderAttributeDrawer : PropertyDrawerBase
{
Expand All @@ -20,7 +22,11 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU

label = EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
ToolboxEditorGui.DrawMinMaxSlider(position, label, ref xValue, ref yValue, minValue, maxValue);
using (new ZeroIndentScope())
{
ToolboxEditorGui.DrawMinMaxSlider(position, label, ref xValue, ref yValue, minValue, maxValue);
}

if (EditorGUI.EndChangeCheck())
{
property.vector2Value = new Vector2(xValue, yValue);
Expand Down
104 changes: 76 additions & 28 deletions Assets/Editor Toolbox/Editor/Drawers/Regular/PresetAttributeDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections;

using UnityEditor;
using UnityEngine;
Expand All @@ -9,30 +8,19 @@ namespace Toolbox.Editor.Drawers
[CustomPropertyDrawer(typeof(PresetAttribute))]
public class PresetAttributeDrawer : PropertyDrawerBase
{
protected override float GetPropertyHeightSafe(SerializedProperty property, GUIContent label)
private IList GetPresetList(object parentObject, string sourceHandle, SerializedProperty property)
{
return base.GetPropertyHeightSafe(property, label);
}

protected override void OnGUISafe(Rect position, SerializedProperty property, GUIContent label)
{
//NOTE: this implementation does not support multiple different sources
var sourceHandle = Attribute.SourceHandle;
var declaringObject = property.GetDeclaringObject();
//extract (if available) the real preset value
if (!ValueExtractionHelper.TryGetValue(sourceHandle, declaringObject, out var sourceValue))
if (!ValueExtractionHelper.TryGetValue(sourceHandle, parentObject, out var sourceValue))
{
ToolboxEditorLog.MemberNotFoundWarning(attribute, property, sourceHandle);
EditorGUI.PropertyField(position, property, label);
return;
return null;
}

if (!(sourceValue is IList presetList))
{
ToolboxEditorLog.AttributeUsageWarning(attribute, property,
string.Format("Preset ({0}) has to be a one-dimensional collection (array or list).", sourceHandle));
EditorGUI.PropertyField(position, property, label);
return;
string.Format("Values preset ({0}) has to be a one-dimensional collection (array or list).", sourceHandle));
return null;
}

var sourceType = sourceValue.GetType();
Expand All @@ -44,36 +32,96 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
{
ToolboxEditorLog.AttributeUsageWarning(attribute, property,
"Type mismatch between serialized property and given Preset.");
EditorGUI.PropertyField(position, property, label);
return;
return null;
}

return presetList;
}

private string[] GetOptions(IList presetList)
{
var itemsCount = presetList.Count;
var objects = new object[itemsCount];
var options = new string[itemsCount];
for (var i = 0; i < itemsCount; i++)
{
objects[i] = presetList[i];
options[i] = presetList[i]?.ToString();
}

var value = property.GetProperValue(fieldInfo, declaringObject);
var index = Array.IndexOf(objects, value);
return options;
}

private string[] GetOptions(IList presetList, object parentObject, string optionHandle, SerializedProperty property)
{
if (string.IsNullOrEmpty(optionHandle))
{
return GetOptions(presetList);
}

if (!ValueExtractionHelper.TryGetValue(optionHandle, parentObject, out var optionValue))
{
ToolboxEditorLog.MemberNotFoundWarning(attribute, property, optionHandle);
return GetOptions(presetList);
}

if (!(optionValue is IList optionList))
{
ToolboxEditorLog.AttributeUsageWarning(attribute, property,
string.Format("Options preset ({0}) has to be a one-dimensional collection (array or list).", optionHandle));
return GetOptions(presetList);
}

var presetsCount = presetList.Count;
var optionsCount = optionList.Count;
var options = new string[presetsCount];
for (int i = 0; i < presetsCount; i++)
{
options[i] = i < optionsCount
? optionList[i]?.ToString()
: presetList[i]?.ToString();
}

return options;
}


protected override float GetPropertyHeightSafe(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeightSafe(property, label);
}

protected override void OnGUISafe(Rect position, SerializedProperty property, GUIContent label)
{
//NOTE: this implementation does not support multiple different sources
var sourceHandle = Attribute.SourceHandle;
var optionHandle = Attribute.OptionHandle;
var parentObject = property.GetDeclaringObject();
var presetList = GetPresetList(parentObject, sourceHandle, property);
if (presetList == null)
{
EditorGUI.PropertyField(position, property, label);
return;
}

var options = GetOptions(presetList, parentObject, optionHandle, property);

var value = property.GetProperValue(fieldInfo, parentObject);
var index = presetList.IndexOf(value);

//begin the true property
label = EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();

//get selected preset value
index = EditorGUI.Popup(position, label, index, EditorGUIUtility.TrTempContent(options));
index = Mathf.Clamp(index, 0, itemsCount - 1);
index = Mathf.Clamp(index, 0, presetList.Count - 1);
if (EditorGUI.EndChangeCheck())
{
//udpate property value using previously cached FieldInfo and picked value
//there is no cleaner way to do it, since we don't really know what kind of
//serialized property we are updating

property.serializedObject.Update();
property.SetProperValue(fieldInfo, objects[index]);
property.SetProperValue(fieldInfo, presetList[index]);
property.serializedObject.ApplyModifiedProperties();
//handle situation when updating multiple different targets
property.serializedObject.SetIsDifferentCacheDirty();
Expand All @@ -85,10 +133,10 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU

public override bool IsPropertyValid(SerializedProperty property)
{
var declaringObject = property.GetDeclaringObject();
var parentObject = property.GetDeclaringObject();
//NOTE: reflection won't work properly on nested structs because of boxing
//TODO: handle this case
return !declaringObject.GetType().IsValueType;
return !parentObject.GetType().IsValueType;
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using UnityEngine;

namespace Toolbox.Editor.Drawers
{
public class BeginVerticalAttributeDrawer : ToolboxDecoratorDrawer<BeginVerticalAttribute>
{
protected override void OnGuiBeginSafe(BeginVerticalAttribute attribute)
{
ToolboxLayoutHelper.BeginVertical();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using UnityEngine;

namespace Toolbox.Editor.Drawers
{
public class EndVerticalAttributeDrawer : ToolboxDecoratorDrawer<EndVerticalAttribute>
{
protected override void OnGuiCloseSafe(EndVerticalAttribute attribute)
{
ToolboxLayoutHelper.CloseVertical();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ public void RemoveElement(int index)
/// </summary>
public virtual void DoList()
{
DoList(null);
DoList(TitleLabel);
}

/// <summary>
Expand Down
20 changes: 9 additions & 11 deletions Assets/Editor Toolbox/Editor/ToolboxEditorGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,21 +205,19 @@ public static void DrawMinMaxSlider(Rect rect, string label, ref float xValue, r

public static void DrawMinMaxSlider(Rect rect, GUIContent label, ref float xValue, ref float yValue, float minValue, float maxValue)
{
var padding = 8.0f;
var labelWidth = EditorGUIUtility.labelWidth;
rect = EditorGUI.PrefixLabel(rect, label);

var fieldWidth = EditorGUIUtility.fieldWidth;

var minFieldRect = new Rect(rect.xMin + labelWidth, rect.y, fieldWidth, rect.height);
var minFieldRect = new Rect(rect.xMin, rect.y, fieldWidth, rect.height);
var maxFieldRect = new Rect(rect.xMax - fieldWidth, rect.y, fieldWidth, rect.height);
var labelRect = new Rect(rect.x, rect.y, labelWidth, rect.height);

//set slider rect between min and max fields + additional padding
var sliderRect = new Rect(rect.x + labelWidth + fieldWidth + padding,
rect.y,
rect.width - labelWidth - fieldWidth * 2 - padding * 2,
rect.height);
var spacing = 8.0f;
var sliderRect = Rect.MinMaxRect(minFieldRect.xMax + spacing,
rect.yMin,
maxFieldRect.xMin - spacing,
rect.yMax);

//begin drawing using GUI methods
EditorGUI.LabelField(labelRect, label);
EditorGUI.BeginChangeCheck();
xValue = EditorGUI.FloatField(minFieldRect, xValue);
yValue = EditorGUI.FloatField(maxFieldRect, yValue);
Expand Down
46 changes: 38 additions & 8 deletions Assets/Editor Toolbox/Editor/ToolboxPropertyHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ private void DrawProperty(SerializedProperty property, GUIContent label)
}
}

private void BeginDecoratorDrawers()
private void BeginDecoratorDrawers(PropertyCondition conditionState = PropertyCondition.Valid)
{
if (!hasToolboxDecoratorDrawer)
{
Expand All @@ -302,11 +302,11 @@ private void BeginDecoratorDrawers()

for (var i = 0; i < decoratorAttributes.Count; i++)
{
ToolboxDrawerModule.GetDecoratorDrawer(decoratorAttributes[i])?.OnGuiBegin(decoratorAttributes[i]);
HandleDecorator(decoratorAttributes[i], true, conditionState);
}
}

private void CloseDecoratorDrawers()
private void CloseDecoratorDrawers(PropertyCondition conditionState = PropertyCondition.Valid)
{
if (!hasToolboxDecoratorDrawer)
{
Expand All @@ -315,7 +315,38 @@ private void CloseDecoratorDrawers()

for (var i = decoratorAttributes.Count - 1; i >= 0; i--)
{
ToolboxDrawerModule.GetDecoratorDrawer(decoratorAttributes[i])?.OnGuiClose(decoratorAttributes[i]);
HandleDecorator(decoratorAttributes[i], false, conditionState);
}
}

private void HandleDecorator(ToolboxDecoratorAttribute attribute, bool onBegin, PropertyCondition conditionState = PropertyCondition.Valid)
{
var drawer = ToolboxDrawerModule.GetDecoratorDrawer(attribute);
if (drawer == null)
{
return;
}

if (!attribute.ApplyCondition)
{
conditionState = PropertyCondition.Valid;
}

var isValid = conditionState != PropertyCondition.NonValid;
var disable = conditionState == PropertyCondition.Disabled;
if (isValid)
{
using (new EditorGUI.DisabledScope(disable))
{
if (onBegin)
{
drawer.OnGuiBegin(attribute);
}
else
{
drawer.OnGuiClose(attribute);
}
}
}
}

Expand Down Expand Up @@ -363,11 +394,10 @@ public void OnGuiLayout(SerializedProperty property, GUIContent label)
//using custom attributes and information about native drawers
//we can use all associated and allowed ToolboxDrawers (for each type)

//begin all needed decorator drawers in the proper order
BeginDecoratorDrawers();

//handle condition attribute and draw property if possible
var conditionState = Validate(property);
//begin all needed decorator drawers in the proper order
BeginDecoratorDrawers(conditionState);
var isValid = conditionState != PropertyCondition.NonValid;
var disable = conditionState == PropertyCondition.Disabled;
if (isValid)
Expand All @@ -382,7 +412,7 @@ public void OnGuiLayout(SerializedProperty property, GUIContent label)
}

//close all needed decorator drawers in the proper order
CloseDecoratorDrawers();
CloseDecoratorDrawers(conditionState);
}

/// <summary>
Expand Down
Loading

0 comments on commit 4cd14d0

Please sign in to comment.