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,249 @@
#if UNITY_EDITOR
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using UnityEditor;
////TODO: ensure that GUIDs in the asset are unique
namespace UnityEngine.InputSystem.Editor
{
/// <summary>
/// Keeps a reference to the asset being edited and maintains a copy of the asset object
/// around for editing.
/// </summary>
[Serializable]
internal class InputActionAssetManager : IDisposable
{
[SerializeField] private InputActionAsset m_AssetObjectForEditing;
[SerializeField] private InputActionAsset m_ImportedAssetObject;
[SerializeField] private string m_AssetGUID;
[SerializeField] private string m_ImportedAssetJson;
[SerializeField] private bool m_IsDirty;
private SerializedObject m_SerializedObject;
/// <summary>
/// Returns the Asset GUID uniquely identifying the associated imported asset.
/// </summary>
public string guid => m_AssetGUID;
/// <summary>
/// Returns the current Asset Path for the associated imported asset.
/// If the asset have been deleted this will be <c>null</c>.
/// </summary>
public string path
{
get
{
Debug.Assert(!string.IsNullOrEmpty(m_AssetGUID), "Asset GUID is empty");
return AssetDatabase.GUIDToAssetPath(m_AssetGUID);
}
}
/// <summary>
/// Returns the name of the associated imported asset.
/// </summary>
public string name
{
get
{
var asset = importedAsset;
if (asset != null)
return asset.name;
if (!string.IsNullOrEmpty(path))
return Path.GetFileNameWithoutExtension(path);
return string.Empty;
}
}
private InputActionAsset importedAsset
{
get
{
// Note that this may be null after deserialization from domain reload
if (m_ImportedAssetObject == null)
LoadImportedObjectFromGuid();
return m_ImportedAssetObject;
}
}
public InputActionAsset editedAsset => m_AssetObjectForEditing; // TODO Remove if redundant
public Action<bool> onDirtyChanged { get; set; }
public InputActionAssetManager(InputActionAsset inputActionAsset)
{
if (inputActionAsset == null)
throw new NullReferenceException(nameof(inputActionAsset));
m_AssetGUID = EditorHelpers.GetAssetGUID(inputActionAsset);
if (m_AssetGUID == null)
throw new Exception($"Failed to get asset {inputActionAsset.name} GUID");
m_ImportedAssetObject = inputActionAsset;
Initialize();
}
public SerializedObject serializedObject => m_SerializedObject;
public bool dirty => m_IsDirty;
public bool Initialize()
{
if (m_AssetObjectForEditing == null)
{
if (importedAsset == null)
{
// The asset we want to edit no longer exists.
return false;
}
CreateWorkingCopyAsset();
}
else
{
m_SerializedObject = new SerializedObject(m_AssetObjectForEditing);
}
return true;
}
public void Dispose()
{
if (m_SerializedObject == null)
return;
m_SerializedObject?.Dispose();
m_SerializedObject = null;
}
public bool ReInitializeIfAssetHasChanged()
{
var json = importedAsset.ToJson();
if (m_ImportedAssetJson == json)
return false;
CreateWorkingCopyAsset();
return true;
}
public static InputActionAsset CreateWorkingCopy(InputActionAsset source)
{
var copy = Object.Instantiate(source);
copy.hideFlags = HideFlags.HideAndDontSave;
copy.name = source.name;
return copy;
}
public static void CreateWorkingCopyAsset(ref InputActionAsset copy, InputActionAsset source)
{
if (copy != null)
Cleanup(ref copy);
copy = CreateWorkingCopy(source);
}
private void CreateWorkingCopyAsset() // TODO Can likely be removed if combined with Initialize
{
if (m_AssetObjectForEditing != null)
Cleanup();
// Duplicate the asset along 1:1. Unlike calling Clone(), this will also preserve GUIDs.
var asset = importedAsset;
m_AssetObjectForEditing = CreateWorkingCopy(asset);
m_ImportedAssetJson = asset.ToJson();
m_SerializedObject = new SerializedObject(m_AssetObjectForEditing);
}
public void Cleanup()
{
Cleanup(ref m_AssetObjectForEditing);
}
public static void Cleanup(ref InputActionAsset asset)
{
if (asset == null)
return;
Object.DestroyImmediate(asset);
asset = null;
}
private void LoadImportedObjectFromGuid()
{
// https://fogbugz.unity3d.com/f/cases/1313185/
// InputActionEditorWindow being an EditorWindow, it will be saved as part of the editor's
// window layout. When a project is opened that has no Library/ folder, the layout from the
// most recently opened project is used. Which means that when opening an .inputactions
// asset in project A, then closing it, and then opening project B, restoring the window layout
// also tries to restore the InputActionEditorWindow having that very same asset open -- which
// will lead nowhere except there happens to be an InputActionAsset with the very same GUID in
// the project.
var assetPath = path;
if (!string.IsNullOrEmpty(assetPath))
m_ImportedAssetObject = AssetDatabase.LoadAssetAtPath<InputActionAsset>(assetPath);
}
public void ApplyChanges()
{
m_SerializedObject.ApplyModifiedProperties();
m_SerializedObject.Update();
}
internal void SaveChangesToAsset()
{
// If this is invoked after a domain reload, importAsset will resolve itself.
// However, if the asset do not exist importedAsset will be null and we cannot complete the operation.
if (importedAsset == null)
throw new Exception("Unable to save changes. Associated asset does not exist.");
SaveAsset(path, m_AssetObjectForEditing.ToJson());
SetDirty(false);
}
/// <summary>
/// Saves an asset to the given <c>assetPath</c> with file content corresponding to <c>assetJson</c>
/// if the current content of the asset given by <c>assetPath</c> is different or the asset do not exist.
/// </summary>
/// <param name="assetPath">Destination asset path.</param>
/// <param name="assetJson">The JSON file content to be written to the asset.</param>
/// <returns><c>true</c> if the asset was successfully modified or created, else <c>false</c>.</returns>
internal static bool SaveAsset(string assetPath, string assetJson)
{
var existingJson = File.Exists(assetPath) ? File.ReadAllText(assetPath) : string.Empty;
// Return immediately if file content has not changed, i.e. touching the file would not yield a difference.
if (assetJson == existingJson)
return false;
// Attempt to write asset to disc (including checkout the file) and inform the user if this fails.
if (EditorHelpers.WriteAsset(assetPath, assetJson))
return true;
Debug.LogError($"Unable save asset to \"{assetPath}\" since the asset-path could not be checked-out as editable in the underlying version-control system.");
return false;
}
public void MarkDirty()
{
SetDirty(true);
}
public void UpdateAssetDirtyState()
{
m_SerializedObject.Update();
SetDirty(m_AssetObjectForEditing.ToJson() != importedAsset.ToJson()); // TODO Why not using cached version?
}
private void SetDirty(bool newValue)
{
m_IsDirty = newValue;
if (onDirtyChanged != null)
onDirtyChanged(newValue);
}
}
}
#endif // UNITY_EDITOR

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,130 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
namespace UnityEngine.InputSystem.Editor
{
/// <summary>
/// UI that edits the properties of an <see cref="InputAction"/>.
/// </summary>
/// <remarks>
/// Right-most pane in <see cref="InputActionEditorWindow"/> when an action is selected.
/// </remarks>
internal class InputActionPropertiesView : PropertiesViewBase
{
public static FourCC k_PropertiesChanged => new FourCC("PROP");
public InputActionPropertiesView(SerializedProperty actionProperty, Action<FourCC> onChange = null)
: base("Action", actionProperty, onChange, actionProperty.FindPropertyRelative("m_ExpectedControlType").stringValue)
{
m_ExpectedControlTypeProperty = actionProperty.FindPropertyRelative(nameof(InputAction.m_ExpectedControlType));
m_ActionTypeProperty = actionProperty.FindPropertyRelative(nameof(InputAction.m_Type));
m_ActionFlagsProperty = actionProperty.FindPropertyRelative(nameof(InputAction.m_Flags));
m_SelectedActionType = (InputActionType)m_ActionTypeProperty.intValue;
m_WantsInitialStateCheck = (m_ActionFlagsProperty.intValue & (int)InputAction.ActionFlags.WantsInitialStateCheck) != 0;
BuildControlTypeList();
m_SelectedControlType = Array.IndexOf(m_ControlTypeList, m_ExpectedControlTypeProperty.stringValue);
if (m_SelectedControlType == -1)
m_SelectedControlType = 0;
if (s_ControlTypeLabel == null)
s_ControlTypeLabel = EditorGUIUtility.TrTextContent("Control Type", m_ExpectedControlTypeProperty.GetTooltip());
if (s_ActionTypeLabel == null)
s_ActionTypeLabel = EditorGUIUtility.TrTextContent("Action Type", m_ActionTypeProperty.GetTooltip());
if (s_WantsInitialStateCheckLabel == null)
s_WantsInitialStateCheckLabel = EditorGUIUtility.TrTextContent("Initial State Check",
"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.");
}
protected override void DrawGeneralProperties()
{
EditorGUI.BeginChangeCheck();
m_SelectedActionType = EditorGUILayout.EnumPopup(s_ActionTypeLabel, m_SelectedActionType);
if ((InputActionType)m_SelectedActionType != InputActionType.Button)
m_SelectedControlType = EditorGUILayout.Popup(s_ControlTypeLabel, m_SelectedControlType, m_ControlTypeOptions);
if ((InputActionType)m_SelectedActionType != InputActionType.Value)
m_WantsInitialStateCheck = EditorGUILayout.Toggle(s_WantsInitialStateCheckLabel, m_WantsInitialStateCheck);
if (EditorGUI.EndChangeCheck())
{
if ((InputActionType)m_SelectedActionType == InputActionType.Button)
m_ExpectedControlTypeProperty.stringValue = "Button";
else if (m_SelectedControlType == 0)
m_ExpectedControlTypeProperty.stringValue = string.Empty;
else
m_ExpectedControlTypeProperty.stringValue = m_ControlTypeList[m_SelectedControlType];
m_ActionTypeProperty.intValue = (int)(InputActionType)m_SelectedActionType;
if (m_WantsInitialStateCheck)
m_ActionFlagsProperty.intValue |= (int)InputAction.ActionFlags.WantsInitialStateCheck;
else
m_ActionFlagsProperty.intValue &= ~(int)InputAction.ActionFlags.WantsInitialStateCheck;
m_ActionTypeProperty.serializedObject.ApplyModifiedProperties();
UpdateProcessors(m_ExpectedControlTypeProperty.stringValue);
onChange(k_PropertiesChanged);
}
}
private void BuildControlTypeList()
{
var types = new List<string>();
var allLayouts = InputSystem.s_Manager.m_Layouts;
foreach (var layoutName in allLayouts.layoutTypes.Keys)
{
if (EditorInputControlLayoutCache.TryGetLayout(layoutName).hideInUI)
continue;
// If the action type is InputActionType.Value, skip button controls.
var type = allLayouts.layoutTypes[layoutName];
if ((InputActionType)m_SelectedActionType == InputActionType.Value &&
typeof(ButtonControl).IsAssignableFrom(type))
continue;
////TODO: skip aliases
if (typeof(InputControl).IsAssignableFrom(type) &&
!typeof(InputDevice).IsAssignableFrom(type))
{
types.Add(layoutName);
}
}
// Sort alphabetically.
types.Sort((a, b) => string.Compare(a, b, StringComparison.OrdinalIgnoreCase));
// Make sure "Any" is always topmost entry.
types.Insert(0, "Any");
m_ControlTypeList = types.ToArray();
m_ControlTypeOptions = m_ControlTypeList.Select(x => new GUIContent(ObjectNames.NicifyVariableName(x)))
.ToArray();
}
private readonly SerializedProperty m_ExpectedControlTypeProperty;
private readonly SerializedProperty m_ActionTypeProperty;
private readonly SerializedProperty m_ActionFlagsProperty;
private string m_ExpectedControlLayout;
private string[] m_ControlTypeList;
private GUIContent[] m_ControlTypeOptions;
private int m_SelectedControlType;
private Enum m_SelectedActionType;
private bool m_WantsInitialStateCheck;
private static GUIContent s_ActionTypeLabel;
private static GUIContent s_ControlTypeLabel;
private static GUIContent s_WantsInitialStateCheckLabel;
}
}
#endif // UNITY_EDITOR

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,393 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine.InputSystem.Editor.Lists;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.Utilities;
////REVIEW: when we start with a blank tree view state, we should initialize the control picker to select the control currently
//// selected by the path property
namespace UnityEngine.InputSystem.Editor
{
/// <summary>
/// UI for editing properties of an <see cref="InputBinding"/>. Right-most pane in action editor when
/// binding is selected in middle pane.
/// </summary>
internal class InputBindingPropertiesView : PropertiesViewBase, IDisposable
{
public static FourCC k_GroupsChanged => new FourCC("GRPS");
public static FourCC k_PathChanged => new FourCC("PATH");
public static FourCC k_CompositeTypeChanged => new FourCC("COMP");
public static FourCC k_CompositePartAssignmentChanged => new FourCC("PART");
public InputBindingPropertiesView(
SerializedProperty bindingProperty,
Action<FourCC> onChange = null,
InputControlPickerState controlPickerState = null,
string expectedControlLayout = null,
ReadOnlyArray<InputControlScheme> controlSchemes = new ReadOnlyArray<InputControlScheme>(),
IEnumerable<string> controlPathsToMatch = null)
: base(InputActionSerializationHelpers.IsCompositeBinding(bindingProperty) ? "Composite" : "Binding",
bindingProperty, onChange, expectedControlLayout)
{
m_BindingProperty = bindingProperty;
m_GroupsProperty = bindingProperty.FindPropertyRelative("m_Groups");
m_PathProperty = bindingProperty.FindPropertyRelative("m_Path");
m_BindingGroups = m_GroupsProperty.stringValue
.Split(new[] {InputBinding.Separator}, StringSplitOptions.RemoveEmptyEntries).ToList();
m_ExpectedControlLayout = expectedControlLayout;
m_ControlSchemes = controlSchemes;
var flags = (InputBinding.Flags)bindingProperty.FindPropertyRelative("m_Flags").intValue;
m_IsPartOfComposite = (flags & InputBinding.Flags.PartOfComposite) != 0;
m_IsComposite = (flags & InputBinding.Flags.Composite) != 0;
// Set up control picker for m_Path. Not needed if the binding is a composite.
if (!m_IsComposite)
{
m_ControlPickerState = controlPickerState ?? new InputControlPickerState();
m_ControlPathEditor = new InputControlPathEditor(m_PathProperty, m_ControlPickerState, OnPathChanged);
m_ControlPathEditor.SetExpectedControlLayout(m_ExpectedControlLayout);
if (controlPathsToMatch != null)
m_ControlPathEditor.SetControlPathsToMatch(controlPathsToMatch);
}
}
public void Dispose()
{
m_ControlPathEditor?.Dispose();
}
protected override void DrawGeneralProperties()
{
var currentPath = m_PathProperty.stringValue;
InputSystem.OnDrawCustomWarningForBindingPath(currentPath);
if (m_IsComposite)
{
if (m_CompositeParameters == null)
InitializeCompositeProperties();
// Composite type dropdown.
var selectedCompositeType = EditorGUILayout.Popup(s_CompositeTypeLabel, m_SelectedCompositeType, m_CompositeTypeOptions);
if (selectedCompositeType != m_SelectedCompositeType)
{
m_SelectedCompositeType = selectedCompositeType;
OnCompositeTypeChanged();
}
// Composite parameters.
m_CompositeParameters.OnGUI();
}
else
{
// Path.
m_ControlPathEditor.OnGUI();
// Composite part.
if (m_IsPartOfComposite)
{
if (m_CompositeParts == null)
InitializeCompositePartProperties();
var selectedPart = EditorGUILayout.Popup(s_CompositePartAssignmentLabel, m_SelectedCompositePart,
m_CompositePartOptions);
if (selectedPart != m_SelectedCompositePart)
{
m_SelectedCompositePart = selectedPart;
OnCompositePartAssignmentChanged();
}
}
// Show the specific controls which match the current path
DrawMatchingControlPaths();
// Control scheme matrix.
DrawUseInControlSchemes();
}
}
/// <summary>
/// Used to keep track of which foldouts are expanded.
/// </summary>
private static bool showMatchingLayouts = false;
private static Dictionary<string, bool> showMatchingChildLayouts = new Dictionary<string, bool>();
private static void DrawMatchingControlPaths(List<MatchingControlPath> matchingControlPaths)
{
foreach (var matchingControlPath in matchingControlPaths)
{
bool showLayout = false;
EditorGUI.indentLevel++;
var text = $"{matchingControlPath.deviceName} > {matchingControlPath.controlName}";
if (matchingControlPath.children.Count() > 0 && !matchingControlPath.isRoot)
{
showMatchingChildLayouts.TryGetValue(matchingControlPath.deviceName, out showLayout);
showMatchingChildLayouts[matchingControlPath.deviceName] = EditorGUILayout.Foldout(showLayout, text);
}
else
{
EditorGUILayout.LabelField(text);
}
showLayout |= matchingControlPath.isRoot;
if (showLayout)
DrawMatchingControlPaths(matchingControlPath.children);
EditorGUI.indentLevel--;
}
}
/// <summary>
/// Finds all registered control paths implemented by concrete classes which match the current binding path and renders it.
/// </summary>
private void DrawMatchingControlPaths()
{
bool controlPathUsagePresent = false;
List<MatchingControlPath> matchingControlPaths = MatchingControlPath.CollectMatchingControlPaths(m_ControlPathEditor.pathProperty.stringValue, showMatchingLayouts, ref controlPathUsagePresent);
if (matchingControlPaths == null || matchingControlPaths.Count != 0)
{
EditorGUILayout.BeginVertical();
showMatchingLayouts = EditorGUILayout.Foldout(showMatchingLayouts, "Derived Bindings");
if (showMatchingLayouts)
{
if (matchingControlPaths == null)
{
if (controlPathUsagePresent)
EditorGUILayout.HelpBox("No registered controls match this current binding. Some controls are only registered at runtime.", MessageType.Warning);
else
EditorGUILayout.HelpBox("No other registered controls match this current binding. Some controls are only registered at runtime.", MessageType.Warning);
}
else
{
DrawMatchingControlPaths(matchingControlPaths);
}
}
EditorGUILayout.EndVertical();
}
}
/// <summary>
/// Draw control scheme matrix that allows selecting which control schemes a particular
/// binding appears in.
/// </summary>
private void DrawUseInControlSchemes()
{
if (m_ControlSchemes.Count <= 0)
return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField(s_UseInControlSchemesLAbel, EditorStyles.boldLabel);
EditorGUILayout.BeginVertical();
foreach (var scheme in m_ControlSchemes)
{
EditorGUI.BeginChangeCheck();
var result = EditorGUILayout.Toggle(scheme.name, m_BindingGroups.Contains(scheme.bindingGroup));
if (EditorGUI.EndChangeCheck())
{
if (result)
{
m_BindingGroups.Add(scheme.bindingGroup);
}
else
{
m_BindingGroups.Remove(scheme.bindingGroup);
}
OnBindingGroupsChanged();
}
}
EditorGUILayout.EndVertical();
}
private void InitializeCompositeProperties()
{
// Find name of current composite.
var path = m_PathProperty.stringValue;
var compositeNameAndParameters = NameAndParameters.Parse(path);
var compositeName = compositeNameAndParameters.name;
var compositeType = InputBindingComposite.s_Composites.LookupTypeRegistration(compositeName);
// Collect all possible composite types.
var selectedCompositeIndex = -1;
var compositeTypeOptionsList = new List<GUIContent>();
var compositeTypeList = new List<string>();
var currentIndex = 0;
foreach (var composite in InputBindingComposite.s_Composites.internedNames.Where(x =>
!InputBindingComposite.s_Composites.aliases.Contains(x)).OrderBy(x => x))
{
if (!string.IsNullOrEmpty(m_ExpectedControlLayout))
{
var valueType = InputBindingComposite.GetValueType(composite);
if (valueType != null &&
!InputControlLayout.s_Layouts.ValueTypeIsAssignableFrom(
new InternedString(m_ExpectedControlLayout), valueType))
continue;
}
if (InputBindingComposite.s_Composites.LookupTypeRegistration(composite) == compositeType)
selectedCompositeIndex = currentIndex;
var name = ObjectNames.NicifyVariableName(composite);
compositeTypeOptionsList.Add(new GUIContent(name));
compositeTypeList.Add(composite);
++currentIndex;
}
// If the current composite type isn't a registered type, add it to the list as
// an extra option.
if (selectedCompositeIndex == -1)
{
selectedCompositeIndex = compositeTypeList.Count;
compositeTypeOptionsList.Add(new GUIContent(ObjectNames.NicifyVariableName(compositeName)));
compositeTypeList.Add(compositeName);
}
m_CompositeTypes = compositeTypeList.ToArray();
m_CompositeTypeOptions = compositeTypeOptionsList.ToArray();
m_SelectedCompositeType = selectedCompositeIndex;
// Initialize parameters.
m_CompositeParameters = new ParameterListView
{
onChange = OnCompositeParametersModified
};
if (compositeType != null)
m_CompositeParameters.Initialize(compositeType, compositeNameAndParameters.parameters);
}
private void InitializeCompositePartProperties()
{
var currentCompositePart = m_BindingProperty.FindPropertyRelative("m_Name").stringValue;
////REVIEW: this makes a lot of assumptions about the serialized data based on the one property we've been given in the ctor
// Determine the name of the current composite type that the part belongs to.
var bindingArrayProperty = m_BindingProperty.GetArrayPropertyFromElement();
var partBindingIndex = InputActionSerializationHelpers.GetIndex(bindingArrayProperty, m_BindingProperty);
var compositeBindingIndex =
InputActionSerializationHelpers.GetCompositeStartIndex(bindingArrayProperty, partBindingIndex);
if (compositeBindingIndex == -1)
return;
var compositeBindingProperty = bindingArrayProperty.GetArrayElementAtIndex(compositeBindingIndex);
var compositePath = compositeBindingProperty.FindPropertyRelative("m_Path").stringValue;
var compositeNameAndParameters = NameAndParameters.Parse(compositePath);
// Initialize option list from all parts available for the composite.
var optionList = new List<GUIContent>();
var nameList = new List<string>();
var currentIndex = 0;
var selectedPartNameIndex = -1;
foreach (var partName in InputBindingComposite.GetPartNames(compositeNameAndParameters.name))
{
if (partName.Equals(currentCompositePart, StringComparison.InvariantCultureIgnoreCase))
selectedPartNameIndex = currentIndex;
var niceName = ObjectNames.NicifyVariableName(partName);
optionList.Add(new GUIContent(niceName));
nameList.Add(partName);
++currentIndex;
}
// If currently selected part is not in list, add it as an option.
if (selectedPartNameIndex == -1)
{
selectedPartNameIndex = nameList.Count;
optionList.Add(new GUIContent(ObjectNames.NicifyVariableName(currentCompositePart)));
nameList.Add(currentCompositePart);
}
m_CompositeParts = nameList.ToArray();
m_CompositePartOptions = optionList.ToArray();
m_SelectedCompositePart = selectedPartNameIndex;
}
private void OnCompositeParametersModified()
{
Debug.Assert(m_CompositeParameters != null);
var path = m_PathProperty.stringValue;
var nameAndParameters = NameAndParameters.Parse(path);
nameAndParameters.parameters = m_CompositeParameters.GetParameters();
m_PathProperty.stringValue = nameAndParameters.ToString();
m_PathProperty.serializedObject.ApplyModifiedProperties();
OnPathChanged();
}
private void OnBindingGroupsChanged()
{
m_GroupsProperty.stringValue = string.Join(InputBinding.kSeparatorString, m_BindingGroups.ToArray());
m_GroupsProperty.serializedObject.ApplyModifiedProperties();
onChange?.Invoke(k_GroupsChanged);
}
private void OnPathChanged()
{
m_BindingProperty.serializedObject.ApplyModifiedProperties();
onChange?.Invoke(k_PathChanged);
}
private void OnCompositeTypeChanged()
{
var nameAndParameters = new NameAndParameters
{
name = m_CompositeTypes[m_SelectedCompositeType],
parameters = m_CompositeParameters.GetParameters()
};
InputActionSerializationHelpers.ChangeCompositeBindingType(m_BindingProperty, nameAndParameters);
m_PathProperty.serializedObject.ApplyModifiedProperties();
onChange?.Invoke(k_CompositeTypeChanged);
}
private void OnCompositePartAssignmentChanged()
{
m_BindingProperty.FindPropertyRelative("m_Name").stringValue = m_CompositeParts[m_SelectedCompositePart];
m_BindingProperty.serializedObject.ApplyModifiedProperties();
onChange?.Invoke(k_CompositePartAssignmentChanged);
}
private readonly bool m_IsComposite;
private ParameterListView m_CompositeParameters;
private int m_SelectedCompositeType;
private GUIContent[] m_CompositeTypeOptions;
private string[] m_CompositeTypes;
private int m_SelectedCompositePart;
private GUIContent[] m_CompositePartOptions;
private string[] m_CompositeParts;
private readonly SerializedProperty m_GroupsProperty;
private readonly SerializedProperty m_BindingProperty;
private readonly SerializedProperty m_PathProperty;
private readonly InputControlPickerState m_ControlPickerState;
private readonly InputControlPathEditor m_ControlPathEditor;
private static readonly GUIContent s_CompositeTypeLabel = EditorGUIUtility.TrTextContent("Composite Type",
"Type of composite. Allows changing the composite type retroactively. Doing so will modify the bindings that are part of the composite.");
private static readonly GUIContent s_UseInControlSchemesLAbel = EditorGUIUtility.TrTextContent("Use in control scheme",
"In which control schemes the binding is active. A binding can be used by arbitrary many control schemes. If a binding is not "
+ "assigned to a specific control schemes, it is active in all of them.");
private static readonly GUIContent s_CompositePartAssignmentLabel = EditorGUIUtility.TrTextContent(
"Composite Part",
"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.");
private ReadOnlyArray<InputControlScheme> m_ControlSchemes;
private readonly List<string> m_BindingGroups;
private readonly string m_ExpectedControlLayout;
}
}
#endif // UNITY_EDITOR

View File

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

View File

@@ -0,0 +1,229 @@
#if UNITY_EDITOR
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine.InputSystem.Utilities;
namespace UnityEngine.InputSystem.Editor.Lists
{
/// <summary>
/// A <see cref="ReorderableList"/> to manage a set of name-and-parameter pairs and a <see cref="ParameterListView"/>
/// to edit the parameters of the currently selected pair.
/// </summary>
/// <remarks>
/// Produces output that can be consumed by <see cref="NameAndParameters.ParseMultiple"/>.
/// </remarks>
internal abstract class NameAndParameterListView
{
protected NameAndParameterListView(SerializedProperty property, Action applyAction, string expectedControlLayout, TypeTable listOptions, Func<Type, Type> getValueType, string itemName)
{
m_ItemName = itemName;
m_GetValueType = getValueType;
m_DeleteButton = EditorGUIUtility.TrIconContent("Toolbar Minus", $"Delete {itemName}");
m_UpButton = EditorGUIUtility.TrIconContent(GUIHelpers.LoadIcon("ChevronUp"), $"Move {itemName} up");
m_DownButton = EditorGUIUtility.TrIconContent(GUIHelpers.LoadIcon("ChevronDown"), $"Move {itemName} down");
m_Property = property;
m_Apply = applyAction;
m_ListOptions = listOptions;
m_ExpectedControlLayout = expectedControlLayout;
if (!string.IsNullOrEmpty(m_ExpectedControlLayout))
m_ExpectedValueType = EditorInputControlLayoutCache.GetValueType(m_ExpectedControlLayout);
m_ParametersForEachListItem = NameAndParameters.ParseMultiple(m_Property.stringValue).ToArray();
m_EditableParametersForEachListItem = new ParameterListView[m_ParametersForEachListItem.Length];
for (var i = 0; i < m_ParametersForEachListItem.Length; i++)
{
m_EditableParametersForEachListItem[i] = new ParameterListView { onChange = OnParametersChanged };
var typeName = m_ParametersForEachListItem[i].name;
var rowType = m_ListOptions.LookupTypeRegistration(typeName);
m_EditableParametersForEachListItem[i].Initialize(rowType, m_ParametersForEachListItem[i].parameters);
var name = ObjectNames.NicifyVariableName(typeName);
////REVIEW: finding this kind of stuff should probably have better support globally on the asset; e.g. some
//// notification that pops up and allows fixing all occurrences in one click
// Find out if we still support this option and indicate it in the list, if we don't.
if (rowType == null)
name += " (Obsolete)";
else if (m_ExpectedValueType != null)
{
var valueType = getValueType(rowType);
if (valueType != null && !m_ExpectedValueType.IsAssignableFrom(valueType))
name += " (Incompatible Value Type)";
}
m_EditableParametersForEachListItem[i].name = name;
}
}
public void OnAddDropdown(Rect r)
{
// Add only original names to the menu and not aliases.
var menu = new GenericMenu();
foreach (var name in m_ListOptions.internedNames.Where(x => !m_ListOptions.ShouldHideInUI(x)).OrderBy(x => x.ToString()))
{
// Skip if not compatible with value type.
if (m_ExpectedValueType != null)
{
var type = m_ListOptions.LookupTypeRegistration(name);
var valueType = m_GetValueType(type);
if (valueType != null && !m_ExpectedValueType.IsAssignableFrom(valueType))
continue;
}
var niceName = ObjectNames.NicifyVariableName(name);
menu.AddItem(new GUIContent(niceName), false, OnAddElement, name.ToString());
}
menu.ShowAsContext();
}
private void OnAddElement(object data)
{
var name = (string)data;
ArrayHelpers.Append(ref m_ParametersForEachListItem,
new NameAndParameters {name = name});
ArrayHelpers.Append(ref m_EditableParametersForEachListItem,
new ParameterListView { onChange = OnParametersChanged });
var index = m_EditableParametersForEachListItem.Length - 1;
var typeName = m_ParametersForEachListItem[index].name;
var rowType = m_ListOptions.LookupTypeRegistration(typeName);
m_EditableParametersForEachListItem[index].Initialize(rowType, m_ParametersForEachListItem[index].parameters);
m_EditableParametersForEachListItem[index].name = ObjectNames.NicifyVariableName(name);
m_Apply();
}
private void OnParametersChanged()
{
for (var i = 0; i < m_ParametersForEachListItem.Length; i++)
{
m_ParametersForEachListItem[i] = new NameAndParameters
{
name = m_ParametersForEachListItem[i].name,
parameters = m_EditableParametersForEachListItem[i].GetParameters(),
};
}
m_Apply();
}
private static class Styles
{
public static readonly GUIStyle s_FoldoutStyle = new GUIStyle("foldout").WithFontStyle(FontStyle.Bold);
public static readonly GUIStyle s_UpDownButtonStyle = new GUIStyle("label").WithFixedWidth(12).WithFixedHeight(12).WithPadding(new RectOffset());
}
private void SwapEntry(int oldIndex, int newIndex)
{
MemoryHelpers.Swap(ref m_ParametersForEachListItem[oldIndex], ref m_ParametersForEachListItem[newIndex]);
MemoryHelpers.Swap(ref m_EditableParametersForEachListItem[oldIndex], ref m_EditableParametersForEachListItem[newIndex]);
m_Apply();
}
public void OnGUI()
{
if (m_EditableParametersForEachListItem == null || m_EditableParametersForEachListItem.Length == 0)
{
using (new EditorGUI.DisabledScope(true))
{
EditorGUI.indentLevel++;
EditorGUILayout.LabelField($"No {m_ItemName}s have been added.");
EditorGUI.indentLevel--;
}
}
else
for (var i = 0; i < m_EditableParametersForEachListItem.Length; i++)
{
var editableParams = m_EditableParametersForEachListItem[i];
EditorGUILayout.BeginHorizontal();
if (editableParams.hasUIToShow)
editableParams.visible = EditorGUILayout.Foldout(editableParams.visible, editableParams.name, true, Styles.s_FoldoutStyle);
else
{
GUILayout.Space(16);
EditorGUILayout.LabelField(editableParams.name, EditorStyles.boldLabel);
}
GUILayout.FlexibleSpace();
using (new EditorGUI.DisabledScope(i == 0))
{
if (GUILayout.Button(m_UpButton, Styles.s_UpDownButtonStyle))
SwapEntry(i, i - 1);
}
using (new EditorGUI.DisabledScope(i == m_EditableParametersForEachListItem.Length - 1))
{
if (GUILayout.Button(m_DownButton, Styles.s_UpDownButtonStyle))
SwapEntry(i, i + 1);
}
if (GUILayout.Button(m_DeleteButton, EditorStyles.label))
{
// Unfocus controls, because otherwise, the editor can get confused and have text from a text field
// on the deleted item leak to a different field.
GUI.FocusControl(null);
ArrayHelpers.EraseAt(ref m_ParametersForEachListItem, i);
ArrayHelpers.EraseAt(ref m_EditableParametersForEachListItem, i);
m_Apply();
GUIUtility.ExitGUI();
}
EditorGUILayout.EndHorizontal();
if (editableParams.visible)
{
EditorGUI.indentLevel++;
editableParams.OnGUI();
EditorGUI.indentLevel--;
}
GUIHelpers.DrawLineSeparator();
}
}
public string ToSerializableString()
{
if (m_ParametersForEachListItem == null)
return string.Empty;
return string.Join(NamedValue.Separator,
m_ParametersForEachListItem.Select(x => x.ToString()).ToArray());
}
private Func<Type, Type> m_GetValueType;
private SerializedProperty m_Property;
private readonly TypeTable m_ListOptions;
private readonly string m_ExpectedControlLayout;
private readonly Type m_ExpectedValueType;
private readonly GUIContent m_DeleteButton;
private readonly GUIContent m_UpButton;
private readonly GUIContent m_DownButton;
private NameAndParameters[] m_ParametersForEachListItem;
private ParameterListView[] m_EditableParametersForEachListItem;
private readonly Action m_Apply;
private string m_ItemName;
}
/// <summary>
/// A list of processors and their parameters.
/// </summary>
internal class ProcessorsListView : NameAndParameterListView
{
public ProcessorsListView(SerializedProperty property, Action applyAction, string expectedControlLayout)
: base(property, applyAction, expectedControlLayout, InputProcessor.s_Processors, InputProcessor.GetValueTypeFromType, "Processor")
{
}
}
/// <summary>
/// A list view of interactions and their parameters.
/// </summary>
internal class InteractionsListView : NameAndParameterListView
{
public InteractionsListView(SerializedProperty property, Action applyAction, string expectedControlLayout)
: base(property, applyAction, expectedControlLayout, InputInteraction.s_Interactions, InputInteraction.GetValueType, "Interaction")
{
}
}
}
#endif // UNITY_EDITOR

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 33f32142c2c2d4662be5f5274db27158
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: ffeba93637e654de6a5906b48520dc94
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: ce5f11cd993284c4f9c54f854bdc8c9c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 1
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 9cfdf4253b3de4d389dff51ab21111ad
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: cf632ed80bf1f46c980de6b1b8b903ef
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: 5ab69704aa4984b49bc426da72fabbed
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 1
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: aa4c2360f910d46f497f75b4b6677358
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 1
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: d7b144323984d4298924c65ed071dea1
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: c4b66e31395c54087a2fbc13ae7e0f3c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 943deaaee9c9347e0a455aa208526c42
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: c0996bc290ff74bf4834f4a8b7dc8c3e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
fileFormatVersion: 2
guid: b02e3f0c0798a4f1789a89a7697660be
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 47cf506b4219343519083fe1c0b8fc9c
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,454 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UIElements;
////TODO: show description of interaction or processor when selected
namespace UnityEngine.InputSystem.Editor.Lists
{
/// <summary>
/// Inspector-like functionality for editing parameter lists as used in <see cref="InputControlLayout"/>.
/// </summary>
/// <remarks>
/// This can be used for parameters on interactions, processors, and composites.
///
/// Call <see cref="Initialize"/> to set up (can be done repeatedly on the same instance). Call
/// <see cref="OnGUI"/> to render.
///
/// Custom parameter GUIs can be defined by deriving from <see cref="InputParameterEditor{TObject}"/>.
/// This class will automatically incorporate custom GUIs and fall back to default GUIs where no custom
/// ones are defined.
/// </remarks>
internal class ParameterListView
{
/// <summary>
/// Invoked whenever a parameter is changed.
/// </summary>
public Action onChange { get; set; }
public bool hasUIToShow => (m_Parameters != null && m_Parameters.Length > 0) || m_ParameterEditor != null;
public bool visible { get; set; }
public string name { get; set; }
/// <summary>
/// Get the current parameter values according to the editor state.
/// </summary>
/// <returns>An array of parameter values.</returns>
public NamedValue[] GetParameters()
{
if (m_Parameters == null)
return null;
// See if we have parameters that aren't at their default value.
var countOfParametersNotAtDefaultValue = 0;
for (var i = 0; i < m_Parameters.Length; ++i)
{
if (!m_Parameters[i].isAtDefault)
++countOfParametersNotAtDefaultValue;
}
// If not, we return null.
if (countOfParametersNotAtDefaultValue == 0)
return null;
// Collect non-default parameter values.
var result = new NamedValue[countOfParametersNotAtDefaultValue];
var index = 0;
for (var i = 0; i < m_Parameters.Length; ++i)
{
var parameter = m_Parameters[i];
if (parameter.isAtDefault)
continue;
result[index++] = parameter.value;
}
return result;
}
/// <summary>
/// Initialize the parameter list view based on the given registered type that has parameters to edit. This can be
/// things such as interactions, processors, or composites.
/// </summary>
/// <param name="registeredType">Type of object that the parameters will be passed to at runtime.
/// We need this to be able to determine the possible set of parameters and their possible values. This
/// can be a class implementing <see cref="IInputInteraction"/>, for example.</param>
/// <param name="existingParameters">List of existing parameters. Can be empty.</param>
public void Initialize(Type registeredType, ReadOnlyArray<NamedValue> existingParameters)
{
if (registeredType == null)
{
// No registered type. This usually happens when data references a registration that has
// been removed in the meantime (e.g. an interaction that is no longer supported). We want
// to accept this case and simply pretend that the given type has no parameters.
Clear();
return;
}
visible = true;
// Try to instantiate object so that we can determine defaults.
object instance = null;
try
{
instance = Activator.CreateInstance(registeredType);
}
catch (Exception)
{
// Swallow. If we can't create an instance, we simply assume no defaults.
}
var parameters = new List<EditableParameterValue>();
////REVIEW: support properties here?
// Go through public instance fields and add every parameter found on the registered
// type.
var fields = registeredType.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (var field in fields)
{
// Skip all fields that have an [InputControl] attribute. This is relevant
// only for composites, but we just always do it here.
if (field.GetCustomAttribute<InputControlAttribute>(false) != null)
continue;
// Determine parameter name from field.
var parameter = new EditableParameterValue {field = field};
var name = field.Name;
parameter.value.name = name;
// Determine parameter type from field.
var fieldType = field.FieldType;
if (fieldType.IsEnum)
{
// For enums, we want the underlying integer type.
var underlyingType = fieldType.GetEnumUnderlyingType();
var underlyingTypeCode = Type.GetTypeCode(underlyingType);
parameter.value = parameter.value.ConvertTo(underlyingTypeCode);
// Read enum names and values.
parameter.enumNames = Enum.GetNames(fieldType).Select(x => new GUIContent(x)).ToArray();
////REVIEW: this probably falls apart if multiple members have the same value
var list = new List<int>();
foreach (var value in Enum.GetValues(fieldType))
list.Add((int)value);
parameter.enumValues = list.ToArray();
}
else
{
var typeCode = Type.GetTypeCode(fieldType);
parameter.value = parameter.value.ConvertTo(typeCode);
}
// Determine default value.
if (instance != null)
{
try
{
var value = field.GetValue(instance);
parameter.defaultValue = new NamedValue
{
name = name,
value = PrimitiveValue.FromObject(value)
};
}
catch
{
// If the getter throws, ignore. All we lose is the actual default value from
// the field.
}
}
// If the parameter already exists in the given list, maintain its value.
var existingParameterIndex = existingParameters.IndexOf(x => x.name == field.Name);
if (existingParameterIndex >= 0)
{
// Make sure we're preserving the right type.
parameter.value = existingParameters[existingParameterIndex].ConvertTo(parameter.value.type);
}
else
{
// Not assigned. Set to default.
if (parameter.defaultValue != null)
parameter.value = parameter.defaultValue.Value;
}
// Add.
parameters.Add(parameter);
}
m_Parameters = parameters.ToArray();
// See if we have a dedicated parameter editor.
var parameterEditorType = InputParameterEditor.LookupEditorForType(registeredType);
if (parameterEditorType != null)
{
// Create an editor instance and hand it the instance we created. Unlike our default
// editing logic, on this path we will be operating on an object instance that contains
// the parameter values. So on this path, we actually need to update the object to reflect
// the current parameter values.
NamedValue.ApplyAllToObject(instance, m_Parameters.Select(x => x.value));
m_ParameterEditor = (InputParameterEditor)Activator.CreateInstance(parameterEditorType);
// We have to jump through some hoops here to create instances of any CustomOrDefaultSetting fields on the
// parameter editor. This is because those types changed from structs to classes when UIToolkit was
// introduced, and we don't want to force users to have to create those instances manually on any of their
// own editors.
var genericArgumentType = TypeHelpers.GetGenericTypeArgumentFromHierarchy(parameterEditorType,
typeof(InputParameterEditor<>), 0);
if (genericArgumentType != null)
{
var fieldInfos = parameterEditorType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var customOrDefaultGenericType = typeof(InputParameterEditor<>.CustomOrDefaultSetting);
var customOrDefaultType = customOrDefaultGenericType.MakeGenericType(genericArgumentType);
foreach (var customOrDefaultEditorField in fieldInfos.Where(f => f.FieldType == customOrDefaultType))
{
customOrDefaultEditorField.SetValue(m_ParameterEditor, Activator.CreateInstance(customOrDefaultEditorField.FieldType));
}
}
m_ParameterEditor.SetTarget(instance);
}
else
{
m_ParameterEditor = null;
// Create parameter labels.
m_ParameterLabels = new GUIContent[m_Parameters.Length];
for (var i = 0; i < m_Parameters.Length; ++i)
{
// Look up tooltip from field.
var tooltip = string.Empty;
var field = m_Parameters[i].field;
var tooltipAttribute = field.GetCustomAttribute<TooltipAttribute>();
if (tooltipAttribute != null)
tooltip = tooltipAttribute.tooltip;
// Create label.
var niceName = ObjectNames.NicifyVariableName(m_Parameters[i].value.name);
m_ParameterLabels[i] = new GUIContent(niceName, tooltip);
}
}
}
public void Clear()
{
m_Parameters = null;
m_ParameterEditor = null;
}
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
public void OnDrawVisualElements(VisualElement root)
{
if (m_ParameterEditor != null)
{
m_ParameterEditor.OnDrawVisualElements(root, OnValuesChanged);
return;
}
if (m_Parameters == null)
return;
void OnValueChanged(ref EditableParameterValue parameter, object result, int i)
{
parameter.value.value = PrimitiveValue.FromObject(result).ConvertTo(parameter.value.type);
m_Parameters[i] = parameter;
}
void OnEditEnd()
{
onChange?.Invoke();
}
for (var i = 0; i < m_Parameters.Length; i++)
{
var parameter = m_Parameters[i];
var label = m_ParameterLabels[i];
var closedIndex = i;
if (parameter.isEnum)
{
var intValue = parameter.value.value.ToInt32();
var field = new DropdownField(label.text, parameter.enumNames.Select(x => x.text).ToList(), intValue);
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, field.index, closedIndex));
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
root.Add(field);
}
else if (parameter.value.type == TypeCode.Int64 || parameter.value.type == TypeCode.UInt64)
{
var longValue = parameter.value.value.ToInt64();
var field = new LongField(label.text) { value = longValue };
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
root.Add(field);
}
else if (parameter.value.type.IsInt())
{
var intValue = parameter.value.value.ToInt32();
var field = new IntegerField(label.text) { value = intValue };
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
root.Add(field);
}
else if (parameter.value.type == TypeCode.Single)
{
var floatValue = parameter.value.value.ToSingle();
var field = new FloatField(label.text) { value = floatValue };
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
root.Add(field);
}
else if (parameter.value.type == TypeCode.Double)
{
var floatValue = parameter.value.value.ToDouble();
var field = new DoubleField(label.text) { value = floatValue };
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
field.RegisterCallback<BlurEvent>(_ => OnEditEnd());
root.Add(field);
}
else if (parameter.value.type == TypeCode.Boolean)
{
var boolValue = parameter.value.value.ToBoolean();
var field = new Toggle(label.text) { value = boolValue };
field.RegisterValueChangedCallback(evt => OnValueChanged(ref parameter, evt.newValue, closedIndex));
field.RegisterValueChangedCallback(_ => OnEditEnd());
root.Add(field);
}
}
}
#endif
private void OnValuesChanged()
{
ReadParameterValuesFrom(m_ParameterEditor.target);
onChange?.Invoke();
}
public void OnGUI()
{
// If we have a dedicated parameter editor, let it do all the work.
if (m_ParameterEditor != null)
{
EditorGUI.BeginChangeCheck();
m_ParameterEditor.OnGUI();
if (EditorGUI.EndChangeCheck())
{
ReadParameterValuesFrom(m_ParameterEditor.target);
onChange?.Invoke();
}
return;
}
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
// handled by OnDrawVisualElements with UI Toolkit
if (!InputSystem.settings.IsFeatureEnabled(InputFeatureNames.kUseIMGUIEditorForAssets)) return;
#endif
// Otherwise, fall back to our default logic.
if (m_Parameters == null)
return;
for (var i = 0; i < m_Parameters.Length; i++)
{
var parameter = m_Parameters[i];
var label = m_ParameterLabels[i];
EditorGUI.BeginChangeCheck();
object result = null;
if (parameter.isEnum)
{
var intValue = parameter.value.value.ToInt32();
result = EditorGUILayout.IntPopup(label, intValue, parameter.enumNames, parameter.enumValues);
}
else if (parameter.value.type == TypeCode.Int64 || parameter.value.type == TypeCode.UInt64)
{
var longValue = parameter.value.value.ToInt64();
result = EditorGUILayout.LongField(label, longValue);
}
else if (parameter.value.type.IsInt())
{
var intValue = parameter.value.value.ToInt32();
result = EditorGUILayout.IntField(label, intValue);
}
else if (parameter.value.type == TypeCode.Single)
{
var floatValue = parameter.value.value.ToSingle();
result = EditorGUILayout.FloatField(label, floatValue);
}
else if (parameter.value.type == TypeCode.Double)
{
var floatValue = parameter.value.value.ToDouble();
result = EditorGUILayout.DoubleField(label, floatValue);
}
else if (parameter.value.type == TypeCode.Boolean)
{
var boolValue = parameter.value.value.ToBoolean();
result = EditorGUILayout.Toggle(label, boolValue);
}
if (EditorGUI.EndChangeCheck())
{
parameter.value.value = PrimitiveValue.FromObject(result).ConvertTo(parameter.value.type);
m_Parameters[i] = parameter;
onChange?.Invoke();
}
}
}
////REVIEW: check whether parameters have *actually* changed?
/// <summary>
/// Refresh <see cref="m_Parameters"/> from the current parameter values in <paramref name="target"/>.
/// </summary>
/// <param name="target">An instance of the current type we are editing parameters on.</param>
private void ReadParameterValuesFrom(object target)
{
if (m_Parameters == null)
return;
for (var i = 0; i < m_Parameters.Length; ++i)
{
var parameter = m_Parameters[i];
object value = null;
try
{
value = parameter.field.GetValue(target);
}
catch
{
// Ignore exceptions from getters.
}
m_Parameters[i].value.value = PrimitiveValue.FromObject(value).ConvertTo(parameter.value.type);
}
}
private InputParameterEditor m_ParameterEditor;
private EditableParameterValue[] m_Parameters;
private GUIContent[] m_ParameterLabels;
private struct EditableParameterValue
{
public NamedValue value;
public NamedValue? defaultValue;
public int[] enumValues;
public GUIContent[] enumNames;
public FieldInfo field;
public bool isEnum => enumValues != null;
public bool isAtDefault => defaultValue != null && value == defaultValue.Value;
}
}
}
#endif // UNITY_EDITOR

View File

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

View File

@@ -0,0 +1,146 @@
#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEngine.InputSystem.Editor.Lists;
using UnityEngine.InputSystem.Utilities;
////TODO: show parameters for selected interaction or processor inline in list rather than separately underneath list
namespace UnityEngine.InputSystem.Editor
{
/// <summary>
/// Base class for views that show the properties of actions or bindings.
/// </summary>
internal abstract class PropertiesViewBase
{
protected PropertiesViewBase(string label, SerializedProperty bindingOrAction, Action<FourCC> onChange, string expectedControlLayout = null)
{
if (bindingOrAction == null)
throw new ArgumentNullException(nameof(bindingOrAction));
m_InteractionsProperty = bindingOrAction.FindPropertyRelative("m_Interactions");
m_ProcessorsProperty = bindingOrAction.FindPropertyRelative("m_Processors");
m_InteractionsList = new InteractionsListView(m_InteractionsProperty, OnInteractionsModified, expectedControlLayout);
UpdateProcessors(expectedControlLayout);
m_OnChange = onChange;
m_GeneralFoldoutLabel = EditorGUIUtility.TrTextContent(label);
}
protected void UpdateProcessors(string expectedControlLayout)
{
m_ProcessorsList = new ProcessorsListView(m_ProcessorsProperty, OnProcessorsModified, expectedControlLayout);
}
public void OnGUI()
{
EditorGUILayout.BeginVertical();
DrawGeneralGroup();
if (!m_IsPartOfComposite)
{
EditorGUILayout.Space();
DrawInteractionsGroup();
}
EditorGUILayout.Space();
DrawProcessorsGroup();
GUILayout.FlexibleSpace();
EditorGUILayout.EndVertical();
}
protected abstract void DrawGeneralProperties();
private void DrawGeneralGroup()
{
m_GeneralFoldout = DrawFoldout(m_GeneralFoldoutLabel, m_GeneralFoldout);
if (m_GeneralFoldout)
{
EditorGUI.indentLevel++;
DrawGeneralProperties();
EditorGUI.indentLevel--;
}
}
private void DrawProcessorsGroup()
{
m_ProcessorsFoldout = DrawFoldout(s_ProcessorsFoldoutLabel, m_ProcessorsFoldout, s_ProcessorsAddButton, m_ProcessorsList.OnAddDropdown);
if (m_ProcessorsFoldout)
m_ProcessorsList.OnGUI();
}
private void DrawInteractionsGroup()
{
m_InteractionsFoldout = DrawFoldout(s_InteractionsFoldoutLabel, m_InteractionsFoldout, s_InteractionsAddButton, m_InteractionsList.OnAddDropdown);
if (m_InteractionsFoldout)
m_InteractionsList.OnGUI();
}
private static bool DrawFoldout(GUIContent content, bool folded, GUIContent addButton = null, Action<Rect> addDropDown = null)
{
const int k_PopupSize = 20;
var bgRect = GUILayoutUtility.GetRect(content, Styles.s_FoldoutBackgroundStyle);
EditorGUI.LabelField(bgRect, GUIContent.none, Styles.s_FoldoutBackgroundStyle);
var foldoutRect = bgRect;
foldoutRect.xMax -= k_PopupSize;
var retval = EditorGUI.Foldout(foldoutRect, folded, content, true, Styles.s_FoldoutStyle);
if (addButton != null)
{
var popupRect = bgRect;
popupRect.xMin = popupRect.xMax - k_PopupSize;
if (GUI.Button(popupRect, addButton, EditorStyles.label))
addDropDown(popupRect);
}
return retval;
}
private void OnProcessorsModified()
{
m_ProcessorsProperty.stringValue = m_ProcessorsList.ToSerializableString();
m_ProcessorsProperty.serializedObject.ApplyModifiedProperties();
m_OnChange(k_ProcessorsChanged);
}
private void OnInteractionsModified()
{
m_InteractionsProperty.stringValue = m_InteractionsList.ToSerializableString();
m_InteractionsProperty.serializedObject.ApplyModifiedProperties();
m_OnChange(k_InteractionsChanged);
}
public Action<FourCC> onChange => m_OnChange;
private bool m_GeneralFoldout = true;
private bool m_InteractionsFoldout = true;
private bool m_ProcessorsFoldout = true;
protected bool m_IsPartOfComposite;
private readonly Action<FourCC> m_OnChange;
private readonly InteractionsListView m_InteractionsList;
private ProcessorsListView m_ProcessorsList;
private readonly SerializedProperty m_InteractionsProperty;
private readonly SerializedProperty m_ProcessorsProperty;
private readonly GUIContent m_GeneralFoldoutLabel;
////TODO: tooltips
private static readonly GUIContent s_ProcessorsFoldoutLabel = EditorGUIUtility.TrTextContent("Processors");
public static readonly GUIContent s_ProcessorsAddButton = EditorGUIUtility.TrIconContent("Toolbar Plus More", "Add Processor");
private static readonly GUIContent s_InteractionsFoldoutLabel = EditorGUIUtility.TrTextContent("Interactions");
public static readonly GUIContent s_InteractionsAddButton = EditorGUIUtility.TrIconContent("Toolbar Plus More", "Add Interaction");
public static FourCC k_InteractionsChanged => new FourCC("IACT");
public static FourCC k_ProcessorsChanged => new FourCC("PROC");
private static class Styles
{
public static readonly GUIStyle s_FoldoutBackgroundStyle = new GUIStyle("Label")
.WithNormalBackground(AssetDatabase.LoadAssetAtPath<Texture2D>(InputActionTreeView.ResourcesPath + "foldoutBackground.png"))
.WithBorder(new RectOffset(3, 3, 3, 3))
.WithMargin(new RectOffset(1, 1, 3, 3));
public static readonly GUIStyle s_FoldoutStyle = new GUIStyle("foldout");
}
}
}
#endif // UNITY_EDITOR

View File

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