test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 665321577aaff5344b5a12d626dfcaf7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60e5ec46fb7a7ff41856f37c60efb70f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99cfd7e6e4fd7294090b6bf84b177326
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 255ca660c2e3b424bb54d7be66737f57
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35e258ef8ccb13146952199468118233
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36827be967eb9244b973cbee1bbf53e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18d3e83390dcd6349b3086b9f70391b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a8e0b5c429811847b8c97a058e5884f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e68462a09b6ba104abce11d2d157d0b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b8e35f20292579409c899395e30948f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7894838fa258e3a4197077ddbda0eec5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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('project://database/Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_InputControl.png?fileID=2800000&guid=399cd90f4e31041e692a7d3a8b1aa4d0&type=3#d_InputControl'); 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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 449c8e5ca27af8e4a9db710c8be5e4df
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bd2d0548382d58489e8c2999daf4139
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acfae125fa5d7904987a696b3993d432
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 303ef5b13740f9a4db252c50122d2c62
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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&guid=7dac9c49a90bca4499371d0adc9b617b&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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fa44185ed614414ebab354dfe5a06b6
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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&guid=7dac9c49a90bca4499371d0adc9b617b&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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c662e0d3cc3c4f948808f9847f715ef2
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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;
|
||||
}
|
@@ -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
|
@@ -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&guid=7dac9c49a90bca4499371d0adc9b617b&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. 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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75a33987e21d5ac449deecea3dcd864f
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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&guid=7dac9c49a90bca4499371d0adc9b617b&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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 452df07a8ad0c944c879a484d5890e61
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -0,0 +1,4 @@
|
||||
:root {
|
||||
--input-editor-colors-properties-foldout: rgb(34, 34, 34);
|
||||
--input-editor-colors-properties-foldout-border: #808080;
|
||||
}
|
@@ -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
|
@@ -0,0 +1,4 @@
|
||||
:root {
|
||||
--input-editor-colors-properties-foldout: #DFDFDF;
|
||||
--input-editor-colors-properties-foldout-border: #808080;
|
||||
}
|
@@ -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
|
@@ -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&guid=7dac9c49a90bca4499371d0adc9b617b&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>
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cbd73d51dc491b4888055ae65cd9545
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6f2f33363708814e8530579e2d8cf2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcffff3de13f4304a98bb50b1222399a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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
Reference in New Issue
Block a user