Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMCL-1587: cleanup UX layout code. fix alignment for U6 #989

Merged
merged 34 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fd806cf
cleanup UX layout code. fix alignment for U6
glabute May 9, 2024
691da91
Update InspectorUtility.cs
glabute May 9, 2024
e94aece
Merge branch 'main' into dev/ux-layout-cleanup
glabute May 31, 2024
5524ac0
merge errors
glabute May 31, 2024
a3b774a
Update CinemachineSplineRollEditor.cs
glabute May 31, 2024
5a8af97
Merge branch 'main' into dev/ux-layout-cleanup
glabute Jun 4, 2024
b25b871
merge errors
glabute Jun 4, 2024
702c5d1
Merge branch 'main' into dev/ux-layout-cleanup
glabute Jun 5, 2024
4b1a22d
bugfixes
glabute Jun 5, 2024
25187a6
Remove bindItem from BlenderSettingsEditor
glabute Jun 5, 2024
7c43274
Update InspectorUtility.cs
glabute Jun 5, 2024
b979417
Merge branch 'dev/ux-layout-cleanup' into dev/ListView-cleanup
glabute Jun 5, 2024
09ddd49
get rid of bindItem in SequencerEditor
glabute Jun 5, 2024
f7cde10
get rid of bindItem in StateDrivenCamera editor
glabute Jun 5, 2024
8cadc0c
fix bindItem in CameraInspectorUtility
glabute Jun 5, 2024
a4ddbd7
add some missing draggers
glabute Jun 5, 2024
4b4e069
layout tweaking
glabute Jun 5, 2024
8525321
Simplify SplineDataInspectorUtility.CreateDataListField
glabute Jun 6, 2024
4658905
cleanup code for creating draggable properties
glabute Jun 6, 2024
fe16a6a
remove bindItem from SplineRoll
glabute Jun 6, 2024
e586048
remove bindItem for SplineLookAtTargets
glabute Jun 6, 2024
46d6887
minor layout tweaks
glabute Jun 10, 2024
2784fb4
Minor tweaks, LabeledRow refactor (one container less)
glabute Jun 10, 2024
9900a60
More reduction of excess containers
glabute Jun 10, 2024
93e82d2
simplification
glabute Jun 10, 2024
00b3964
Update CinemachineFollowZoom.cs
glabute Jun 10, 2024
4b76b6e
Update InputAxisPropertyDrawer.cs
glabute Jun 10, 2024
2f61e37
fix upgrade message layout
glabute Jun 10, 2024
b6c9210
better handling of missing target warnings
glabute Jun 10, 2024
4bbf548
layout tweaks
glabute Jun 10, 2024
3131ed9
No SaveDuringPlay for PerlinNoise.m_NoiseOffset
glabute Jun 11, 2024
5678056
Add isDelayed on some fields
glabute Jun 11, 2024
7aba388
Cleanup SaveDuringPlay for input axis controller
glabute Jun 11, 2024
ba7c9ae
Add some missing NoSaveDuringPlay
glabute Jun 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System;

namespace Unity.Cinemachine.Editor
{
Expand Down Expand Up @@ -55,6 +56,7 @@ public override VisualElement CreateInspectorGUI()
// Gather the camera candidates
var availableCameras = new List<string>();
Dictionary<string, int> cameraIndexLookup = new();
Action onCamerasUpdated = null;
list.TrackAnyUserActivity(() =>
{
var allCameras = new List<CinemachineVirtualCameraBase>();
Expand All @@ -65,29 +67,47 @@ public override VisualElement CreateInspectorGUI()
for (int i = 0; i < allCameras.Count; ++i)
if (allCameras[i] != null && !availableCameras.Contains(allCameras[i].Name))
availableCameras.Add(allCameras[i].Name);
list.RefreshItems(); // rebuild the list
onCamerasUpdated?.Invoke();
});

list.makeItem = () => new BindableElement { style = { flexDirection = FlexDirection.Row }};
list.bindItem = (row, index) =>
list.makeItem = () =>
{
// Remove children - items get recycled
for (int i = row.childCount - 1; i >= 0; --i)
row.RemoveAt(i);

var def = new CinemachineBlenderSettings.CustomBlend();
var element = index < elements.arraySize ? elements.GetArrayElementAtIndex(index) : null;
if (!IsUnityNull(element))
var row = new BindableElement { style = { flexDirection = FlexDirection.Row }};
var from = row.AddChild(CreateCameraPopup(SerializedPropertyHelper.PropertyName(() => def.From)));
var to = row.AddChild(CreateCameraPopup(SerializedPropertyHelper.PropertyName(() => def.To)));
var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend)});
FormatElement(false, from, to, blend);
return row;

// Local function
VisualElement CreateCameraPopup(string bindingPath)
{
var from = row.AddChild(CreateCameraPopup(element.FindPropertyRelative(() => def.From)));
var to = row.AddChild(CreateCameraPopup(element.FindPropertyRelative(() => def.To)));
var blend = row.AddChild(new PropertyField(element.FindPropertyRelative(() => def.Blend), ""));
FormatElement(false, from, to, blend);
var container = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }};
var textField = container.AddChild(new TextField { bindingPath = bindingPath, isDelayed = true, style = { flexGrow = 1, flexBasis = 20 }});

((BindableElement)row).BindProperty(element); // bind must be done at the end
var warning = container.AddChild(InspectorUtility.MiniHelpIcon($"No in-scene camera matches this name"));
textField.RegisterValueChangedCallback((evt) => OnCameraUpdated());
onCamerasUpdated += OnCameraUpdated;
void OnCameraUpdated()
{
warning.tooltip = $"No in-scene camera matches \"{textField.value}\"";
warning.SetVisible(availableCameras.FindIndex(x => x == textField.value) < 0);
};

var popup = container.AddChild(InspectorUtility.MiniDropdownButton(
"Choose from currently-available cameras", new ContextualMenuManipulator((evt) =>
{
for (int i = 0; i < availableCameras.Count; ++i)
evt.menu.AppendAction(availableCameras[i], (action) => textField.value = action.name);
})));
popup.style.marginRight = 5;
return container;
}
};

return ux;

// Local function
static void FormatElement(bool isHeader, VisualElement e1, VisualElement e2, VisualElement e3)
{
Expand All @@ -101,38 +121,6 @@ static void FormatElement(bool isHeader, VisualElement e1, VisualElement e2, Vis
e3.style.flexBasis = 1;
e3.style.flexGrow = 2;
}

// Local function
VisualElement CreateCameraPopup(SerializedProperty p)
{
var row = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }};
var textField = row.AddChild(new TextField { isDelayed = true, style = { flexGrow = 1, flexBasis = 20 }});
textField.BindProperty(p);
if (availableCameras.FindIndex(x => x == p.stringValue) < 0)
row.AddChild(InspectorUtility.MiniHelpIcon("No in-scene camera matches this name"));
var popup = row.AddChild(InspectorUtility.MiniDropdownButton(
"Choose from currently-available cameras", new ContextualMenuManipulator((evt) =>
{
for (int i = 0; i < availableCameras.Count; ++i)
evt.menu.AppendAction(availableCameras[i],
(action) =>
{
p.stringValue = action.name;
p.serializedObject.ApplyModifiedProperties();
});
})));
popup.style.marginRight = 5;
return row;
}

// Local function
static bool IsUnityNull(object obj)
{
// Checks whether an object is null or Unity pseudo-null
// without having to cast to UnityEngine.Object manually
return obj == null || ((obj is UnityEngine.Object) && ((UnityEngine.Object)obj) == null);
}
return ux;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ public override VisualElement CreateInspectorGUI()

var defaultTargetLabel = new ObjectField("");
defaultTargetLabel.SetEnabled(false);
var defaultTargetRow = ux.AddChild(new InspectorUtility.LabeledRow("Default Target", "", defaultTargetLabel));
defaultTargetRow.tooltip = "The default target is set in the parent object, and will be used if the Tracking Target is None";
var defaultTargetRow = ux.AddChild(new InspectorUtility.LabeledRow(
"Default Target", "The default target is set in the parent object, and will be used if the Tracking Target is None",
defaultTargetLabel));
defaultTargetRow.focusable = false;
defaultTargetLabel.style.marginLeft = 5;
defaultTargetLabel.style.marginRight = -2;
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.Target)));

ux.AddHeader("Global Settings");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ public override VisualElement CreateInspectorGUI()
{
var ux = new VisualElement();

ux.Add(new HelpBox("This component is optional and can be removed if you don't need it. "
+ "The modifiers you add will override settings for the top and bottom portions "
+ "of the camera's vertical orbit.",
HelpBoxMessageType.Info));

var invalidSrcMsg = ux.AddChild(
new HelpBox("<b>This component will be ignored because no applicable target components are present.</b>\n\n"
+ "Applicable target components include: "
new HelpBox("<b>Component will be ignored because no modifiable targets are present.</b>\n\n"
+ "Modifiable target components include: "
+ InspectorUtility.GetAssignableBehaviourNames(
typeof(CinemachineFreeLookModifier.IModifierValueSource)),
HelpBoxMessageType.Warning));
Expand Down Expand Up @@ -110,7 +115,9 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property)
warningSymbol.SetVisible(showWarning);
});

return new InspectorUtility.FoldoutWithOverlay(foldout, overlay, null);
var ux = new InspectorUtility.FoldoutWithOverlay(foldout, overlay, null);
ux.style.marginLeft = 12;
return ux;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public override VisualElement CreateInspectorGUI()
{
var ux = new VisualElement();
this.AddMissingCmCameraHelpBox(ux);
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TargetOffset)));
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TrackerSettings)));
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TargetOffset)));
ux.AddSpace();

var orbitModeProp = serializedObject.FindProperty(() => Target.OrbitStyle);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
Expand Down Expand Up @@ -41,7 +42,6 @@ public override VisualElement CreateInspectorGUI()

var list = container.AddChild(new ListView()
{
name = "InstructionList",
reorderable = true,
reorderMode = ListViewReorderMode.Animated,
showAddRemoveFooter = true,
Expand All @@ -53,77 +53,55 @@ public override VisualElement CreateInspectorGUI()
var instructions = serializedObject.FindProperty(() => Target.Instructions);
list.BindProperty(instructions);

list.makeItem = () => new BindableElement { style = { flexDirection = FlexDirection.Row }};
list.bindItem = (row, index) =>
// Available camera candidates
var availableCameras = new List<Object>();

list.makeItem = () =>
{
// Remove children - items get recycled
for (int i = row.childCount - 1; i >= 0; --i)
row.RemoveAt(i);
var row = new BindableElement { style = { flexDirection = FlexDirection.Row }};

var def = new CinemachineSequencerCamera.Instruction();
var element = instructions.GetArrayElementAtIndex(index);

var vcamSelProp = element.FindPropertyRelative(() => def.Camera);
var vcamSel = row.AddChild(new PopupField<Object> { name = $"vcamSelector{index}", choices = new() });
vcamSel.formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name;
vcamSel.formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name;
vcamSel.TrackPropertyWithInitialCallback(instructions, (p) => UpdateCameraDropdowns());
var vcamSel = row.AddChild(new PopupField<Object>
{
bindingPath = SerializedPropertyHelper.PropertyName(() => def.Camera),
choices = availableCameras,
formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name,
formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name
});

var blend = row.AddChild(new PropertyField(element.FindPropertyRelative(() => def.Blend), ""));
if (index == 0)
blend.name = "FirstItemBlend";
var hold = row.AddChild(
new InspectorUtility.CompactPropertyField(element.FindPropertyRelative(() => def.Hold), " "));
hold.RemoveFromClassList(InspectorUtility.kAlignFieldClass);
var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend), name = "blendSelector" });
var hold = row.AddChild(InspectorUtility.CreateDraggableField(() => def.Hold, row.AddChild(new Label(" ")), out _));
hold.SafeSetIsDelayed();

FormatInstructionElement(false, vcamSel, blend, hold);

// Bind must be last
((BindableElement)row).BindProperty(element);
vcamSel.BindProperty(vcamSelProp);
return row;
};

container.AddSpace();
this.AddChildCameras(container, null);

container.TrackAnyUserActivity(() =>
{
if (Target == null)
if (Target == null || list.itemsSource == null)
return; // object deleted

var isMultiSelect = targets.Length > 1;
multiSelectMsg.SetVisible(isMultiSelect);
container.SetVisible(!isMultiSelect);

// Hide the first blend if not looped
list.Q<VisualElement>("FirstItemBlend")?.SetEnabled(Target.Loop);
var index = 0;
list.Query<VisualElement>().Where((e) => e.name == "blendSelector").ForEach((e)
=> e.style.visibility = (index++ == 0 && !Target.Loop) ? Visibility.Hidden : Visibility.Visible);

// Update the list items
UpdateCameraDropdowns();
// Gather the camera candidates
availableCameras.Clear();
availableCameras.AddRange(Target.ChildCameras);
});
this.AddExtensionsDropdown(ux);

return ux;

// Local function
void UpdateCameraDropdowns()
{
var children = Target.ChildCameras;
int index = 0;
var iter = list.itemsSource.GetEnumerator();
while (iter.MoveNext())
{
var vcamSel = list.Q<PopupField<Object>>($"vcamSelector{index}");
if (vcamSel != null)
{
vcamSel.choices.Clear();
for (int i = 0; i < children.Count; ++i)
vcamSel.choices.Add(children[i]);
}
++index;
}
}

// Local function
static void FormatInstructionElement(bool isHeader, VisualElement e1, VisualElement e2, VisualElement e3)
{
Expand All @@ -133,13 +111,13 @@ static void FormatInstructionElement(bool isHeader, VisualElement e1, VisualElem
e1.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight;
e1.style.flexGrow = 1;

e2.style.flexBasis = floatFieldWidth;
e2.style.marginLeft = isHeader ? 4 * InspectorUtility.SingleLineHeight - 3 : 0;
e2.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight;
e2.style.flexGrow = 1;

e3.style.marginRight = 4;
floatFieldWidth += isHeader ? InspectorUtility.SingleLineHeight/2 - 1 : 0;
e3.style.flexBasis = floatFieldWidth;
e3.style.flexGrow = 0;
e3.style.unityTextAlign = TextAnchor.MiddleRight;
}
}
}
Expand Down
Loading
Loading