Skip to content

Commit

Permalink
cleanup code for creating draggable properties
Browse files Browse the repository at this point in the history
  • Loading branch information
glabute committed Jun 6, 2024
1 parent 8525321 commit 4658905
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,7 @@ public override VisualElement CreateInspectorGUI()
});

var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend), name = "blendSelector" });

var holdTooltip = "How long to wait (in seconds) before activating the next camera in the list (if any)";
var holdDragger = row.AddChild(new Label(" ") { tooltip = holdTooltip });
holdDragger.AddToClassList("unity-base-field__label--with-dragger");
var hold = row.AddChild(new FloatField
{
tooltip = holdTooltip,
bindingPath = SerializedPropertyHelper.PropertyName(() => def.Hold)
});
new DelayedFriendlyFieldDragger<float>(hold).SetDragZone(holdDragger);
var hold = row.AddChild(InspectorUtility.CreateDraggableField(() => def.Hold, row.AddChild(new Label(" ")), out _));

FormatInstructionElement(false, vcamSel, blend, hold);
return row;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,25 +143,8 @@ public override VisualElement CreateInspectorGUI()
formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name
});

var waitTooltip = "How long to wait (in seconds) before activating the camera. This filters out very short state durations";
var waitDragger = row.AddChild(new Label(" ") { tooltip = waitTooltip });
waitDragger.AddToClassList("unity-base-field__label--with-dragger");
var wait = row.AddChild(new FloatField
{
tooltip = waitTooltip,
bindingPath = SerializedPropertyHelper.PropertyName(() => def.ActivateAfter)
});
new DelayedFriendlyFieldDragger<float>(wait).SetDragZone(waitDragger);

var holdTooltip = "The minimum length of time (in seconds) to keep a camera active";
var holdDragger = row.AddChild(new Label(" ") { tooltip = holdTooltip });
holdDragger.AddToClassList("unity-base-field__label--with-dragger");
var hold = row.AddChild(new FloatField
{
tooltip = holdTooltip,
bindingPath = SerializedPropertyHelper.PropertyName(() => def.MinDuration)
});
new DelayedFriendlyFieldDragger<float>(hold).SetDragZone(holdDragger);
var wait = row.AddChild(InspectorUtility.CreateDraggableField(() => def.ActivateAfter, row.AddChild(new Label(" ")), out _));
var hold = row.AddChild(InspectorUtility.CreateDraggableField(() => def.MinDuration, row.AddChild(new Label(" ")), out _));

FormatInstructionElement(false, stateSel, vcamSel, wait, hold);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,11 +535,13 @@ public static void AddChildCameras(
style = { flexBasis = 20, flexGrow = 1 }
}).SetEnabled(false);

var dragger = row.AddChild(new Label(" "));
var tooltip = "The child camera's Priority";
var dragger = row.AddChild(new Label(" ") { tooltip = tooltip });
dragger.AddToClassList("unity-base-field__label--with-dragger");
var priorityField = row.AddChild(new IntegerField
{
name = "priorityField",
tooltip = tooltip,
isDelayed = true,
style = { flexBasis = floatFieldWidth, flexGrow = 0, marginRight = 4 }
});
Expand Down
30 changes: 30 additions & 0 deletions com.unity.cinemachine/Editor/Utility/InspectorUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Reflection;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System.Linq.Expressions;

namespace Unity.Cinemachine.Editor
{
Expand Down Expand Up @@ -291,6 +292,35 @@ public static void AddDelayedFriendlyPropertyDragger(
});
}
}

public static VisualElement CreateDraggableField(Expression<Func<object>> exp, Label label, out BaseFieldMouseDragger dragger)
{
VisualElement field;
var name = SerializedPropertyHelper.PropertyName(exp);
var tooltip = SerializedPropertyHelper.PropertyTooltip(exp);

label.tooltip = tooltip;
label.AddToClassList("unity-base-field__label--with-dragger");

var type = SerializedPropertyHelper.PropertyType(exp);
if (type == typeof(float))
{
field = new FloatField { bindingPath = name };
dragger = new DelayedFriendlyFieldDragger<float>((FloatField)field);
}
else if (type == typeof(int))
{
field = new IntegerField { bindingPath = name };
dragger = new DelayedFriendlyFieldDragger<int>((IntegerField)field);
}
else
{
field = new PropertyField(null, "") { bindingPath = name };
dragger = null;
}
dragger?.SetDragZone(label);
return field;
}

/// <summary>A small warning sybmol, suitable for embedding in an inspector row</summary>
/// <param name="tooltip">The tooltip text</param>
Expand Down
50 changes: 47 additions & 3 deletions com.unity.cinemachine/Editor/Utility/SerializedPropertyHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using UnityEditor;

namespace Unity.Cinemachine.Editor
Expand All @@ -23,17 +24,60 @@ static class SerializedPropertyHelper
/// </code>
/// </summary>
/// <param name="exp">Magic expression that resolves to a field: () => myClass.m_MyField</param>
/// <returns></returns>
public static string PropertyName(Expression<Func<object>> exp)
/// <returns>string name of field</returns>
public static MemberInfo MemberInfo(Expression<Func<object>> exp)
{
if (exp.Body is not MemberExpression body)
{
var ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
return body.Member;
}

/// <summary>
/// This is a way to get a field name string in such a manner that the compiler will
/// generate errors for invalid fields. Much better than directly using strings.
/// Usage: instead of
/// <code>
/// "m_MyField";
/// </code>
/// do this:
/// <code>
/// MyClass myclass = null;
/// SerializedPropertyHelper.PropertyName( () => myClass.m_MyField);
/// </code>
/// </summary>
/// <param name="exp">Magic expression that resolves to a field: () => myClass.m_MyField</param>
/// <returns>string name of field</returns>
public static string PropertyName(Expression<Func<object>> exp) => MemberInfo(exp).Name;

/// <summary>
/// This is a way to get a field tooltip string in such a manner that the compiler will
/// generate errors for invalid fields. Much better than directly using strings.
/// </summary>
/// <param name="exp">Magic expression that resolves to a field: () => myClass.m_MyField</param>
/// <returns>Tooltip text</returns>
public static string PropertyTooltip(Expression<Func<object>> exp)
{
var attrs = MemberInfo(exp).GetCustomAttributes(typeof(UnityEngine.TooltipAttribute), false);
return attrs.Length > 0 ? ((UnityEngine.TooltipAttribute)attrs[0]).tooltip : string.Empty;
}

/// <summary>
/// This is a way to get a field name string in such a manner that the compiler will
/// generate errors for invalid fields. Much better than directly using strings.
/// </summary>
/// <param name="exp">Magic expression that resolves to a field: () => myClass.m_MyField</param>
/// <returns>Type of field</returns>
public static Type PropertyType(Expression<Func<object>> exp)
{
var member = MemberInfo(exp);
if (member.MemberType == MemberTypes.Field)
return ((FieldInfo)member).FieldType;
throw new ArgumentException ( "Input MemberInfo must be of type FieldInfo" );
}

/// <summary>
/// A compiler-assisted (non-string-based) way to call SerializedProperty.FindProperty
/// </summary>
Expand Down

0 comments on commit 4658905

Please sign in to comment.