Files

201 lines
9.0 KiB
C#

using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
namespace Unity.Cinemachine.Editor
{
[CustomEditor(typeof(CinemachineInputAxisController))]
class InputAxisControllerEditor : UnityEditor.Editor
{
public override VisualElement CreateInspectorGUI()
{
var ux = new VisualElement();
#if ENABLE_LEGACY_INPUT_MANAGER && CINEMACHINE_UNITY_INPUTSYSTEM
ux.AddChild(new HelpBox("Old and new input systems are both active. For simplicity and clarity, "
+ "it's recommended to activate only one of them.\nYou can do this in Player Settings > Active Input Handling.",
HelpBoxMessageType.Info));
#endif
var prop = serializedObject.GetIterator();
if (prop.NextVisible(true))
InspectorUtility.AddRemainingProperties(ux, prop);
return ux;
}
[InitializeOnLoad]
class DefaultControlInitializer
{
static DefaultControlInitializer()
{
CinemachineInputAxisController.SetControlDefaults
= (in IInputAxisOwner.AxisDescriptor axis, ref CinemachineInputAxisController.Controller controller) =>
{
#pragma warning disable CS0219 // Variable is assigned but its value is never used
var actionName = "";
#pragma warning restore CS0219
var inputName = "";
var invertY = false;
bool isMomentary = (axis.DrivenAxis().Restrictions & InputAxis.RestrictionFlags.Momentary) != 0;
if (axis.Name.Contains("Look"))
{
actionName = "CM Default/Look";
inputName = axis.Hint switch
{
IInputAxisOwner.AxisDescriptor.Hints.X => "Mouse X",
IInputAxisOwner.AxisDescriptor.Hints.Y => "Mouse Y",
_ => ""
};
invertY = axis.Hint == IInputAxisOwner.AxisDescriptor.Hints.Y;
controller.Driver = DefaultInputAxisDriver.Default;
}
if (axis.Name.Contains("Zoom") || axis.Name.Contains("Scale"))
{
actionName = "CM Default/Zoom";
inputName = "Mouse ScrollWheel";
invertY = true;
}
if (axis.Name.Contains("Move"))
{
actionName = "CM Default/Move";
inputName = axis.Hint switch
{
IInputAxisOwner.AxisDescriptor.Hints.X => "Horizontal",
IInputAxisOwner.AxisDescriptor.Hints.Y => "Vertical",
_ => ""
};
}
if (axis.Name.Contains("Fire"))
{
actionName = "CM Default/Fire";
inputName = "Fire1";
}
if (axis.Name.Contains("Jump"))
{
actionName = "CM Default/Jump";
inputName = "Jump";
}
if (axis.Name.Contains("Sprint"))
{
actionName = "CM Default/Sprint";
inputName = "Fire3"; // best we can do
}
#if CINEMACHINE_UNITY_INPUTSYSTEM
if (actionName.Length != 0)
{
var assetPath = CinemachineCore.kPackageRoot
+ "/Runtime/Input/CinemachineDefaultInputActions.inputactions";
var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
for (int i = 0; controller.Input.InputAction == null && i < assets.Length; ++i)
if (assets[i].name == actionName)
controller.Input.InputAction = (UnityEngine.InputSystem.InputActionReference)assets[i];
}
controller.Input.Gain = invertY ? -1 : 1;
#endif
#if ENABLE_LEGACY_INPUT_MANAGER && !CINEMACHINE_UNITY_INPUTSYSTEM
controller.Input.LegacyInput = inputName;
controller.Input.LegacyGain = isMomentary ? 1 : 100 * (invertY ? -1 : 1);
#endif
controller.Enabled = true;
};
}
}
}
[CustomPropertyDrawer(typeof(CinemachineInputAxisController.Controller), true)]
class InputAxisControllerItemPropertyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
CinemachineInputAxisController.Controller def = new ();
var overlay = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }};
overlay.Add(new PropertyField(property.FindPropertyRelative(() => def.Enabled), "")
{ style = { marginLeft = 2, flexGrow = 0, flexBasis = InspectorUtility.SingleLineHeight, alignSelf = Align.Center}} );
// Draw the input value on the same line as the foldout, for convenience
var inputProperty = property.FindPropertyRelative(() => def.Input);
#if CINEMACHINE_UNITY_INPUTSYSTEM
overlay.Add(new PropertyField(inputProperty.FindPropertyRelative(() => def.Input.InputAction), "")
{ style = { marginLeft = -3, flexGrow = 1, flexBasis = 5 * InspectorUtility.SingleLineHeight}} );
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
overlay.Add(new PropertyField(inputProperty.FindPropertyRelative(() => def.Input.LegacyInput), "")
{ style = {flexGrow = 1, flexBasis = 5 * InspectorUtility.SingleLineHeight }} );
#endif
var foldout = new Foldout() { text = property.displayName, tooltip = property.tooltip };
foldout.BindProperty(property);
var childProperty = property.Copy();
var endProperty = childProperty.GetEndProperty();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
foldout.Add(new PropertyField(childProperty));
childProperty.NextVisible(false);
}
return new InspectorUtility.FoldoutWithOverlay(foldout, overlay, null) { style = { marginLeft = 12, marginRight = 3 }};
}
}
[CustomPropertyDrawer(typeof(InputAxisControllerManagerAttribute))]
class InputAxisControllerListPropertyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// Why not make a PropertyDrawer for the list directly? Because
// of a bug in ListView - PropertyDrawers directly on Lists don't work.
// This is a workaround for that bug.
property = property.FindPropertyRelative("Controllers");
var ux = new VisualElement();
var list = ux.AddChild(new ListView()
{
reorderable = false,
showAddRemoveFooter = false,
showBorder = false,
showBoundCollectionSize = false,
showFoldoutHeader = false,
virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
style = { marginLeft = -12, marginRight = -3 }
});
list.BindProperty(property);
var isEmptyMessage = ux.AddChild(new HelpBox(
"This component will be ignored because no applicable targets are present.\n"
+ "<b>You can remove this component.\n</b>Applicable target components include: "
+ InspectorUtility.GetAssignableBehaviourNames(typeof(IInputAxisOwner)),
HelpBoxMessageType.Warning));
list.TrackPropertyWithInitialCallback(property, (p) =>
{
bool isEmpty = p.IsDeletedObject() || p.arraySize == 0;
isEmptyMessage.SetVisible(isEmpty);
list.SetVisible(!isEmpty);
});
// Synchronize the controller list
ux.TrackAnyUserActivity(() =>
{
if (property.IsDeletedObject())
return;
var targets = property.serializedObject.targetObjects;
for (int i = 0; i < targets.Length; ++i)
{
var obj = targets[i];
if (obj is IInputAxisController target && !target.ControllersAreValid())
{
EditorApplication.delayCall += () =>
{
Undo.RecordObject(obj, "SynchronizeControllers");
target.SynchronizeControllers();
};
}
}
});
return ux;
}
}
}