using System.Collections.Generic; using Unity.Pipeline.Commands; using UnityEditor; using UnityEngine; namespace Unity.Pipeline.Editor.Commands.ProjectSettings { /// /// Get/set the legacy Input Manager (CLI-202). The InputManager has no scripting API, so this /// reads/writes ProjectSettings/InputManager.asset via serialized properties: /// get lists the configured axis names; set tunes a named axis's /// sensitivity/gravity/dead values. /// /// "Input (legacy / Input System where feasible)" per the ticket: the legacy InputManager is /// always present, so it is the portable target. Projects on the new Input System package store /// their config in a separate input-actions asset, which would be a follow-up. /// public static class InputSettingsCommands { const string Group = "input"; const string AssetPath = "ProjectSettings/InputManager.asset"; [CliCommand("get_input_settings", "Read the legacy Input Manager axes (names and count).", MainThreadRequired = true)] public static ProjectSettingsResponse Get() => ProjectSettingsCommand.Get(Group, Read); [CliCommand("set_input_settings", "Tune a legacy Input Manager axis (sensitivity/gravity/dead) by name. Requires confirm=true; use dry_run to preview. Not undoable via Ctrl+Z.", MainThreadRequired = true)] public static ProjectSettingsResponse Set( [CliArg("settings", "Axis change. 'axis' selects the axis by name; omitted numeric fields are left unchanged.")] InputAxisInput settings = null, [CliArg("confirm", "Apply the change. Without it the call is refused.")] bool confirm = false, [CliArg("dry_run", "Preview the change without applying it.")] bool dryRun = false) { if (settings == null) return ProjectSettingsResponse.Fail(Group, "No 'settings' object provided."); if (string.IsNullOrEmpty(settings.Axis)) return ProjectSettingsResponse.Fail(Group, "'axis' is required."); var so = ProjectSettingsAsset.Load(AssetPath); var axes = so.FindProperty("m_Axes"); var index = FindAxisIndex(axes, settings.Axis); if (index < 0) return ProjectSettingsResponse.Fail(Group, $"No axis named '{settings.Axis}'."); var axis = axes.GetArrayElementAtIndex(index); var changes = new List(); AddFloatChange(axis, "sensitivity", settings.Sensitivity, changes); AddFloatChange(axis, "gravity", settings.Gravity, changes); AddFloatChange(axis, "dead", settings.Dead, changes); if (changes.Count == 0) return NoChanges(); var planText = $"Set input axis '{settings.Axis}': " + string.Join("; ", changes); void Apply() { var obj = ProjectSettingsAsset.Load(AssetPath); var arr = obj.FindProperty("m_Axes"); var idx = FindAxisIndex(arr, settings.Axis); if (idx < 0) return; var ax = arr.GetArrayElementAtIndex(idx); SetFloat(ax, "sensitivity", settings.Sensitivity); SetFloat(ax, "gravity", settings.Gravity); SetFloat(ax, "dead", settings.Dead); obj.ApplyModifiedProperties(); AssetDatabase.SaveAssets(); } return ProjectSettingsCommand.Apply(Group, confirm, dryRun, settings, () => planText, Apply, Read); } static ProjectSettingsResponse NoChanges() { var response = ProjectSettingsCommand.Get(Group, Read); response.Message = "No changes specified; nothing to apply."; return response; } static int FindAxisIndex(SerializedProperty axes, string name) { if (axes == null) return -1; for (var i = 0; i < axes.arraySize; i++) { var nameProp = axes.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name"); if (nameProp != null && nameProp.stringValue == name) return i; } return -1; } static void AddFloatChange(SerializedProperty axis, string prop, float? newValue, List changes) { if (!newValue.HasValue) return; var p = axis.FindPropertyRelative(prop); if (p == null) return; if (!Mathf.Approximately(p.floatValue, newValue.Value)) changes.Add($"{prop} {p.floatValue} -> {newValue.Value}"); } static void SetFloat(SerializedProperty axis, string prop, float? value) { if (!value.HasValue) return; var p = axis.FindPropertyRelative(prop); if (p != null) p.floatValue = value.Value; } static Dictionary Read() { var so = ProjectSettingsAsset.Load(AssetPath); var axes = so.FindProperty("m_Axes"); var names = new List(); if (axes != null) { for (var i = 0; i < axes.arraySize; i++) { var nameProp = axes.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name"); names.Add(nameProp != null ? nameProp.stringValue : null); } } return new Dictionary { ["axisCount"] = names.Count, ["axes"] = names }; } } /// Selects a legacy input axis by name and the numeric fields to change (omitted = unchanged). public class InputAxisInput : IStructuredCommandInput { [CliArg("axis", "Name of the axis to modify (e.g. 'Horizontal').", Required = true)] public string Axis { get; set; } [CliArg("sensitivity", "New sensitivity.")] public float? Sensitivity { get; set; } [CliArg("gravity", "New gravity.")] public float? Gravity { get; set; } [CliArg("dead", "New dead-zone size.")] public float? Dead { get; set; } } }