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; }
}
}