Skip to content

Commit

Permalink
remove bindItem for SplineLookAtTargets
Browse files Browse the repository at this point in the history
  • Loading branch information
glabute committed Jun 6, 2024
1 parent fe16a6a commit e586048
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ public override VisualElement CreateInspectorGUI()
() =>
{
// Create a default item for index 0
var item = new CinemachineSplineDollyLookAtTargets.Item();
item.LookAt = splineData.VirtualCamera.LookAt;
var item = new CinemachineSplineDollyLookAtTargets.Item { LookAt = splineData.VirtualCamera.LookAt, Easing = 1 };
if (item.LookAt == null)
{
// No LookAt? Find a point to look at near the spline
Expand All @@ -113,57 +112,83 @@ public override VisualElement CreateInspectorGUI()
}
return item;
}));


var arrayProp = targetsProp.FindPropertyRelative("m_DataPoints");
list.makeItem = () => new BindableElement() { style = { marginRight = 4 }};
list.bindItem = (ux, index) =>
list.makeItem = () =>
{
// Remove children - items get recycled
for (int i = ux.childCount - 1; i >= 0; --i)
ux.RemoveAt(i);
var itemRootName = "ItemRoot";
var row = new BindableElement() { name = itemRootName, style = { marginRight = 4 }};

const string indexTooltip = "The position on the Spline at which this data point will take effect. "
+ "The value is interpreted according to the Index Unit setting.";
var overlay = new VisualElement () { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }};
var overlayLabel = overlay.AddChild(new Label("Index"));
var indexField1 = overlay.AddChild(InspectorUtility.CreateDraggableField(
typeof(float), "m_Index", SplineDataInspectorUtility.ItemIndexTooltip, overlayLabel, out var dragger));
indexField1.style.flexGrow = 1;
indexField1.style.flexBasis = 50;
indexField1.SafeSetIsDelayed();
dragger.OnDragValueChangedFloat = (v) => BringCameraToCustomSplinePoint(splineData, v);
dragger.OnStartDrag = (d) => list.selectedIndex = GetIndexInList(list, d.DragElement, itemRootName);

var element = index < arrayProp.arraySize ? arrayProp.GetArrayElementAtIndex(index) : null;
CinemachineSplineDollyLookAtTargets.Item def = new ();
var indexProp = element.FindPropertyRelative("m_Index");
var valueProp = element.FindPropertyRelative("m_Value");
var lookAtProp = valueProp.FindPropertyRelative(() => def.LookAt);
var offsetProp = valueProp.FindPropertyRelative(() => def.Offset);
var lookAtField1 = overlay.AddChild(new ObjectField
{
bindingPath = "m_Value." + SerializedPropertyHelper.PropertyName(() => def.LookAt),
tooltip = SerializedPropertyHelper.PropertyTooltip(() => def.LookAt),
objectType = typeof(Transform),
style = { flexGrow = 4, flexBasis = 50, marginLeft = 6 }
});

var foldout = new Foldout() { value = false, text = "Target" }; // do not bind to "m_Value" because it will mess up the binding for index
var indexRow = foldout.AddChild(new InspectorUtility.LabeledRow("Index", SplineDataInspectorUtility.ItemIndexTooltip));
var indexField2 = indexRow.Contents.AddChild(InspectorUtility.CreateDraggableField(
typeof(float), "m_Index", SplineDataInspectorUtility.ItemIndexTooltip, indexRow.Label, out dragger));
indexField2.style.flexGrow = 1;
indexField2.style.flexBasis = 50;
indexField2.SafeSetIsDelayed();
dragger.OnDragValueChangedFloat = (v) => BringCameraToCustomSplinePoint(splineData, v);
dragger.OnStartDrag = (d) => list.selectedIndex = GetIndexInList(list, d.DragElement, itemRootName);

var overlay = new VisualElement () { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }};
var indexField1 = overlay.AddChild(new PropertyField(indexProp, "") { tooltip = indexTooltip, style = { flexGrow = 1, flexBasis = 50 }});
indexField1.OnInitialGeometry(() => indexField1.SafeSetIsDelayed());
var lookAtField2 = foldout.AddChild(new PropertyField { bindingPath = "m_Value." + SerializedPropertyHelper.PropertyName(() => def.LookAt) });

var lookAtField1 = overlay.AddChild(new PropertyField(lookAtProp, "") { style = { flexGrow = 4, flexBasis = 50, marginLeft = 3 }});
var overlayLabel = new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }};
overlayLabel.AddDelayedFriendlyPropertyDragger(indexProp, overlay, OnIndexDraggerCreated);

var foldout = new Foldout() { text = $"Target {index}" };
foldout.BindProperty(element);
var row = foldout.AddChild(new InspectorUtility.LabeledRow(indexProp.displayName, indexTooltip));
var indexField2 = row.Contents.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1 }});
indexField2.OnInitialGeometry(() => indexField2.SafeSetIsDelayed());
row.Label.AddDelayedFriendlyPropertyDragger(indexProp, indexField2, OnIndexDraggerCreated);
foldout.Add(new PropertyField { bindingPath = "m_Value." + SerializedPropertyHelper.PropertyName(() => def.Offset) });
foldout.Add(new PropertyField { bindingPath = "m_Value." + SerializedPropertyHelper.PropertyName(() => def.Easing) });

var lookAtField2 = foldout.AddChild(new PropertyField(lookAtProp));
foldout.Add(new PropertyField(offsetProp));
foldout.Add(new PropertyField(valueProp.FindPropertyRelative(() => def.Easing)));
var foldoutWithOverlay = row.AddChild(new InspectorUtility.FoldoutWithOverlay(
foldout, overlay, overlayLabel) { style = { marginLeft = 12 }});
foldoutWithOverlay.OpenFoldout.name = foldoutWithOverlay.ClosedFoldout.name = "ItemFoldout";

ux.Add(new InspectorUtility.FoldoutWithOverlay(foldout, overlay, overlayLabel) { style = { marginLeft = 12 }});
// When the LookAt is changed, we want to do a little processing to fix up the offset
lookAtField1.RegisterValueChangedCallback((evt) => OnLookAtChanged(GetIndexInList(list, row, itemRootName)));

ux.TrackPropertyValue(lookAtProp, (p) =>
return row;

// Sneaky way to find out which list element we are
static int GetIndexInList(ListView list, VisualElement element, string itemRootName)
{
var container = list.Q("unity-content-container");
if (container != null)
{
while (element != null && element.name != itemRootName)
element = element.parent;
if (element != null)
return container.IndexOf(element);
}
return - 1;
}

void OnLookAtChanged(int index)
{
// Don't mess with the offset if change was a result of undo/redo
if (m_UndoRedoMonitor.IsUndoRedo)
if (m_UndoRedoMonitor.IsUndoRedo || index < 0 || index >= arrayProp.arraySize)
return;

var offsetProp = arrayProp.GetArrayElementAtIndex(index).FindPropertyRelative("m_Value.Offset");
var lookAtProp = arrayProp.GetArrayElementAtIndex(index).FindPropertyRelative("m_Value.LookAt");

// if lookAt target was set to null, preserve the worldspace location
if (GetInspectorStateCache(splineData).GetCachedValue(index, out var previous))
{
var newData = p.objectReferenceValue;
var newData = lookAtProp.objectReferenceValue;
if (newData == null && previous.Value.LookAt != null)
SetOffset(previous.Value.WorldLookAt);

Expand All @@ -175,22 +200,24 @@ public override VisualElement CreateInspectorGUI()
void SetOffset(Vector3 offset)
{
offsetProp.vector3Value = offset;
p.serializedObject.ApplyModifiedProperties();
lookAtProp.serializedObject.ApplyModifiedProperties();
}
}
});

((BindableElement)ux).BindProperty(element); // bind must be done at the end

// local function
void OnIndexDraggerCreated(IDelayedFriendlyDragger dragger)
{
//dragger.OnStartDrag = () => list.selectedIndex = index;
dragger.OnDragValueChangedFloat = (v) => BringCameraToCustomSplinePoint(splineData, v);
}
};

list.TrackPropertyValue(arrayProp, (p) => EditorApplication.delayCall += () => GetInspectorStateCache(splineData).Reset(splineData));
list.TrackPropertyWithInitialCallback(arrayProp, (p) =>
{
// Fix up the foldout names to reflect the index of the item
int index = 0;
list.Query("ItemFoldout").ForEach((e) =>
{
if (e is Foldout f)
f.text = $"Target {index++ / 2}"; // because there are 2 foldouts for each item
});
// Reset the state cache after all processing is done
EditorApplication.delayCall += () => GetInspectorStateCache(splineData).Reset(splineData);
});

// When the list selection changes, cache the index and put the camera at that point on the dolly track
list.selectedIndicesChanged += (indices) =>
Expand Down
30 changes: 13 additions & 17 deletions com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,14 @@ public override VisualElement CreateInspectorGUI()
var itemRootName = "ItemRoot";
var row = new BindableElement() { name = itemRootName, style = { flexDirection = FlexDirection.Row, marginRight = 4 }};

const string indexTooltip = "The position on the Spline at which this data point will take effect. "
+ "The value is interpreted according to the Index Unit setting.";

row.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { flexBasis = 12 }}); // pass-through for selecting row in list
var indexField = row.AddChild(InspectorUtility.CreateDraggableField(
typeof(float), "m_Index", indexTooltip, row.AddChild(new Label("Index")), out var dragger));
typeof(float), "m_Index", SplineDataInspectorUtility.ItemIndexTooltip,
row.AddChild(new Label("Index")), out var dragger));
indexField.style.flexGrow = 1;
indexField.style.flexBasis = 50;
indexField.SafeSetIsDelayed();
if (dragger is IDelayedFriendlyDragger delayedDragger)
delayedDragger.OnStartDrag = (d) => SelectListElementContainingAnElement(list, d.DragElement, itemRootName);
dragger.OnStartDrag = (d) => list.selectedIndex = GetIndexInList(list, d.DragElement, itemRootName);

var def = new CinemachineSplineRoll.RollData();
var rollTooltip = SerializedPropertyHelper.PropertyTooltip(() => def.Value);
Expand All @@ -63,25 +60,24 @@ public override VisualElement CreateInspectorGUI()
typeof(float), "m_Value.Value", rollTooltip, row.AddChild(new Label("Roll")), out dragger));
rollField.style.flexGrow = 1;
rollField.style.flexBasis = 50;
if (dragger is IDelayedFriendlyDragger delayedDragger2)
delayedDragger2.OnStartDrag = (d) => SelectListElementContainingAnElement(list, d.DragElement, itemRootName);
dragger.OnStartDrag = (d) => list.selectedIndex = GetIndexInList(list, d.DragElement, itemRootName);

return row;

static void SelectListElementContainingAnElement(ListView list, VisualElement element, string itemRootName)
// Sneaky way to find out which list element we are
static int GetIndexInList(ListView list, VisualElement element, string itemRootName)
{
var container = list.Q("unity-content-container");
if (container == null)
return;
while (element != null && element.name != itemRootName)
element = element.parent;
if (element != null)
if (container != null)
{
var index = container.IndexOf(element);
if (index >= 0)
list.selectedIndex = index;
while (element != null && element.name != itemRootName)
element = element.parent;
if (element != null)
return container.IndexOf(element);
}
return - 1;
}

};

SplineRollTool.s_OnDataLookAtDragged += OnToolDragged;
Expand Down
7 changes: 4 additions & 3 deletions com.unity.cinemachine/Editor/Utility/InspectorUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,14 @@ public static void AddDelayedFriendlyPropertyDragger(
}
}

public static VisualElement CreateDraggableField(Expression<Func<object>> exp, Label label, out BaseFieldMouseDragger dragger)
public static VisualElement CreateDraggableField(Expression<Func<object>> exp, Label label, out IDelayedFriendlyDragger dragger)
{
var bindingPath = SerializedPropertyHelper.PropertyName(exp);
var tooltip = SerializedPropertyHelper.PropertyTooltip(exp);
return CreateDraggableField(SerializedPropertyHelper.PropertyType(exp), bindingPath, tooltip, label, out dragger);
}

public static VisualElement CreateDraggableField(Type type, string bindingPath, string tooltip, Label label, out BaseFieldMouseDragger dragger)
public static VisualElement CreateDraggableField(Type type, string bindingPath, string tooltip, Label label, out IDelayedFriendlyDragger dragger)
{
VisualElement field;
label.AddToClassList("unity-base-field__label--with-dragger");
Expand All @@ -321,7 +321,8 @@ public static VisualElement CreateDraggableField(Type type, string bindingPath,
field = new PropertyField(null, "") { bindingPath = bindingPath, tooltip = tooltip };
dragger = null;
}
dragger?.SetDragZone(label);
var d = dragger as BaseFieldMouseDragger;
d?.SetDragZone(label);
return field;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ static class SplineDataInspectorUtility
public delegate ISplineContainer GetSplineDelegate();
public delegate T GetDefaultValueDelegate<T>();

public const string ItemIndexTooltip = "The position on the Spline at which this data point will take effect. "
+ "The value is interpreted according to the Index Unit setting.";

public static VisualElement CreatePathUnitField(SerializedProperty splineDataProp, GetSplineDelegate getSpline)
{
var indexUnitProp = splineDataProp.FindPropertyRelative("m_IndexUnit");
Expand Down

0 comments on commit e586048

Please sign in to comment.