Skip to content

Commit

Permalink
🔀 Merge develop into main
Browse files Browse the repository at this point in the history
  • Loading branch information
matheusamazonas committed Nov 1, 2023
2 parents f61f693 + ef9e942 commit 61ac7a4
Show file tree
Hide file tree
Showing 52 changed files with 3,420 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,6 @@ fabric.properties

## Unity editor user settings
UserSettings/*

# Obsidian
.obsidian/
8 changes: 8 additions & 0 deletions Assets/Libraries.meta

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

8 changes: 8 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute.meta

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

8 changes: 8 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/Editor.meta

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

149 changes: 149 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/Editor/MinMaxRangeDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using System;
using UnityEditor;
using UnityEngine;

namespace SneakySquirrelLabs.MinMaxRangeAttribute.Editor
{
[CustomPropertyDrawer(typeof(MinMaxRangeAttribute))]
internal class MinMaxRangeDrawer : PropertyDrawer
{
#region Fields

private const float HorizontalSpacing = 5f;
private const float SliderHandlerWidth = 12f;

private static readonly float VerticalSpacing = EditorGUIUtility.standardVerticalSpacing;
private static GUIStyle LabelStyleField;

private uint _decimals;

#endregion

#region Properties

private static GUIStyle LabelStyle => LabelStyleField ??= new GUIStyle(GUI.skin.label);

#endregion

#region Update

public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label) * 2;
}

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (attribute is not MinMaxRangeAttribute minMaxAttribute)
{
Debug.LogError("Min max range attribute failed to draw.");
return;
}

var minLimit = minMaxAttribute.MinLimit;
var maxLimit = minMaxAttribute.MaxLimit;
_decimals = minMaxAttribute.Decimals;

if (property.propertyType == SerializedPropertyType.Vector2Int)
{
var value = property.vector2IntValue;
var minValue = (float)value.x;
var maxValue = (float)value.y;
DrawSlider(position, property, minLimit, maxLimit, ref minValue, ref maxValue, BuildIntLabel);
value.x = (int)minValue;
value.y = (int)maxValue;
property.vector2IntValue = value;
}
else if (property.propertyType == SerializedPropertyType.Vector2)
{
var value = property.vector2Value;
var minValue = value.x;
var maxValue = value.y;
DrawSlider(position, property, minLimit, maxLimit, ref minValue, ref maxValue, BuildFloatLabel);
value.x = minValue;
value.y = maxValue;
property.vector2Value = value;
}

static void DrawSlider(Rect position, SerializedProperty property, float min, float max, ref float x,
ref float y, Func<float, GUIContent> buildLabel)
{
var consumedX = 0f;
var firstLineRect = new Rect(position) { height = position.height / 2 - VerticalSpacing};

// Field name
consumedX += DrawFieldName(firstLineRect, property);

// Min label
var minLabel = buildLabel(min);
consumedX += DrawLabel(firstLineRect, consumedX, minLabel);
consumedX += HorizontalSpacing; // Add spacing between min label and slider

// Slider
var maxLabel = buildLabel(max);
var maxLabelWidth = LabelStyle.CalcSize(maxLabel).x; // We need to know the max label's size
var sliderWidth = firstLineRect.width - consumedX - maxLabelWidth - HorizontalSpacing;
var sliderPosition = new Rect(firstLineRect) { x = firstLineRect.x + consumedX, width = sliderWidth };
EditorGUI.MinMaxSlider(sliderPosition, ref x, ref y, min, max);
consumedX += sliderWidth + HorizontalSpacing;

// Max label
DrawLabel(firstLineRect, consumedX, maxLabel);

// Value labels
var secondLineRect = new Rect(position) { y = position.y, height = firstLineRect.height};
var valuesY = secondLineRect.y + sliderPosition.height + EditorGUIUtility.standardVerticalSpacing;
// X label
var labelsPosition = new Rect(sliderPosition) { y = valuesY };
DrawValueLabel(labelsPosition, x, min, max, true, buildLabel);
// Label
DrawValueLabel(labelsPosition, y, min, max, false, buildLabel);

static float DrawFieldName(Rect position, SerializedProperty property)
{
var labelPosition = new Rect(position) { width = EditorGUIUtility.labelWidth };
EditorGUI.LabelField(labelPosition, property.displayName);
return labelPosition.width;
}

static float DrawLabel(Rect position, float xOffset, GUIContent label)
{
var size = LabelStyle.CalcSize(label);
var minLabelPosition = new Rect(position) { x = position.x + xOffset, width = size.x};
EditorGUI.LabelField(minLabelPosition, label, LabelStyle);
return size.x;
}

static void DrawValueLabel(Rect position, float value, float minLimit, float maxLimit,
bool applyExtraOffset, Func<float, GUIContent> buildLabel)
{
var label = buildLabel(value);
var labelSize = LabelStyle.CalcSize(label);
var relativePosition = (value - minLimit) / (maxLimit - minLimit);
var offset = SliderHandlerWidth / 2 + (applyExtraOffset ? -labelSize.x : 0);
var totalWidth = position.width - SliderHandlerWidth;
var x = position.x + relativePosition * totalWidth + offset;
var labelPosition = new Rect(position) { x = x, width = labelSize.x };
EditorGUI.LabelField(labelPosition, label, LabelStyle);
}
}

static GUIContent BuildIntLabel(float value) => new($"{value:F0}");

GUIContent BuildFloatLabel(float value)
{
var floatLabel = _decimals switch
{
0 => $"{value:F0}",
1 => $"{value:F1}",
2 => $"{value:F2}",
3 => $"{value:F3}",
_ => throw new NotSupportedException("Min max attribute supports up to 3 decimal places.")
};
return new GUIContent(floatLabel);
}
}

#endregion
}
}

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,18 @@
{
"name": "SneakySquirrelLabs.MinMaxRangeAttribute.Editor",
"rootNamespace": "SneakySquirrelLabs.MinMaxRangeAttribute.Editor",
"references": [
"GUID:397edf9bfe7ea4399b706e9ee953b982"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

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

49 changes: 49 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/MinMaxRangeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using UnityEngine;

namespace SneakySquirrelLabs.MinMaxRangeAttribute
{
/// <summary>
/// An attribute that simplifies defining bounded ranges (ranges with minimum and maximum limits) on the inspector.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class MinMaxRangeAttribute : PropertyAttribute
{
#region Fields

public readonly float MinLimit;
public readonly float MaxLimit;
public readonly uint Decimals;

#endregion

#region Setup

/// <summary>
/// A bounded range for integers.
/// </summary>
/// <param name="minLimit">The minimum acceptable value.</param>
/// <param name="maxLimit">The maximum acceptable value.</param>
public MinMaxRangeAttribute(int minLimit, int maxLimit)
{
MinLimit = minLimit;
MaxLimit = maxLimit;
}

/// <summary>
/// A bounded range for floats.
/// </summary>
/// <param name="minLimit">The minimum acceptable value.</param>
/// <param name="maxLimit">The maximum acceptable value.</param>
/// <param name="decimals">How many decimals the inspector labels should display. Values must be in the [0,3]
/// range. Default is 1.</param>
public MinMaxRangeAttribute(float minLimit, float maxLimit, uint decimals = 1)
{
MinLimit = minLimit;
MaxLimit = maxLimit;
Decimals = decimals;
}

#endregion
}
}
11 changes: 11 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/MinMaxRangeAttribute.cs.meta

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,14 @@
{
"name": "SneakySquirrelLabs.MinMaxRangeAttribute",
"rootNamespace": "SneakySquirrelLabs.MinMaxRangeAttribute",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

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

22 changes: 22 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "com.sneakysquirrellabs.minmaxrangeattribute",
"version": "1.0.0",
"displayName": "Min/max range attribute",
"description": "A bounded (i.e., with a minimum and maximum) range attribute for Unity's Vector2 and Vector2Int fields.",
"unity": "2021.3",
"documentationUrl": "https://github.com/matheusamazonas/min_max_range_attribute",
"changelogUrl": "https://github.com/matheusamazonas/min_max_range_attribute/releases",
"licensesUrl": "https://github.com/matheusamazonas/min_max_range_attribute/LICENSE",
"keywords": [
"editor",
"attribute",
"terrain inspector",
"vector",
"range"
],
"author": {
"name": "Matheus Amazonas",
"email": "matheus.amazonas@gmail.com",
"url": "https://matheusamazonas.net"
}
}
7 changes: 7 additions & 0 deletions Assets/Libraries/MinMaxRangeAttribute/package.json.meta

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

8 changes: 8 additions & 0 deletions Assets/Settings.meta

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

Loading

0 comments on commit 61ac7a4

Please sign in to comment.