This commit is contained in:
2025-01-17 13:10:42 +01:00
commit 4536213c91
15115 changed files with 1442174 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 665321577aaff5344b5a12d626dfcaf7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60e5ec46fb7a7ff41856f37c60efb70f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,305 @@
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine.InputSystem.Utilities;
namespace UnityEngine.InputSystem.Editor
{
internal static class ControlSchemeCommands
{
private const string kAllControlSchemesName = "All Control Schemes";
private const string kNewControlSchemeName = "New Control Scheme";
public static Command AddNewControlScheme()
{
return (in InputActionsEditorState state) =>
{
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(selectedControlScheme: new InputControlScheme(
MakeUniqueControlSchemeName(state, kNewControlSchemeName)));
};
}
public static Command AddDeviceRequirement(InputControlScheme.DeviceRequirement requirement)
{
return (in InputActionsEditorState state) =>
{
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(selectedControlScheme: new InputControlScheme(state.selectedControlScheme.name,
state.selectedControlScheme.deviceRequirements.Append(requirement)));
};
}
public static Command RemoveDeviceRequirement(int selectedDeviceIndex)
{
return (in InputActionsEditorState state) =>
{
state.m_Analytics?.RegisterControlSchemeEdit();
var newDeviceIndex =
Mathf.Clamp(
selectedDeviceIndex <= state.selectedDeviceRequirementIndex
? state.selectedDeviceRequirementIndex - 1
: state.selectedDeviceRequirementIndex, -1, state.selectedDeviceRequirementIndex);
return state.With(selectedControlScheme: new InputControlScheme(state.selectedControlScheme.name,
state.selectedControlScheme.deviceRequirements.Where((r, i) => i != selectedDeviceIndex)), selectedDeviceRequirementIndex: newDeviceIndex);
};
}
public static Command SaveControlScheme(string newControlSchemeName = "", bool updateExisting = false)
{
return (in InputActionsEditorState state) =>
{
var controlSchemeName = state.selectedControlScheme.name;
var controlSchemesArray = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes));
var controlScheme = controlSchemesArray
.FirstOrDefault(sp => sp.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue == controlSchemeName);
var actionMaps = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ActionMaps));
// If the control scheme is null, we're saving a new control scheme, otherwise editing an existing one
if (controlScheme == null && updateExisting)
throw new InvalidOperationException("Tried to update a non-existent control scheme.");
if (updateExisting == false)
{
controlSchemeName = MakeUniqueControlSchemeName(state, controlSchemeName);
controlSchemesArray.InsertArrayElementAtIndex(controlSchemesArray.arraySize);
controlScheme = controlSchemesArray.GetArrayElementAtIndex(controlSchemesArray.arraySize - 1);
}
// If we're renaming a control scheme, we need to update the bindings that use it and make a unique name
if (!string.IsNullOrEmpty(newControlSchemeName))
{
newControlSchemeName = MakeUniqueControlSchemeName(state, newControlSchemeName);
RenameBindingsControlSchemeHelper(controlScheme, actionMaps, controlSchemeName, newControlSchemeName);
}
controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue = string.IsNullOrWhiteSpace(newControlSchemeName) ? controlSchemeName : newControlSchemeName;
controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_BindingGroup)).stringValue = string.IsNullOrWhiteSpace(newControlSchemeName) ? controlSchemeName : newControlSchemeName;
var serializedDeviceRequirements = controlScheme.FindPropertyRelative(nameof(InputControlScheme.m_DeviceRequirements));
serializedDeviceRequirements.ClearArray();
for (var i = 0; i < state.selectedControlScheme.deviceRequirements.Count; i++)
{
var deviceRequirement = state.selectedControlScheme.deviceRequirements[i];
serializedDeviceRequirements.InsertArrayElementAtIndex(i);
var serializedRequirement = serializedDeviceRequirements.GetArrayElementAtIndex(i);
serializedRequirement
.FindPropertyRelative(nameof(InputControlScheme.DeviceRequirement.m_ControlPath))
.stringValue = deviceRequirement.controlPath;
serializedRequirement.FindPropertyRelative(nameof(InputControlScheme.DeviceRequirement.m_Flags))
.enumValueFlag = (int)deviceRequirement.m_Flags;
}
state.serializedObject.ApplyModifiedProperties();
return state.With(
selectedControlScheme: new InputControlScheme(controlScheme),
// Select the control scheme updated, otherwise select the new one it was added
selectedControlSchemeIndex: updateExisting? state.selectedControlSchemeIndex: controlSchemesArray.arraySize - 1);
};
}
static void RenameBindingsControlSchemeHelper(SerializedProperty controlScheme, SerializedProperty actionMaps, string controlSchemeName, string newName)
{
foreach (SerializedProperty actionMap in actionMaps)
{
var bindings = actionMap
.FindPropertyRelative(nameof(InputActionMap.m_Bindings))
.Select(sp => new SerializedInputBinding(sp))
.ToList();
var bindingsToRename = bindings.Where(b => b.controlSchemes.Contains(controlSchemeName)).ToList();
foreach (var binding in bindingsToRename)
{
var bindingGroups = binding.controlSchemes.ToList();
bindingGroups.Remove(controlSchemeName);
bindingGroups.Add(newName);
binding.wrappedProperty.FindPropertyRelative(nameof(InputBinding.m_Groups)).stringValue = bindingGroups.Join(InputBinding.kSeparatorString);
}
}
}
public static Command SelectControlScheme(int controlSchemeIndex)
{
return (in InputActionsEditorState state) =>
{
if (controlSchemeIndex == -1)
return state.With(selectedControlSchemeIndex: controlSchemeIndex, selectedControlScheme: new InputControlScheme());
var controlSchemeSerializedProperty = state.serializedObject
.FindProperty(nameof(InputActionAsset.m_ControlSchemes))
.GetArrayElementAtIndex(controlSchemeIndex);
return state.With(
selectedControlSchemeIndex: controlSchemeIndex,
selectedControlScheme: new InputControlScheme(controlSchemeSerializedProperty));
};
}
public static Command ResetSelectedControlScheme()
{
return (in InputActionsEditorState state) =>
{
var controlSchemeSerializedProperty = state.selectedControlSchemeIndex == -1 ? null :
state.serializedObject
.FindProperty(nameof(InputActionAsset.m_ControlSchemes))
.GetArrayElementAtIndex(state.selectedControlSchemeIndex);
if (controlSchemeSerializedProperty == null)
{
return state.With(
selectedControlSchemeIndex: -1,
selectedControlScheme: new InputControlScheme());
}
return state.With(
selectedControlScheme: new InputControlScheme(controlSchemeSerializedProperty));
};
}
public static Command SelectDeviceRequirement(int deviceRequirementIndex)
{
return (in InputActionsEditorState state) => state.With(selectedDeviceRequirementIndex: deviceRequirementIndex);
}
/// <summary>
/// Duplicate creates a new instance of the selected control scheme and places it in the selected
/// control scheme property of the state but doesn't persist anything.
/// </summary>
public static Command DuplicateSelectedControlScheme()
{
return (in InputActionsEditorState state) =>
{
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(selectedControlScheme: new InputControlScheme(
MakeUniqueControlSchemeName(state, state.selectedControlScheme.name),
state.selectedControlScheme.deviceRequirements));
};
}
public static Command DeleteSelectedControlScheme()
{
return (in InputActionsEditorState state) =>
{
var selectedControlSchemeName = state.selectedControlScheme.name;
var serializedArray = InputActionSerializationHelpers.GetControlSchemesArray(state.serializedObject);
var indexOfArrayElement = InputActionSerializationHelpers.IndexOfControlScheme(serializedArray, selectedControlSchemeName);
if (indexOfArrayElement < 0)
throw new InvalidOperationException("Control scheme doesn't exist in collection.");
// Ask for confirmation.
if (Dialog.Result.Cancel == Dialog.ControlScheme.ShowDeleteControlScheme(selectedControlSchemeName))
return state;
serializedArray.DeleteArrayElementAtIndex(indexOfArrayElement);
state.serializedObject.ApplyModifiedProperties();
if (serializedArray.arraySize == 0)
return state.With(
selectedControlSchemeIndex: -1,
selectedControlScheme: new InputControlScheme(),
selectedDeviceRequirementIndex: -1);
if (indexOfArrayElement > serializedArray.arraySize - 1)
return state.With(
selectedControlSchemeIndex: serializedArray.arraySize - 1,
selectedControlScheme: new InputControlScheme(serializedArray.GetArrayElementAtIndex(serializedArray.arraySize - 1)), selectedDeviceRequirementIndex: -1);
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(
selectedControlSchemeIndex: indexOfArrayElement,
selectedControlScheme: new InputControlScheme(serializedArray.GetArrayElementAtIndex(indexOfArrayElement)), selectedDeviceRequirementIndex: -1);
};
}
internal static string MakeUniqueControlSchemeName(InputActionsEditorState state, string name)
{
var controlSchemes = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes));
IEnumerable<string> controlSchemeNames = Array.Empty<string>();
if (controlSchemes != null)
controlSchemeNames =
controlSchemes.Select(sp => sp.FindPropertyRelative(nameof(InputControlScheme.m_Name)).stringValue);
return StringHelpers.MakeUniqueName(name, controlSchemeNames.Append(kAllControlSchemesName), x => x);
}
public static Command ChangeDeviceRequirement(int deviceRequirementIndex, bool isRequired)
{
return (in InputActionsEditorState state) =>
{
var deviceRequirements = state.selectedControlScheme.deviceRequirements.ToList();
var requirement = deviceRequirements[deviceRequirementIndex];
requirement.isOptional = !isRequired;
deviceRequirements[deviceRequirementIndex] = requirement;
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(selectedControlScheme: new InputControlScheme(
state.selectedControlScheme.name,
deviceRequirements,
state.selectedControlScheme.bindingGroup));
};
}
public static Command ReorderDeviceRequirements(int oldPosition, int newPosition)
{
return (in InputActionsEditorState state) =>
{
var deviceRequirements = state.selectedControlScheme.deviceRequirements.ToList();
var requirement = deviceRequirements[oldPosition];
deviceRequirements.RemoveAt(oldPosition);
deviceRequirements.Insert(newPosition, requirement);
state.m_Analytics?.RegisterControlSchemeEdit();
return state.With(selectedControlScheme: new InputControlScheme(
state.selectedControlScheme.name,
deviceRequirements,
state.selectedControlScheme.bindingGroup));
};
}
public static Command ChangeSelectedBindingsControlSchemes(string controlScheme, bool add)
{
return (in InputActionsEditorState state) =>
{
var actionMapSO = state.serializedObject
?.FindProperty(nameof(InputActionAsset.m_ActionMaps))
?.GetArrayElementAtIndex(state.selectedActionMapIndex);
var serializedProperty = actionMapSO?.FindPropertyRelative(nameof(InputActionMap.m_Bindings))
?.GetArrayElementAtIndex(state.selectedBindingIndex);
var groupsProperty = serializedProperty.FindPropertyRelative(nameof(InputBinding.m_Groups));
var groups = groupsProperty.stringValue;
if (add)
groupsProperty.stringValue = groups
.Split(InputBinding.kSeparatorString)
.Append(controlScheme)
.Distinct()
.Join(InputBinding.kSeparatorString);
else
groupsProperty.stringValue = groups
.Split(InputBinding.kSeparatorString)
.Where(s => s != controlScheme)
.Join(InputBinding.kSeparatorString);
state.m_Analytics?.RegisterBindingEdit();
state.serializedObject.ApplyModifiedProperties();
return state;
};
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99cfd7e6e4fd7294090b6bf84b177326
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
namespace UnityEngine.InputSystem.Editor
{
internal static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T, int> action)
{
int index = 0;
foreach (var item in enumerable)
action(item, index++);
}
public static string Join<T>(this IEnumerable<T> enumerable, string separator)
{
return string.Join(separator, enumerable);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 255ca660c2e3b424bb54d7be66737f57
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
#if UNITY_EDITOR
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace UnityEngine.InputSystem.Editor
{
internal static class ExpressionUtils
{
public static PropertyInfo GetProperty<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> expression)
{
var member = GetMemberExpression(expression).Member;
var property = member as PropertyInfo;
if (property == null)
throw new InvalidOperationException($"Member with Name '{member.Name}' is not a property.");
return property;
}
private static MemberExpression GetMemberExpression<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> expression)
{
MemberExpression memberExpression = null;
switch (expression.Body.NodeType)
{
case ExpressionType.Convert:
{
var body = (UnaryExpression)expression.Body;
memberExpression = body.Operand as MemberExpression;
break;
}
case ExpressionType.MemberAccess:
memberExpression = expression.Body as MemberExpression;
break;
}
if (memberExpression == null)
throw new ArgumentException("Not a member access", nameof(expression));
return memberExpression;
}
public static Func<TEntity, TProperty> CreateGetter<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
{
var propertyInfo = GetProperty(property);
var instance = Expression.Parameter(typeof(TEntity), "instance");
var body = Expression.Call(instance, propertyInfo.GetGetMethod());
var parameters = new[] { instance };
return Expression.Lambda<Func<TEntity, TProperty>>(body, parameters).Compile();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35e258ef8ccb13146952199468118233
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
#if UNITY_EDITOR
namespace UnityEngine.InputSystem.Editor
{
internal static class InputActionsEditorConstants
{
// Paths
public const string PackagePath = "Packages/com.unity.inputsystem";
public const string ResourcesPath = "/InputSystem/Editor/UITKAssetEditor/PackageResources";
/// Template names
public const string ProjectSettingsUxml = "/InputActionsProjectSettings.uxml";
public const string MainEditorViewNameUxml = "/InputActionsEditor.uxml";
public const string BindingsPanelRowTemplateUxml = "/BindingPanelRowTemplate.uxml";
public const string NameAndParametersListViewItemUxml = "/NameAndParameterListViewItemTemplate.uxml";
public const string CompositeBindingPropertiesViewUxml = "/CompositeBindingPropertiesEditor.uxml";
public const string CompositePartBindingPropertiesViewUxml = "/CompositePartBindingPropertiesEditor.uxml";
public const string ControlSchemeEditorViewUxml = "/ControlSchemeEditor.uxml";
public const string InputActionMapsTreeViewItemUxml = "/InputActionMapsTreeViewItem.uxml";
public const string InputActionsTreeViewItemUxml = "/InputActionsTreeViewItem.uxml";
/// Classes
public static readonly string HiddenStyleClassName = "unity-input-actions-editor-hidden";
public const string CompositePartAssignmentTooltip =
"The named part of the composite that the binding is assigned to. Multiple bindings may be assigned the same part. All controls from "
+ "all bindings that are assigned the same part will collectively feed values into that part of the composite.";
public const string CompositeTypeTooltip =
"Type of composite. Allows changing the composite type retroactively. Doing so will modify the bindings that are part of the composite.";
public const string InitialStateCheckTooltip =
"Whether in the next input update after the action was enabled, the action should "
+ "immediately trigger if any of its bound controls are currently in a non-default state. "
+ "This check happens implicitly for Value actions but can be explicitly enabled for Button and Pass-Through actions.";
public struct CommandEvents
{
public const string Rename = "Rename";
public const string Delete = "Delete";
public const string SoftDelete = "SoftDelete";
public const string Duplicate = "Duplicate";
public const string Copy = "Copy";
public const string Cut = "Cut";
public const string Paste = "Paste";
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 36827be967eb9244b973cbee1bbf53e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,335 @@
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
namespace UnityEngine.InputSystem.Editor
{
internal class InputActionsEditorSettingsProvider : SettingsProvider
{
private static InputActionsEditorSettingsProvider s_Provider;
public static string SettingsPath => InputSettingsPath.kSettingsRootPath;
[SerializeField] InputActionsEditorState m_State;
VisualElement m_RootVisualElement;
private bool m_HasEditFocus;
private bool m_IgnoreActionChangedCallback;
private bool m_IsActivated;
private static bool m_IMGUIDropdownVisible;
StateContainer m_StateContainer;
private static InputActionsEditorSettingsProvider m_ActiveSettingsProvider;
private InputActionsEditorView m_View;
private InputActionsEditorSessionAnalytic m_ActionEditorAnalytics;
public InputActionsEditorSettingsProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null)
: base(path, scopes, keywords)
{}
public override void OnActivate(string searchContext, VisualElement rootElement)
{
// There is an editor bug UUM-55238 that may cause OnActivate and OnDeactivate to be called in unexpected order.
// This flag avoids making assumptions and executing logic twice.
if (m_IsActivated)
return;
// Monitor play mode state changes
EditorApplication.playModeStateChanged += ModeChanged;
// Setup root element with focus monitoring
m_RootVisualElement = rootElement;
m_RootVisualElement.focusable = true;
m_RootVisualElement.RegisterCallback<FocusOutEvent>(OnFocusOut);
m_RootVisualElement.RegisterCallback<FocusInEvent>(OnFocusIn);
// Always begin a session when activated (note that OnActivate isn't called when navigating back
// to editor from another setting category)
m_ActionEditorAnalytics = new InputActionsEditorSessionAnalytic(
InputActionsEditorSessionAnalytic.Data.Kind.EmbeddedInProjectSettings);
m_ActionEditorAnalytics.Begin();
CreateUI();
// Monitor any changes to InputSystem.actions for as long as this editor is active
InputSystem.onActionsChange += BuildUI;
// Set the asset assigned with the editor which indirectly builds the UI based on setting
BuildUI();
// Note that focused element will be set if we are navigating back to an existing instance when switching
// setting in the left project settings panel since this doesn't recreate the editor.
if (m_RootVisualElement?.focusController?.focusedElement != null)
OnFocusIn();
m_IsActivated = true;
}
public override void OnDeactivate()
{
// There is an editor bug UUM-55238 that may cause OnActivate and OnDeactivate to be called in unexpected order.
// This flag avoids making assumptions and executing logic twice.
if (!m_IsActivated)
return;
// Stop monitoring play mode state changes
EditorApplication.playModeStateChanged -= ModeChanged;
if (m_RootVisualElement != null)
{
m_RootVisualElement.UnregisterCallback<FocusInEvent>(OnFocusIn);
m_RootVisualElement.UnregisterCallback<FocusOutEvent>(OnFocusOut);
}
// Make sure any remaining changes are actually saved
SaveAssetOnFocusLost();
// Note that OnDeactivate will also trigger when opening the Project Settings (existing instance).
// Hence we guard against duplicate OnDeactivate() calls.
if (m_HasEditFocus)
{
OnFocusOut();
m_HasEditFocus = false;
}
InputSystem.onActionsChange -= BuildUI;
m_IsActivated = false;
// Always end a session when deactivated.
m_ActionEditorAnalytics?.End();
m_View?.DestroyView();
}
private void OnFocusIn(FocusInEvent @event = null)
{
if (!m_HasEditFocus)
{
m_HasEditFocus = true;
m_ActionEditorAnalytics.RegisterEditorFocusIn();
m_ActiveSettingsProvider = this;
SetIMGUIDropdownVisible(false, false);
}
}
void SaveAssetOnFocusLost()
{
#if UNITY_INPUT_SYSTEM_INPUT_ACTIONS_EDITOR_AUTO_SAVE_ON_FOCUS_LOST
var asset = GetAsset();
if (asset != null)
ValidateAndSaveAsset(asset);
#endif
}
public static void SetIMGUIDropdownVisible(bool visible, bool optionWasSelected)
{
if (m_ActiveSettingsProvider == null)
return;
// If we selected an item from the dropdown, we *should* still be focused on this settings window - but
// since the IMGUI dropdown is technically a separate window, we have to refocus manually.
//
// If we didn't select a dropdown option, there's not a simple way to know where the focus has gone,
// so assume we lost focus and save if appropriate. ISXB-801
if (!visible && m_IMGUIDropdownVisible)
{
if (optionWasSelected)
m_ActiveSettingsProvider.m_RootVisualElement.Focus();
else
m_ActiveSettingsProvider.SaveAssetOnFocusLost();
}
else if (visible && !m_IMGUIDropdownVisible)
{
m_ActiveSettingsProvider.m_HasEditFocus = false;
}
m_IMGUIDropdownVisible = visible;
}
private async void DelayFocusLost(bool relatedTargetWasNull)
{
await Task.Delay(120);
// We delay this call to ensure that the IMGUI flag has a chance to change first.
if (relatedTargetWasNull && m_HasEditFocus && !m_IMGUIDropdownVisible)
{
m_HasEditFocus = false;
SaveAssetOnFocusLost();
}
}
private void OnFocusOut(FocusOutEvent @event = null)
{
// This can be used to detect focus lost events of container elements, but will not detect window focus.
// Note that `event.relatedTarget` contains the element that gains focus, which is null if we select
// elements outside of project settings Editor Window. Also note that @event is null when we call this
// from OnDeactivate().
var element = (VisualElement)@event?.relatedTarget;
m_ActionEditorAnalytics.RegisterEditorFocusOut();
DelayFocusLost(element == null);
}
private void OnStateChanged(InputActionsEditorState newState)
{
#if UNITY_INPUT_SYSTEM_INPUT_ACTIONS_EDITOR_AUTO_SAVE_ON_FOCUS_LOST
// No action, auto-saved on edit-focus lost
#else
// Project wide input actions always auto save - don't check the asset auto save status
var asset = GetAsset();
if (asset != null)
ValidateAndSaveAsset(asset);
#endif
}
private void ValidateAndSaveAsset(InputActionAsset asset)
{
ProjectWideActionsAsset.Verify(asset); // Ignore verification result for save
EditorHelpers.SaveAsset(AssetDatabase.GetAssetPath(asset), asset.ToJson());
}
private void CreateUI()
{
var projectSettingsAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
InputActionsEditorConstants.PackagePath +
InputActionsEditorConstants.ResourcesPath +
InputActionsEditorConstants.ProjectSettingsUxml);
projectSettingsAsset.CloneTree(m_RootVisualElement);
m_RootVisualElement.styleSheets.Add(InputActionsEditorWindowUtils.theme);
}
private void BuildUI()
{
// Construct from InputSystem.actions asset
var asset = InputSystem.actions;
var hasAsset = asset != null;
m_State = (asset != null) ? new InputActionsEditorState(m_ActionEditorAnalytics, new SerializedObject(asset)) : default;
// Dynamically show a section indicating that an asset is missing if not currently having an associated asset
var missingAssetSection = m_RootVisualElement.Q<VisualElement>("missing-asset-section");
if (missingAssetSection != null)
{
missingAssetSection.style.visibility = hasAsset ? Visibility.Hidden : Visibility.Visible;
missingAssetSection.style.display = hasAsset ? DisplayStyle.None : DisplayStyle.Flex;
}
// Allow the user to select an asset out of the assets available in the project via picker.
// Note that we show "None" (null) even if InputSystem.actions is currently a broken/missing reference.
var objectField = m_RootVisualElement.Q<ObjectField>("current-asset");
if (objectField != null)
{
objectField.value = (asset == null) ? null : asset;
objectField.RegisterCallback<ChangeEvent<Object>>((evt) =>
{
if (evt.newValue != asset)
InputSystem.actions = evt.newValue as InputActionAsset;
});
// Prevent reassignment in in editor which would result in exception during play-mode
objectField.SetEnabled(!EditorApplication.isPlayingOrWillChangePlaymode);
}
// Configure a button to allow the user to create and assign a new project-wide asset based on default template
var createAssetButton = m_RootVisualElement.Q<Button>("create-asset");
createAssetButton?.RegisterCallback<ClickEvent>(evt =>
{
var assetPath = ProjectWideActionsAsset.defaultAssetPath;
Dialog.Result result = Dialog.Result.Discard;
if (AssetDatabase.LoadAssetAtPath<Object>(assetPath) != null)
result = Dialog.InputActionAsset.ShowCreateAndOverwriteExistingAsset(assetPath);
if (result == Dialog.Result.Discard)
InputSystem.actions = ProjectWideActionsAsset.CreateDefaultAssetAtPath(assetPath);
});
// Remove input action editor if already present
{
VisualElement element = m_RootVisualElement.Q("action-editor");
if (element != null)
m_RootVisualElement.Remove(element);
}
// If the editor is associated with an asset we show input action editor
if (hasAsset)
{
m_StateContainer = new StateContainer(m_State, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(asset)));
m_StateContainer.StateChanged += OnStateChanged;
m_View = new InputActionsEditorView(m_RootVisualElement, m_StateContainer, true, null);
m_StateContainer.Initialize(m_RootVisualElement.Q("action-editor"));
}
}
private InputActionAsset GetAsset()
{
return m_State.serializedObject?.targetObject as InputActionAsset;
}
private void SetObjectFieldEnabled(bool enabled)
{
// Update object picker enabled state based off editor play mode
if (m_RootVisualElement != null)
UQueryExtensions.Q<ObjectField>(m_RootVisualElement, "current-asset")?.SetEnabled(enabled);
}
private void ModeChanged(PlayModeStateChange change)
{
switch (change)
{
case PlayModeStateChange.EnteredEditMode:
SetObjectFieldEnabled(true);
break;
case PlayModeStateChange.ExitingEditMode:
// Ensure any changes are saved to the asset; FocusLost isn't always triggered when entering PlayMode.
SaveAssetOnFocusLost();
SetObjectFieldEnabled(false);
break;
case PlayModeStateChange.EnteredPlayMode:
case PlayModeStateChange.ExitingPlayMode:
default:
break;
}
}
[SettingsProvider]
public static SettingsProvider CreateGlobalInputActionsEditorProvider()
{
if (s_Provider == null)
s_Provider = new InputActionsEditorSettingsProvider(SettingsPath, SettingsScope.Project);
return s_Provider;
}
#region Shortcuts
[Shortcut("Input Action Editor/Project Settings/Add Action Map", null, KeyCode.M, ShortcutModifiers.Alt)]
private static void AddActionMapShortcut(ShortcutArguments arguments)
{
if (m_ActiveSettingsProvider is { m_HasEditFocus : true })
m_ActiveSettingsProvider.m_StateContainer.Dispatch(Commands.AddActionMap());
}
[Shortcut("Input Action Editor/Project Settings/Add Action", null, KeyCode.A, ShortcutModifiers.Alt)]
private static void AddActionShortcut(ShortcutArguments arguments)
{
if (m_ActiveSettingsProvider is { m_HasEditFocus : true })
m_ActiveSettingsProvider.m_StateContainer.Dispatch(Commands.AddAction());
}
[Shortcut("Input Action Editor/Project Settings/Add Binding", null, KeyCode.B, ShortcutModifiers.Alt)]
private static void AddBindingShortcut(ShortcutArguments arguments)
{
if (m_ActiveSettingsProvider is { m_HasEditFocus : true })
m_ActiveSettingsProvider.m_StateContainer.Dispatch(Commands.AddBinding());
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18d3e83390dcd6349b3086b9f70391b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,475 @@
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using UnityEditor;
namespace UnityEngine.InputSystem.Editor
{
[System.Serializable]
internal class CutElement
{
private Guid id;
internal Type type;
public CutElement(Guid id, Type type)
{
this.id = id;
this.type = type;
}
public int GetIndexOfProperty(InputActionsEditorState state)
{
if (type == typeof(InputActionMap))
{
var actionMap = state.serializedObject
?.FindProperty(nameof(InputActionAsset.m_ActionMaps))
?.FirstOrDefault(s => InputActionSerializationHelpers.GetId(s).Equals(id));
return actionMap.GetIndexOfArrayElement();
}
if (type == typeof(InputAction))
{
var action = Selectors.GetActionMapAtIndex(state, actionMapIndex(state))?.wrappedProperty.FindPropertyRelative("m_Actions").FirstOrDefault(a => InputActionSerializationHelpers.GetId(a).Equals(id));
return action.GetIndexOfArrayElement();
}
if (type == typeof(InputBinding))
{
var binding = Selectors.GetBindingForId(state, id.ToString(),
out _);
return binding.GetIndexOfArrayElement();
}
return -1;
}
public int actionMapIndex(InputActionsEditorState state) => type == typeof(InputActionMap) ? GetIndexOfProperty(state) : GetActionMapIndex(state);
private int GetActionMapIndex(InputActionsEditorState state)
{
var actionMaps = state.serializedObject?.FindProperty(nameof(InputActionAsset.m_ActionMaps));
var cutActionMapIndex = state.serializedObject
?.FindProperty(nameof(InputActionAsset.m_ActionMaps))
?.FirstOrDefault(s => s.FindPropertyRelative("m_Id").stringValue.Equals(id)).GetIndexOfArrayElement();
if (type == typeof(InputBinding))
cutActionMapIndex = actionMaps.FirstOrDefault(map => map.FindPropertyRelative("m_Bindings").Select(InputActionSerializationHelpers.GetId).Contains(id)).GetIndexOfArrayElement();
else if (type == typeof(InputAction))
cutActionMapIndex = actionMaps.FirstOrDefault(map => map.FindPropertyRelative("m_Actions").Select(InputActionSerializationHelpers.GetId).Contains(id)).GetIndexOfArrayElement();
return cutActionMapIndex ?? -1;
}
}
internal struct InputActionsEditorState
{
public int selectedActionMapIndex { get {return m_selectedActionMapIndex; } }
public int selectedActionIndex { get {return m_selectedActionIndex; } }
public int selectedBindingIndex { get {return m_selectedBindingIndex; } }
public SelectionType selectionType { get {return m_selectionType; } }
public SerializedObject serializedObject { get; } // Note that state doesn't own this disposable object
private readonly List<CutElement> cutElements => m_CutElements;
// Control schemes
public int selectedControlSchemeIndex { get { return m_selectedControlSchemeIndex; } }
public int selectedDeviceRequirementIndex { get {return m_selectedDeviceRequirementIndex; } }
public InputControlScheme selectedControlScheme => m_ControlScheme; // TODO Bad this either po
internal InputActionsEditorSessionAnalytic m_Analytics;
[SerializeField] int m_selectedActionMapIndex;
[SerializeField] int m_selectedActionIndex;
[SerializeField] int m_selectedBindingIndex;
[SerializeField] SelectionType m_selectionType;
[SerializeField] int m_selectedControlSchemeIndex;
[SerializeField] int m_selectedDeviceRequirementIndex;
private List<CutElement> m_CutElements;
internal bool hasCutElements => m_CutElements != null && m_CutElements.Count > 0;
public InputActionsEditorState(
InputActionsEditorSessionAnalytic analytics,
SerializedObject inputActionAsset,
int selectedActionMapIndex = 0,
int selectedActionIndex = 0,
int selectedBindingIndex = 0,
SelectionType selectionType = SelectionType.Action,
Dictionary<(string, string), HashSet<int>> expandedBindingIndices = null,
InputControlScheme selectedControlScheme = default,
int selectedControlSchemeIndex = -1,
int selectedDeviceRequirementIndex = -1,
List<CutElement> cutElements = null)
{
Debug.Assert(inputActionAsset != null);
m_Analytics = analytics;
serializedObject = inputActionAsset;
m_selectedActionMapIndex = selectedActionMapIndex;
m_selectedActionIndex = selectedActionIndex;
m_selectedBindingIndex = selectedBindingIndex;
m_selectionType = selectionType;
m_ControlScheme = selectedControlScheme;
m_selectedControlSchemeIndex = selectedControlSchemeIndex;
m_selectedDeviceRequirementIndex = selectedDeviceRequirementIndex;
m_ExpandedCompositeBindings = expandedBindingIndices == null ?
new Dictionary<(string, string), HashSet<int>>() :
new Dictionary<(string, string), HashSet<int>>(expandedBindingIndices);
m_CutElements = cutElements;
}
public InputActionsEditorState(InputActionsEditorState other, SerializedObject asset)
{
m_Analytics = other.m_Analytics;
// Assign serialized object, not that this might be equal to other.serializedObject,
// a slight variation of it with any kind of changes or a completely different one.
// Hence, we do our best here to keep any selections consistent by remapping objects
// based on GUIDs (IDs) and when it fails, attempt to select first object and if that
// fails revert to not having a selection. This would even be true for domain reloads
// if the asset would be modified during domain reload.
serializedObject = asset;
if (other.Equals(default(InputActionsEditorState)))
{
// This instance was created by default constructor and thus is missing some appropriate defaults:
other.m_selectionType = SelectionType.Action;
other.m_selectedControlSchemeIndex = -1;
other.m_selectedDeviceRequirementIndex = -1;
}
// Attempt to preserve action map selection by GUID, otherwise select first or last resort none
var otherSelectedActionMap = other.GetSelectedActionMap();
var actionMapCount = Selectors.GetActionMapCount(asset);
m_selectedActionMapIndex = otherSelectedActionMap != null
? Selectors.GetActionMapIndexFromId(asset,
InputActionSerializationHelpers.GetId(otherSelectedActionMap))
: actionMapCount > 0 ? 0 : -1;
var selectedActionMap = m_selectedActionMapIndex >= 0
? Selectors.GetActionMapAtIndex(asset, m_selectedActionMapIndex)?.wrappedProperty : null;
// Attempt to preserve action selection by GUID, otherwise select first or last resort none
var otherSelectedAction = m_selectedActionMapIndex >= 0 ?
Selectors.GetSelectedAction(other) : null;
m_selectedActionIndex = selectedActionMap != null && otherSelectedAction.HasValue
? Selectors.GetActionIndexFromId(selectedActionMap,
InputActionSerializationHelpers.GetId(otherSelectedAction.Value.wrappedProperty))
: Selectors.GetActionCount(selectedActionMap) > 0 ? 0 : -1;
// Attempt to preserve binding selection by GUID, otherwise select first or none
m_selectedBindingIndex = -1;
if (m_selectedActionMapIndex >= 0)
{
var otherSelectedBinding = Selectors.GetSelectedBinding(other);
if (otherSelectedBinding != null)
{
var otherSelectedBindingId =
InputActionSerializationHelpers.GetId(otherSelectedBinding.Value.wrappedProperty);
var binding = Selectors.GetBindingForId(asset, otherSelectedBindingId.ToString(), out _);
if (binding != null)
m_selectedBindingIndex = binding.GetIndexOfArrayElement();
}
}
// Sanity check selection type and override any previous selection if not valid given indices
// since we have remapped GUIDs to selection indices for another asset (SerializedObject)
if (other.m_selectionType == SelectionType.Binding && m_selectedBindingIndex < 0)
m_selectionType = SelectionType.Action;
else
m_selectionType = other.m_selectionType;
m_selectedControlSchemeIndex = other.m_selectedControlSchemeIndex;
m_selectedDeviceRequirementIndex = other.m_selectedDeviceRequirementIndex;
// Selected ControlScheme index is serialized but we have to recreated actual object after domain reload.
// In case asset is different from from others asset the index might not even be valid range so we need
// to reattempt to preserve selection but range adapt.
// Note that control schemes and device requirements currently lack any GUID/ID to be uniquely identified.
var controlSchemesArrayProperty = serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes));
if (m_selectedControlSchemeIndex >= 0 && controlSchemesArrayProperty.arraySize > 0)
{
if (m_selectedControlSchemeIndex >= controlSchemesArrayProperty.arraySize)
m_selectedControlSchemeIndex = 0;
m_ControlScheme = new InputControlScheme(
controlSchemesArrayProperty.GetArrayElementAtIndex(other.m_selectedControlSchemeIndex));
// TODO Preserve device requirement index
}
else
{
m_selectedControlSchemeIndex = -1;
m_selectedDeviceRequirementIndex = -1;
m_ControlScheme = new InputControlScheme();
}
// Editor may leave these as null after domain reloads, so recreate them in that case.
// If they exist, we attempt to just preserve the same expanded items based on name for now for simplicity.
m_ExpandedCompositeBindings = other.m_ExpandedCompositeBindings == null ?
new Dictionary<(string, string), HashSet<int>>() :
new Dictionary<(string, string), HashSet<int>>(other.m_ExpandedCompositeBindings);
m_CutElements = other.cutElements;
}
public InputActionsEditorState With(
int? selectedActionMapIndex = null,
int? selectedActionIndex = null,
int? selectedBindingIndex = null,
SelectionType? selectionType = null,
InputControlScheme? selectedControlScheme = null,
int? selectedControlSchemeIndex = null,
int? selectedDeviceRequirementIndex = null,
Dictionary<(string, string), HashSet<int>> expandedBindingIndices = null,
List<CutElement> cutElements = null)
{
return new InputActionsEditorState(
m_Analytics,
serializedObject,
selectedActionMapIndex ?? this.selectedActionMapIndex,
selectedActionIndex ?? this.selectedActionIndex,
selectedBindingIndex ?? this.selectedBindingIndex,
selectionType ?? this.selectionType,
expandedBindingIndices ?? m_ExpandedCompositeBindings,
// Control schemes
selectedControlScheme ?? this.selectedControlScheme,
selectedControlSchemeIndex ?? this.selectedControlSchemeIndex,
selectedDeviceRequirementIndex ?? this.selectedDeviceRequirementIndex,
cutElements ?? m_CutElements
);
}
public InputActionsEditorState ClearCutElements()
{
return new InputActionsEditorState(
m_Analytics,
serializedObject,
selectedActionMapIndex,
selectedActionIndex,
selectedBindingIndex,
selectionType,
m_ExpandedCompositeBindings,
selectedControlScheme,
selectedControlSchemeIndex,
selectedDeviceRequirementIndex,
cutElements: null);
}
public SerializedProperty GetActionMapByName(string actionMapName)
{
return serializedObject
.FindProperty(nameof(InputActionAsset.m_ActionMaps))
.FirstOrDefault(p => p.FindPropertyRelative(nameof(InputActionMap.m_Name)).stringValue == actionMapName);
}
public InputActionsEditorState ExpandCompositeBinding(SerializedInputBinding binding)
{
var key = GetSelectedActionMapAndActionKey();
var expandedCompositeBindings = new Dictionary<(string, string), HashSet<int>>(m_ExpandedCompositeBindings);
if (!expandedCompositeBindings.TryGetValue(key, out var expandedStates))
{
expandedStates = new HashSet<int>();
expandedCompositeBindings.Add(key, expandedStates);
}
expandedStates.Add(binding.indexOfBinding);
return With(expandedBindingIndices: expandedCompositeBindings);
}
public InputActionsEditorState CollapseCompositeBinding(SerializedInputBinding binding)
{
var key = GetSelectedActionMapAndActionKey();
if (m_ExpandedCompositeBindings.ContainsKey(key) == false)
throw new InvalidOperationException("Trying to collapse a composite binding tree that was never expanded.");
// do the dance of C# immutability
var oldExpandedCompositeBindings = m_ExpandedCompositeBindings;
var expandedCompositeBindings = oldExpandedCompositeBindings.Keys.Where(dictKey => dictKey != key)
.ToDictionary(dictKey => dictKey, dictKey => oldExpandedCompositeBindings[dictKey]);
var newHashset = new HashSet<int>(m_ExpandedCompositeBindings[key].Where(index => index != binding.indexOfBinding));
expandedCompositeBindings.Add(key, newHashset);
return With(expandedBindingIndices: expandedCompositeBindings);
}
public InputActionsEditorState SelectAction(string actionName)
{
var actionMap = GetSelectedActionMap();
var actions = actionMap.FindPropertyRelative(nameof(InputActionMap.m_Actions));
for (var i = 0; i < actions.arraySize; i++)
{
if (actions.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(InputAction.m_Name)).stringValue != actionName) continue;
return With(selectedActionIndex: i, selectionType: SelectionType.Action);
}
// If we cannot find the desired map we should return invalid index
return With(selectedActionIndex: -1, selectionType: SelectionType.Action);
}
public InputActionsEditorState SelectAction(SerializedProperty state)
{
var index = state.GetIndexOfArrayElement();
return With(selectedActionIndex: index, selectionType: SelectionType.Action);
}
public InputActionsEditorState SelectActionMap(SerializedProperty actionMap)
{
var index = actionMap.GetIndexOfArrayElement();
return With(selectedBindingIndex: 0, selectedActionMapIndex: index, selectedActionIndex: 0);
}
public InputActionsEditorState SelectActionMap(string actionMapName)
{
var actionMap = GetActionMapByName(actionMapName);
return With(selectedBindingIndex: 0,
selectedActionMapIndex: actionMap.GetIndexOfArrayElement(),
selectedActionIndex: 0, selectionType: SelectionType.Action);
}
public InputActionsEditorState SelectBinding(int index)
{
//if no binding selected (due to no bindings in list) set selection type to action
if (index == -1)
return With(selectedBindingIndex: index, selectionType: SelectionType.Action);
return With(selectedBindingIndex: index, selectionType: SelectionType.Binding);
}
public InputActionsEditorState SelectAction(int index)
{
//if no action selected (no actions available) set selection type to none
if (index == -1)
return With(selectedActionIndex: index, selectionType: SelectionType.None);
return With(selectedActionIndex: index, selectionType: SelectionType.Action);
}
public InputActionsEditorState SelectActionMap(int index)
{
if (index == -1)
return With(selectedActionMapIndex: index, selectionType: SelectionType.None);
return With(selectedBindingIndex: 0,
selectedActionMapIndex: index,
selectedActionIndex: 0, selectionType: SelectionType.Action);
}
public InputActionsEditorState CutActionOrBinding()
{
m_CutElements = new List<CutElement>();
var type = selectionType == SelectionType.Action ? typeof(InputAction) : typeof(InputBinding);
var property = selectionType == SelectionType.Action ? Selectors.GetSelectedAction(this)?.wrappedProperty : Selectors.GetSelectedBinding(this)?.wrappedProperty;
cutElements.Add(new CutElement(InputActionSerializationHelpers.GetId(property), type));
return With(cutElements: cutElements);
}
public InputActionsEditorState CutActionMaps()
{
m_CutElements = new List<CutElement> { new(InputActionSerializationHelpers.GetId(Selectors.GetSelectedActionMap(this)?.wrappedProperty), typeof(InputActionMap)) };
return With(cutElements: cutElements);
}
public IEnumerable<string> GetDisabledActionMaps(List<string> allActionMaps)
{
if (cutElements == null || cutElements == null)
return Enumerable.Empty<string>();
var cutActionMaps = cutElements.Where(cut => cut.type == typeof(InputActionMap));
var state = this;
return allActionMaps.Where(actionMapName =>
{
return cutActionMaps.Any(am => am.GetIndexOfProperty(state) == allActionMaps.IndexOf(actionMapName));
});
}
public readonly bool IsBindingCut(int actionMapIndex, int bindingIndex)
{
if (cutElements == null)
return false;
var state = this;
return cutElements.Any(cutElement => cutElement.actionMapIndex(state) == actionMapIndex &&
cutElement.GetIndexOfProperty(state) == bindingIndex &&
cutElement.type == typeof(InputBinding));
}
public readonly bool IsActionCut(int actionMapIndex, int actionIndex)
{
if (cutElements == null)
return false;
var state = this;
return cutElements.Any(cutElement => cutElement.actionMapIndex(state) == actionMapIndex &&
cutElement.GetIndexOfProperty(state) == actionIndex &&
cutElement.type == typeof(InputAction));
}
public readonly bool IsActionMapCut(int actionMapIndex)
{
if (cutElements == null)
return false;
var state = this;
return cutElements.Any(cutElement => cutElement.GetIndexOfProperty(state) == actionMapIndex && cutElement.type == typeof(InputActionMap));
}
public readonly List<CutElement> GetCutElements()
{
return m_CutElements;
}
public ReadOnlyCollection<int> GetOrCreateExpandedState()
{
return new ReadOnlyCollection<int>(GetOrCreateExpandedStateInternal().ToList());
}
private HashSet<int> GetOrCreateExpandedStateInternal()
{
var key = GetSelectedActionMapAndActionKey();
if (m_ExpandedCompositeBindings.TryGetValue(key, out var expandedStates))
return expandedStates;
expandedStates = new HashSet<int>();
m_ExpandedCompositeBindings.Add(key, expandedStates);
return expandedStates;
}
internal (string, string) GetSelectedActionMapAndActionKey()
{
var selectedActionMap = GetSelectedActionMap();
var selectedAction = selectedActionMap
.FindPropertyRelative(nameof(InputActionMap.m_Actions))
.GetArrayElementAtIndex(selectedActionIndex);
var key = (
selectedActionMap.FindPropertyRelative(nameof(InputActionMap.m_Name)).stringValue,
selectedAction.FindPropertyRelative(nameof(InputAction.m_Name)).stringValue
);
return key;
}
private SerializedProperty GetSelectedActionMap()
{
return Selectors.GetActionMapAtIndex(serializedObject, selectedActionMapIndex)?.wrappedProperty;
}
/// <summary>
/// Expanded states for the actions tree view. These are stored per InputActionMap
/// </summary>
private readonly Dictionary<(string, string), HashSet<int>> m_ExpandedCompositeBindings;
private readonly InputControlScheme m_ControlScheme;
}
internal enum SelectionType
{
None,
Action,
Binding
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a8e0b5c429811847b8c97a058e5884f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e68462a09b6ba104abce11d2d157d0b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
#if UNITY_EDITOR
using System;
using System.IO;
using UnityEditor;
using UnityEngine.UIElements;
namespace UnityEngine.InputSystem.Editor
{
internal static class InputActionsEditorWindowUtils
{
/// <summary>
/// Return a relative path to the currently active theme style sheet.
/// </summary>
public static StyleSheet theme => EditorGUIUtility.isProSkin
? AssetDatabase.LoadAssetAtPath<StyleSheet>(InputActionsEditorConstants.PackagePath + InputActionsEditorConstants.ResourcesPath + "/InputAssetEditorDark.uss")
: AssetDatabase.LoadAssetAtPath<StyleSheet>(InputActionsEditorConstants.PackagePath + InputActionsEditorConstants.ResourcesPath + "/InputAssetEditorLight.uss");
// Similar to InputActionAsset.WriteFileJson but excludes the name
[Serializable]
private struct WriteFileJsonNoName
{
public InputActionMap.WriteMapJson[] maps;
public InputControlScheme.SchemeJson[] controlSchemes;
}
// Similar to InputActionAsset.ToJson() but converts to JSON excluding the name property and any additional JSON
// content that may be part of the file not recognized as required data.
public static string ToJsonWithoutName(InputActionAsset asset)
{
return JsonUtility.ToJson(new WriteFileJsonNoName
{
maps = InputActionMap.WriteFileJson.FromMaps(asset.m_ActionMaps).maps,
controlSchemes = InputControlScheme.SchemeJson.ToJson(asset.m_ControlSchemes),
}, prettyPrint: true);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b8e35f20292579409c899395e30948f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7894838fa258e3a4197077ddbda0eec5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement name="item-row" class="unity-list-view__item" style="flex-direction: column; flex-grow: 1; justify-content: center; margin-left: 4px;">
<ui:VisualElement name="row" style="flex-direction: row; border-left-width: 0; border-left-color: rgb(89, 89, 89);">
<ui:Toggle name="expando" class="unity-foldout__toggle" style="visibility: hidden; margin-left: 3px;" />
<ui:VisualElement name="icon" style="justify-content: center; background-image: url(&apos;project://database/Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_InputControl.png?fileID=2800000&amp;guid=399cd90f4e31041e692a7d3a8b1aa4d0&amp;type=3#d_InputControl&apos;); width: 16px; height: 16px;" />
<ui:Label text="binding-name" display-tooltip-when-elided="true" name="name" style="flex-grow: 1; justify-content: center; align-items: stretch; margin-left: 4px; -unity-font-style: normal;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 449c8e5ca27af8e4a9db710c8be5e4df
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,5 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement>
<ui:DropdownField label="Composite Type" index="-1" choices="System.Collections.Generic.List`1[System.String]" name="composite-type-dropdown" tooltip="Type of composite. Allows changing the composite type retroactively. Doing so will modify the bindings that are part of the composite." />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2bd2d0548382d58489e8c2999daf4139
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,6 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement>
<ui:IMGUIContainer name="path-editor-container" />
<ui:DropdownField label="Composite Part" index="-1" choices="System.Collections.Generic.List`1[System.String]" name="composite-part-dropdown" tooltip="The named part of the composite that the binding is assigned to. Multiple bindings may be assigned the same part. All controls from all bindings that are assigned the same part will collectively feed values into that part of the composite." />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: acfae125fa5d7904987a696b3993d432
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,19 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement>
<ui:VisualElement name="SchemeName">
<ui:TextField picking-mode="Ignore" label="Scheme Name" value="New control scheme" text="New Control Scheme" name="control-scheme-name" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-grow: 0;">
<ui:MultiColumnListView focusable="true" reorderable="true" show-foldout-header="false" show-add-remove-footer="true" reorder-mode="Animated" show-border="true" show-bound-collection-size="false" name="control-schemes-list-view" show-alternating-row-backgrounds="ContentOnly" style="flex-grow: 1;">
<ui:Columns>
<ui:Column name="device-type" title="Device Type" width="250" resizable="false" sortable="false" />
<ui:Column name="required" title="Required" width="70" resizable="false" sortable="false" />
</ui:Columns>
</ui:MultiColumnListView>
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; align-items: stretch; justify-content: space-around;">
<ui:Button text="Cancel" display-tooltip-when-elided="true" name="cancel-button" style="flex-grow: 1;" />
<ui:Button text="Save" display-tooltip-when-elided="true" name="save-button" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 303ef5b13740f9a4db252c50122d2c62
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,10 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/PackageResources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
<ui:VisualElement name="item-row" class="unity-list-view__item" style="flex-direction: row; flex-grow: 1; justify-content: space-between; margin-left: 4px; flex-shrink: 0;">
<ui:VisualElement name="row" style="flex-direction: row; border-left-width: 0; border-left-color: rgb(89, 89, 89); justify-content: flex-start; align-items: center;">
<ui:TextField picking-mode="Ignore" name="rename-text-field" is-delayed="true" focusable="true" class="unity-input-actions-editor-hidden" style="visibility: visible; flex-shrink: 1;" />
<ui:Label text="binding-name" display-tooltip-when-elided="true" name="name" style="flex-grow: 1; justify-content: center; align-items: stretch; margin-left: 4px; -unity-font-style: normal;" />
</ui:VisualElement>
<ui:Button text="+" display-tooltip-when-elided="true" enable-rich-text="false" name="add-new-binding-button" style="opacity: 1; background-color: rgba(255, 255, 255, 0); border-left-color: rgba(255, 255, 255, 0); border-right-color: rgba(255, 255, 255, 0); border-top-color: rgba(255, 255, 255, 0); border-bottom-color: rgba(255, 255, 255, 0); display: none; align-items: flex-end; align-self: auto; flex-direction: row-reverse;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3fa44185ed614414ebab354dfe5a06b6
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,60 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/PackageResources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
<ui:VisualElement name="action-editor" style="flex-direction: column; flex-grow: 1;">
<ui:VisualElement name="control-schemes-toolbar-container">
<uie:Toolbar>
<ui:VisualElement style="flex-direction: row; flex-grow: 1;">
<uie:ToolbarMenu display-tooltip-when-elided="true" text="No Control Schemes" name="control-schemes-toolbar-menu" style="min-width: 135px;" />
<uie:ToolbarMenu display-tooltip-when-elided="true" text="All Devices" enabled="false" name="control-schemes-filter-toolbar-menu" />
</ui:VisualElement>
<ui:VisualElement>
<uie:ToolbarSearchField focusable="true" name="search-actions-text-field" class="search-field" style="display: none;" />
</ui:VisualElement>
<ui:VisualElement name="save-asset-toolbar-container" style="flex-direction: row; justify-content: flex-end;">
<uie:ToolbarButton text="Save Asset" display-tooltip-when-elided="true" name="save-asset-toolbar-button" style="align-items: auto;" />
<uie:ToolbarToggle focusable="false" label="Auto-Save" name="auto-save-toolbar-toggle" style="width: 69px;" />
</ui:VisualElement>
</uie:Toolbar>
</ui:VisualElement>
<ui:VisualElement name="body" style="flex-direction: column; flex-grow: 1;">
<ui:TwoPaneSplitView name="actions-split-view" fixed-pane-initial-dimension="200">
<ui:VisualElement name="action-maps-container" class="body-panel-container actions-container">
<ui:VisualElement name="header" class="body-panel-header">
<ui:Label text="Action Maps" display-tooltip-when-elided="true" style="flex-grow: 1;" />
<ui:Button text="+" display-tooltip-when-elided="true" name="add-new-action-map-button" style="align-items: auto;" />
</ui:VisualElement>
<ui:VisualElement name="body">
<ui:ListView focusable="true" name="action-maps-list-view" />
</ui:VisualElement>
<ui:VisualElement name="rclick-area-to-add-new-action-map" style="flex-direction: column; flex-grow: 1;" />
</ui:VisualElement>
<ui:TwoPaneSplitView name="actions-and-properties-split-view" fixed-pane-index="1" fixed-pane-initial-dimension="230" style="height: auto; min-width: 450px">
<ui:VisualElement name="actions-container" class="body-panel-container">
<ui:VisualElement name="header" class="body-panel-header" style="justify-content: space-between;">
<ui:Label text="Actions" display-tooltip-when-elided="true" name="actions-label" />
<ui:Button text="+" display-tooltip-when-elided="true" name="add-new-action-button" style="align-items: auto;" />
</ui:VisualElement>
<ui:VisualElement name="body">
<ui:TreeView view-data-key="unity-tree-view" focusable="true" name="actions-tree-view" show-border="false" reorderable="true" show-alternating-row-backgrounds="None" fixed-item-height="20" />
</ui:VisualElement>
<ui:VisualElement name="rclick-area-to-add-new-action" style="flex-direction: column; flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="properties-container" class="body-panel-container body-panel-container" style="min-width: 220;">
<ui:VisualElement name="header" class="body-panel-header">
<ui:Label text="Action Properties" display-tooltip-when-elided="true" name="properties-header-label" />
</ui:VisualElement>
<ui:ScrollView name="properties-scrollview">
<ui:Foldout text="Action Properties" name="properties-foldout" class="properties-foldout" />
<ui:Foldout text="Interactions" name="interactions-foldout" class="properties-foldout name-and-parameters-list-view">
<ui:Label text="No interactions have been added." name="no-parameters-added-label" display-tooltip-when-elided="true" class="name-and-parameter-empty-label" style="display: flex;" />
</ui:Foldout>
<ui:Foldout text="Processors" name="processors-foldout" class="properties-foldout name-and-parameters-list-view">
<ui:Label text="No processors have been added." name="no-parameters-added-label" display-tooltip-when-elided="true" class="name-and-parameter-empty-label" />
</ui:Foldout>
</ui:ScrollView>
</ui:VisualElement>
</ui:TwoPaneSplitView>
</ui:TwoPaneSplitView>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c662e0d3cc3c4f948808f9847f715ef2
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,215 @@
.unity-input-actions-editor-hidden {
display: none;
}
.asset-menu-button-dark-theme {
background-image: resource('d__Menu.png');
}
.asset-menu-button {
background-image: resource('_Menu.png');
-unity-background-scale-mode: scale-to-fit;
}
.body-panel-container {
min-width: 150px;
border-top-width: 1px;
border-left-color: rgb(25, 25, 25);
border-right-color: rgb(25, 25, 25);
border-top-color: rgb(25, 25, 25);
border-bottom-color: rgb(25, 25, 25);
border-right-width: 0;
}
#actions-container {
min-width: 225px;
}
#selected-action-map-dropdown > .unity-popup-field__input {
-unity-font-style: normal;
}
#add-new-action-map-button {
background-color: transparent;
border-width: 0;
}
#add-new-action-button {
background-color: transparent;
border-width: 0;
}
#bindings-container {
min-width: 225px;
border-left-width: 0;
margin-left: 0;
}
.add-interaction-processor-button {
padding-top: 0;
font-size: 12px;
border-width: 0;
background-color: transparent;
margin-right: 5px;
}
.header {
height: 22px;
flex-direction: row;
margin-left: 10px;
margin-right: 7px;
margin-top: 1px;
margin-bottom: 7px;
}
.header-label {
font-size: 19px;
-unity-font-style: bold;
margin: 0;
padding: 0;
width: auto;
flex-grow: 1;
}
.header-search-box {
justify-content: flex-start;
position: relative;
right: auto;
width: 171px;
border-left-color: rgb(23, 23, 23);
border-right-color: rgb(23, 23, 23);
border-top-color: rgb(23, 23, 23);
border-bottom-color: rgb(23, 23, 23);
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
margin-left: 3px;
margin-right: 3px;
margin-top: 1px;
margin-bottom: 1px;
align-items: auto;
padding-top: 7px;
padding-bottom: 7px;
}
.tree-view-item-icon{
justify-content: center;
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_InputControl.png');
width: 16px;
height: 16px;
}
.body-panel-header {
background-color: var(--unity-colors-toolbar-background);
border-bottom-color: var(--unity-colors-toolbar-border);
flex-direction: row;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 5px;
padding-right: 3px;
padding-top: 4px;
padding-bottom: 4px;
border-bottom-width: 1px;
height: 28px;
min-height: 28px;
font-size: 14px;
-unity-font-style: bold;
align-items: center;
justify-content: flex-start;
-unity-text-align: middle-left;
}
.properties-foldout {
margin: 0;
padding-bottom: 15px;
}
.properties-foldout-toggle {
background-color: var(--input-editor-colors-properties-foldout);
}
.name-and-parameter-empty-label {
margin-top: 5px;
font-size: 12px;
color: rgb(130, 130, 130);
}
.name-and-parameters-list-foldout {
}
.name-and-parameters-list-view .name-and-parameters-list-foldout-button {
width: 12px;
height: 12px;
background-color: transparent;
border-width: 0;
}
.name-and-parameters-list-view .open-settings-button {
width: 120px;
align-items: flex-end;
}
.float-field {
width: 50px;
display: initial;
}
.name-and-parameters-list-view .up {
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/ChevronUp.png');
}
.name-and-parameters-list-view .upDarkTheme {
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_ChevronUp.png');
}
.name-and-parameters-list-view .down {
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/ChevronDown.png');
}
.name-and-parameters-list-view .downDarkTheme {
background-image: resource('Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_ChevronDown.png');
}
.name-and-parameters-list-view .delete {
background-image: resource('Toolbar Minus.png');
}
.name-and-parameters-list-view .deleteDarkTheme {
background-image: resource('d_Toolbar Minus.png');
}
.add-binging-button-dark-theme {
background-image: resource('d_Toolbar Plus More.png');
-unity-background-scale-mode: scale-to-fit;
}
.add-binging-button {
background-image: resource('Toolbar Plus More.png');
-unity-background-scale-mode: scale-to-fit;
}
.search-field {
display: none;
width: 190px;
}
.unity-two-pane-split-view__dragline-anchor {
background-color: rgb(25, 25, 25);
}
#control-scheme-usage-title {
margin: 3px;
-unity-font-style: bold;
}
.matching-controls {
display: flex;
flex-grow: 1;
}
.matching-controls-labels {
margin: 1px;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7dac9c49a90bca4499371d0adc9b617b
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,14 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/PackageResources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
<ui:VisualElement name="header" class="header">
<ui:Label text="Input Actions" display-tooltip-when-elided="true" name="title-label" class="header-label" />
<ui:VisualElement name="asset-menu" style="flex-grow: 0; background-color: rgba(0, 0, 0, 0); width: 16px; flex-shrink: 0; -unity-background-scale-mode: scale-to-fit;" />
</ui:VisualElement>
<ui:VisualElement name="current-asset-section">
<uie:ObjectField name="current-asset" type="UnityEngine.InputSystem.InputActionAsset, Unity.InputSystem" label="Project-wide Actions" />
</ui:VisualElement>
<ui:VisualElement name="missing-asset-section">
<ui:HelpBox text="Actions for the Input System are stored in an Action Asset. You can assign an Action Asset as project-wide in the field above to make them accessible directly through the InputSystem.actions API.&#10;&#10;Click the button below to create a new Action Asset containing default actions, which will be assigned as project-wide." message-type="Info"/>
<ui:Button text="Create and assign a default project-wide Action Asset" name="create-asset"/>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 75a33987e21d5ac449deecea3dcd864f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,11 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/PackageResources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
<ui:VisualElement name="item-row" class="unity-list-view__item" style="flex-direction: row; flex-grow: 1; justify-content: space-between; margin-left: 4px; flex-shrink: 0;">
<ui:VisualElement name="row" style="flex-direction: row; border-left-width: 0; border-left-color: rgb(89, 89, 89); justify-content: flex-start; align-items: center;">
<ui:VisualElement name="icon" class="tree-view-item-icon" style="height: 19px; -unity-background-scale-mode: scale-to-fit;" />
<ui:TextField picking-mode="Ignore" name="rename-text-field" is-delayed="true" focusable="true" class="unity-input-actions-editor-hidden" style="visibility: visible; flex-shrink: 1;" />
<ui:Label text="binding-name" display-tooltip-when-elided="true" name="name" style="flex-grow: 1; justify-content: center; align-items: stretch; margin-left: 4px; -unity-font-style: normal;" />
</ui:VisualElement>
<ui:Button display-tooltip-when-elided="true" enable-rich-text="false" name="add-new-binding-button" style="opacity: 1; background-color: rgba(255, 255, 255, 0); border-left-color: rgba(255, 255, 255, 0); border-right-color: rgba(255, 255, 255, 0); border-top-color: rgba(255, 255, 255, 0); border-bottom-color: rgba(255, 255, 255, 0); display: none; align-items: flex-end; align-self: auto; flex-direction: row-reverse; margin-right: 6px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 452df07a8ad0c944c879a484d5890e61
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,4 @@
:root {
--input-editor-colors-properties-foldout: rgb(34, 34, 34);
--input-editor-colors-properties-foldout-border: #808080;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cca9ce0c8554d5244930f14c21489ac1
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,4 @@
:root {
--input-editor-colors-properties-foldout: #DFDFDF;
--input-editor-colors-properties-foldout-border: #808080;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e7024ed0fd03984289320d04507bc0c
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,6 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/PackageResources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
<ui:VisualElement style="margin-bottom: 0; border-bottom-width: 1px; padding-bottom: 5px;">
<ui:Foldout text="Foldout" name="Foldout" value="true" class="name-and-parameters-list-foldout" style="align-items: stretch;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9cbd73d51dc491b4888055ae65cd9545
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,28 @@
#if UNITY_EDITOR
using System;
namespace UnityEngine.InputSystem.Editor
{
internal class ReactiveProperty<T>
{
private T m_Value;
public event Action<T> Changed;
public T value
{
get => m_Value;
set
{
m_Value = value;
Changed?.Invoke(m_Value);
}
}
public void SetValueWithoutChangeNotification(T value)
{
m_Value = value;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6f2f33363708814e8530579e2d8cf2d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using System;
using UnityEditor;
namespace UnityEngine.InputSystem.Editor
{
internal readonly struct SerializedInputAction
{
public SerializedInputAction(SerializedProperty serializedProperty)
{
// TODO: check that the passed serialized property actually is an InputAction. Reflect over all
// serialized fields and make sure they're present?
wrappedProperty = serializedProperty ?? throw new ArgumentNullException(nameof(serializedProperty));
id = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Id)).stringValue;
name = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Name)).stringValue;
expectedControlType = ReadExpectedControlType(serializedProperty);
type = (InputActionType)serializedProperty.FindPropertyRelative(nameof(InputAction.m_Type)).intValue;
interactions = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Interactions)).stringValue;
processors = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Processors)).stringValue;
propertyPath = wrappedProperty.propertyPath;
initialStateCheck = ReadInitialStateCheck(serializedProperty);
actionTypeTooltip = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Type)).GetTooltip();
expectedControlTypeTooltip = serializedProperty.FindPropertyRelative(nameof(InputAction.m_ExpectedControlType)).GetTooltip();
}
public string id { get; }
public string name { get; }
public string expectedControlType { get; }
public InputActionType type { get; }
public string interactions { get; }
public string processors { get; }
public string propertyPath { get; }
public bool initialStateCheck { get; }
public string actionTypeTooltip { get; }
public string expectedControlTypeTooltip { get; }
public SerializedProperty wrappedProperty { get; }
private static string ReadExpectedControlType(SerializedProperty serializedProperty)
{
var controlType = serializedProperty.FindPropertyRelative(nameof(InputAction.m_ExpectedControlType)).stringValue;
if (!string.IsNullOrEmpty(controlType))
return controlType;
var actionType = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Type)).intValue;
return actionType == (int)InputActionType.Button ? "Button" : null;
}
private static bool ReadInitialStateCheck(SerializedProperty serializedProperty)
{
var actionFlags = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Flags));
return (actionFlags.intValue & (int)InputAction.ActionFlags.WantsInitialStateCheck) != 0;
}
public bool Equals(SerializedInputAction other)
{
return name == other.name
&& expectedControlType == other.expectedControlType
&& type == other.type
&& interactions == other.interactions
&& processors == other.processors
&& initialStateCheck == other.initialStateCheck
&& actionTypeTooltip == other.actionTypeTooltip
&& expectedControlTypeTooltip == other.expectedControlTypeTooltip
&& propertyPath == other.propertyPath;
}
public override bool Equals(object obj)
{
return obj is SerializedInputAction other && Equals(other);
}
public override int GetHashCode()
{
var hashCode = new HashCode();
hashCode.Add(name);
hashCode.Add(expectedControlType);
hashCode.Add((int)type);
hashCode.Add(interactions);
hashCode.Add(processors);
hashCode.Add(initialStateCheck);
hashCode.Add(actionTypeTooltip);
hashCode.Add(expectedControlTypeTooltip);
hashCode.Add(propertyPath);
return hashCode.ToHashCode();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fcffff3de13f4304a98bb50b1222399a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
#if UNITY_EDITOR
using System;
using UnityEditor;
namespace UnityEngine.InputSystem.Editor
{
internal readonly struct SerializedInputActionMap
{
public SerializedInputActionMap(SerializedProperty serializedProperty)
{
wrappedProperty = serializedProperty ?? throw new ArgumentNullException(nameof(serializedProperty));
name = serializedProperty.FindPropertyRelative(nameof(InputActionMap.m_Name)).stringValue;
}
public string name { get; }
public SerializedProperty wrappedProperty { get; }
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d92ba71f7bef7074eb5d8753a9d09521
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More