test
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7fcb545eb7743c8bd27f341b51151dc
|
||||
timeCreated: 1719232353
|
@@ -0,0 +1,328 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Analytics record for tracking engagement with Input Action Asset editor(s).
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class InputActionsEditorSessionAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_actionasset_editor_closed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new <c>InputActionsEditorSession</c> record of the given <para>type</para>.
|
||||
/// </summary>
|
||||
/// <param name="kind">The editor type for which this record is valid.</param>
|
||||
public InputActionsEditorSessionAnalytic(Data.Kind kind)
|
||||
{
|
||||
if (kind == Data.Kind.Invalid)
|
||||
throw new ArgumentException(nameof(kind));
|
||||
|
||||
Initialize(kind);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register that an action map edit has occurred.
|
||||
/// </summary>
|
||||
public void RegisterActionMapEdit()
|
||||
{
|
||||
if (ImplicitFocus())
|
||||
++m_Data.action_map_modification_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register that an action edit has occurred.
|
||||
/// </summary>
|
||||
public void RegisterActionEdit()
|
||||
{
|
||||
if (ImplicitFocus() && ComputeDuration() > 0.5) // Avoid logging actions triggered via UI initialization
|
||||
++m_Data.action_modification_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register than a binding edit has occurred.
|
||||
/// </summary>
|
||||
public void RegisterBindingEdit()
|
||||
{
|
||||
if (ImplicitFocus())
|
||||
++m_Data.binding_modification_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register that a control scheme edit has occurred.
|
||||
/// </summary>
|
||||
public void RegisterControlSchemeEdit()
|
||||
{
|
||||
if (ImplicitFocus())
|
||||
++m_Data.control_scheme_modification_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register that the editor has received focus which is expected to reflect that the user
|
||||
/// is currently exploring or editing it.
|
||||
/// </summary>
|
||||
public void RegisterEditorFocusIn()
|
||||
{
|
||||
if (!hasSession || hasFocus)
|
||||
return;
|
||||
|
||||
m_FocusStart = currentTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register that the editor has lost focus which is expected to reflect that the user currently
|
||||
/// has the attention elsewhere.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Calling this method without having an ongoing session and having focus will not have any effect.
|
||||
/// </remarks>
|
||||
public void RegisterEditorFocusOut()
|
||||
{
|
||||
if (!hasSession || !hasFocus)
|
||||
return;
|
||||
|
||||
var duration = currentTime - m_FocusStart;
|
||||
m_FocusStart = float.NaN;
|
||||
m_Data.session_focus_duration_seconds += (float)duration;
|
||||
++m_Data.session_focus_switch_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a user-event related to explicitly saving in the editor, e.g.
|
||||
/// using a button, menu or short-cut to trigger the save command.
|
||||
/// </summary>
|
||||
public void RegisterExplicitSave()
|
||||
{
|
||||
if (!hasSession)
|
||||
return; // No pending session
|
||||
|
||||
++m_Data.explicit_save_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a user-event related to implicitly saving in the editor, e.g.
|
||||
/// by having auto-save enabled and indirectly saving the associated asset.
|
||||
/// </summary>
|
||||
public void RegisterAutoSave()
|
||||
{
|
||||
if (!hasSession)
|
||||
return; // No pending session
|
||||
|
||||
++m_Data.auto_save_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a user-event related to resetting the editor action configuration to defaults.
|
||||
/// </summary>
|
||||
public void RegisterReset()
|
||||
{
|
||||
if (!hasSession)
|
||||
return; // No pending session
|
||||
|
||||
++m_Data.reset_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins a new session if the session has not already been started.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the session has already been started due to a previous call to <see cref="Begin()"/> without
|
||||
/// a call to <see cref="End()"/> this method has no effect.
|
||||
/// </remarks>
|
||||
public void Begin()
|
||||
{
|
||||
if (hasSession)
|
||||
return; // Session already started.
|
||||
|
||||
m_SessionStart = currentTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends the current session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the session has not previously been started via a call to <see cref="Begin()"/> calling this
|
||||
/// method has no effect.
|
||||
/// </remarks>
|
||||
public void End()
|
||||
{
|
||||
if (!hasSession)
|
||||
return; // No pending session
|
||||
|
||||
// Make sure we register focus out if failed to capture or not invoked
|
||||
if (hasFocus)
|
||||
RegisterEditorFocusOut();
|
||||
|
||||
// Compute and record total session duration
|
||||
var duration = ComputeDuration();
|
||||
m_Data.session_duration_seconds += duration;
|
||||
|
||||
// Sanity check data, if less than a second its likely a glitch so avoid sending incorrect data
|
||||
// Send analytics event
|
||||
if (duration >= 1.0)
|
||||
runtime.SendAnalytic(this);
|
||||
|
||||
// Reset to allow instance to be reused
|
||||
Initialize(m_Data.kind);
|
||||
}
|
||||
|
||||
#region IInputAnalytic Interface
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
if (!isValid)
|
||||
{
|
||||
data = null;
|
||||
error = new Exception("Unable to gather data without a valid session");
|
||||
return false;
|
||||
}
|
||||
|
||||
data = this.m_Data;
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info => new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
|
||||
#endregion
|
||||
|
||||
private double ComputeDuration() => hasSession ? currentTime - m_SessionStart : 0.0;
|
||||
|
||||
private void Initialize(Data.Kind kind)
|
||||
{
|
||||
m_FocusStart = float.NaN;
|
||||
m_SessionStart = float.NaN;
|
||||
|
||||
m_Data = new Data(kind);
|
||||
}
|
||||
|
||||
private bool ImplicitFocus()
|
||||
{
|
||||
if (!hasSession)
|
||||
return false;
|
||||
if (!hasFocus)
|
||||
RegisterEditorFocusIn();
|
||||
return true;
|
||||
}
|
||||
|
||||
private Data m_Data;
|
||||
private double m_FocusStart;
|
||||
private double m_SessionStart;
|
||||
|
||||
private static IInputRuntime runtime => InputSystem.s_Manager.m_Runtime;
|
||||
private bool hasFocus => !double.IsNaN(m_FocusStart);
|
||||
private bool hasSession => !double.IsNaN(m_SessionStart);
|
||||
// Returns current time since startup. Note that IInputRuntime explicitly defines in interface that
|
||||
// IInputRuntime.currentTime corresponds to EditorApplication.timeSinceStartup in editor.
|
||||
private double currentTime => runtime.currentTime;
|
||||
private bool isValid => m_Data.session_duration_seconds >= 0;
|
||||
|
||||
[Serializable]
|
||||
public struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an editor type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This may be added to in the future but items may never be removed.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public enum Kind
|
||||
{
|
||||
Invalid = 0,
|
||||
EditorWindow = 1,
|
||||
EmbeddedInProjectSettings = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <c>InputActionsEditorSessionData</c>.
|
||||
/// </summary>
|
||||
/// <param name="kind">Specifies the kind of editor metrics is being collected for.</param>
|
||||
public Data(Kind kind)
|
||||
{
|
||||
this.kind = kind;
|
||||
session_duration_seconds = 0;
|
||||
session_focus_duration_seconds = 0;
|
||||
session_focus_switch_count = 0;
|
||||
action_map_modification_count = 0;
|
||||
action_modification_count = 0;
|
||||
binding_modification_count = 0;
|
||||
explicit_save_count = 0;
|
||||
auto_save_count = 0;
|
||||
reset_count = 0;
|
||||
control_scheme_modification_count = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what kind of Input Actions editor this event represents.
|
||||
/// </summary>
|
||||
public Kind kind;
|
||||
|
||||
/// <summary>
|
||||
/// The total duration for the session, i.e. the duration during which the editor window was open.
|
||||
/// </summary>
|
||||
public double session_duration_seconds;
|
||||
|
||||
/// <summary>
|
||||
/// The total duration for which the editor window was open and had focus.
|
||||
/// </summary>
|
||||
public double session_focus_duration_seconds;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the number of times the window has transitioned from not having focus to having focus in a single session.
|
||||
/// </summary>
|
||||
public int session_focus_switch_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of action map modifications during the session.
|
||||
/// </summary>
|
||||
public int action_map_modification_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of action modifications during the session.
|
||||
/// </summary>
|
||||
public int action_modification_count;
|
||||
|
||||
/// The total number of binding modifications during the session.
|
||||
/// </summary>
|
||||
public int binding_modification_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of controls scheme modifications during the session.
|
||||
/// </summary>
|
||||
public int control_scheme_modification_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of explicit saves during the session, i.e. as in user-initiated save.
|
||||
/// </summary>
|
||||
public int explicit_save_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of automatic saves during the session, i.e. as in auto-save on close or focus-lost.
|
||||
/// </summary>
|
||||
public int auto_save_count;
|
||||
|
||||
/// <summary>
|
||||
/// The total number of user-initiated resets during the session, i.e. as in using Reset option in menu.
|
||||
/// </summary>
|
||||
public int reset_count;
|
||||
|
||||
public bool isValid => kind != Kind.Invalid && session_duration_seconds >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d771fd88f0934b4dbe724b2690a9f330
|
||||
timeCreated: 1719312605
|
@@ -0,0 +1,400 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Content;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Analytics for tracking Player Input component user engagement in the editor.
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class InputBuildAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_build_completed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
private readonly BuildReport m_BuildReport;
|
||||
|
||||
public InputBuildAnalytic(BuildReport buildReport)
|
||||
{
|
||||
m_BuildReport = buildReport;
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info =>
|
||||
new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
InputSettings defaultSettings = null;
|
||||
try
|
||||
{
|
||||
defaultSettings = ScriptableObject.CreateInstance<InputSettings>();
|
||||
data = new InputBuildAnalyticData(m_BuildReport, InputSystem.settings, defaultSettings);
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (defaultSettings != null)
|
||||
Object.DestroyImmediate(defaultSettings);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input system build analytics data structure.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
internal struct InputBuildAnalyticData : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
#region InputSettings
|
||||
|
||||
[Serializable]
|
||||
public enum UpdateMode
|
||||
{
|
||||
ProcessEventsInBothFixedAndDynamicUpdate = 0, // Note: Deprecated
|
||||
ProcessEventsInDynamicUpdate = 1,
|
||||
ProcessEventsInFixedUpdate = 2,
|
||||
ProcessEventsManually = 3,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum BackgroundBehavior
|
||||
{
|
||||
ResetAndDisableNonBackgroundDevices = 0,
|
||||
ResetAndDisableAllDevices = 1,
|
||||
IgnoreFocus = 2
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum EditorInputBehaviorInPlayMode
|
||||
{
|
||||
PointersAndKeyboardsRespectGameViewFocus = 0,
|
||||
AllDevicesRespectGameViewFocus = 1,
|
||||
AllDeviceInputAlwaysGoesToGameView = 2
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum InputActionPropertyDrawerMode
|
||||
{
|
||||
Compact = 0,
|
||||
MultilineEffective = 1,
|
||||
MultilineBoth = 2
|
||||
}
|
||||
|
||||
public InputBuildAnalyticData(BuildReport report, InputSettings settings, InputSettings defaultSettings)
|
||||
{
|
||||
switch (settings.updateMode)
|
||||
{
|
||||
case 0: // ProcessEventsInBothFixedAndDynamicUpdate (deprecated/removed)
|
||||
update_mode = UpdateMode.ProcessEventsInBothFixedAndDynamicUpdate;
|
||||
break;
|
||||
case InputSettings.UpdateMode.ProcessEventsManually:
|
||||
update_mode = UpdateMode.ProcessEventsManually;
|
||||
break;
|
||||
case InputSettings.UpdateMode.ProcessEventsInDynamicUpdate:
|
||||
update_mode = UpdateMode.ProcessEventsInDynamicUpdate;
|
||||
break;
|
||||
case InputSettings.UpdateMode.ProcessEventsInFixedUpdate:
|
||||
update_mode = UpdateMode.ProcessEventsInFixedUpdate;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported updateMode");
|
||||
}
|
||||
|
||||
switch (settings.backgroundBehavior)
|
||||
{
|
||||
case InputSettings.BackgroundBehavior.IgnoreFocus:
|
||||
background_behavior = BackgroundBehavior.IgnoreFocus;
|
||||
break;
|
||||
case InputSettings.BackgroundBehavior.ResetAndDisableAllDevices:
|
||||
background_behavior = BackgroundBehavior.ResetAndDisableAllDevices;
|
||||
break;
|
||||
case InputSettings.BackgroundBehavior.ResetAndDisableNonBackgroundDevices:
|
||||
background_behavior = BackgroundBehavior.ResetAndDisableNonBackgroundDevices;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported background behavior");
|
||||
}
|
||||
|
||||
switch (settings.editorInputBehaviorInPlayMode)
|
||||
{
|
||||
case InputSettings.EditorInputBehaviorInPlayMode.PointersAndKeyboardsRespectGameViewFocus:
|
||||
editor_input_behavior_in_playmode = EditorInputBehaviorInPlayMode
|
||||
.PointersAndKeyboardsRespectGameViewFocus;
|
||||
break;
|
||||
case InputSettings.EditorInputBehaviorInPlayMode.AllDevicesRespectGameViewFocus:
|
||||
editor_input_behavior_in_playmode = EditorInputBehaviorInPlayMode
|
||||
.AllDevicesRespectGameViewFocus;
|
||||
break;
|
||||
case InputSettings.EditorInputBehaviorInPlayMode.AllDeviceInputAlwaysGoesToGameView:
|
||||
editor_input_behavior_in_playmode = EditorInputBehaviorInPlayMode
|
||||
.AllDeviceInputAlwaysGoesToGameView;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported editor background behavior");
|
||||
}
|
||||
|
||||
switch (settings.inputActionPropertyDrawerMode)
|
||||
{
|
||||
case InputSettings.InputActionPropertyDrawerMode.Compact:
|
||||
input_action_property_drawer_mode = InputActionPropertyDrawerMode.Compact;
|
||||
break;
|
||||
case InputSettings.InputActionPropertyDrawerMode.MultilineBoth:
|
||||
input_action_property_drawer_mode = InputActionPropertyDrawerMode.MultilineBoth;
|
||||
break;
|
||||
case InputSettings.InputActionPropertyDrawerMode.MultilineEffective:
|
||||
input_action_property_drawer_mode = InputActionPropertyDrawerMode.MultilineEffective;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported editor property drawer mode");
|
||||
}
|
||||
|
||||
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
|
||||
var inputSystemActions = InputSystem.actions;
|
||||
var actionsPath = inputSystemActions == null ? null : AssetDatabase.GetAssetPath(inputSystemActions);
|
||||
has_projectwide_input_action_asset = !string.IsNullOrEmpty(actionsPath);
|
||||
#else
|
||||
has_projectwide_input_action_asset = false;
|
||||
#endif
|
||||
|
||||
var settingsPath = settings == null ? null : AssetDatabase.GetAssetPath(settings);
|
||||
has_settings_asset = !string.IsNullOrEmpty(settingsPath);
|
||||
|
||||
compensate_for_screen_orientation = settings.compensateForScreenOrientation;
|
||||
default_deadzone_min = settings.defaultDeadzoneMin;
|
||||
default_deadzone_max = settings.defaultDeadzoneMax;
|
||||
default_button_press_point = settings.defaultButtonPressPoint;
|
||||
button_release_threshold = settings.buttonReleaseThreshold;
|
||||
default_tap_time = settings.defaultTapTime;
|
||||
default_slow_tap_time = settings.defaultSlowTapTime;
|
||||
default_hold_time = settings.defaultHoldTime;
|
||||
tap_radius = settings.tapRadius;
|
||||
multi_tap_delay_time = settings.multiTapDelayTime;
|
||||
max_event_bytes_per_update = settings.maxEventBytesPerUpdate;
|
||||
max_queued_events_per_update = settings.maxQueuedEventsPerUpdate;
|
||||
supported_devices = settings.supportedDevices.ToArray();
|
||||
disable_redundant_events_merging = settings.disableRedundantEventsMerging;
|
||||
shortcut_keys_consume_input = settings.shortcutKeysConsumeInput;
|
||||
|
||||
feature_optimized_controls_enabled = settings.IsFeatureEnabled(InputFeatureNames.kUseOptimizedControls);
|
||||
feature_read_value_caching_enabled = settings.IsFeatureEnabled(InputFeatureNames.kUseReadValueCaching);
|
||||
feature_paranoid_read_value_caching_checks_enabled =
|
||||
settings.IsFeatureEnabled(InputFeatureNames.kParanoidReadValueCachingChecks);
|
||||
|
||||
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
|
||||
feature_use_imgui_editor_for_assets =
|
||||
settings.IsFeatureEnabled(InputFeatureNames.kUseIMGUIEditorForAssets);
|
||||
#else
|
||||
feature_use_imgui_editor_for_assets = false;
|
||||
#endif
|
||||
feature_disable_unity_remote_support =
|
||||
settings.IsFeatureEnabled(InputFeatureNames.kDisableUnityRemoteSupport);
|
||||
feature_run_player_updates_in_editmode =
|
||||
settings.IsFeatureEnabled(InputFeatureNames.kRunPlayerUpdatesInEditMode);
|
||||
|
||||
has_default_settings = InputSettings.AreEqual(settings, defaultSettings);
|
||||
|
||||
build_guid = report != null ? report.summary.guid.ToString() : string.Empty; // Allows testing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.updateMode"/> and indicates how the project handles updates.
|
||||
/// </summary>
|
||||
public UpdateMode update_mode;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.compensateForScreenOrientation"/> and if true automatically
|
||||
/// adjust rotations when the screen orientation changes.
|
||||
/// </summary>
|
||||
public bool compensate_for_screen_orientation;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.backgroundBehavior"/> which determines what happens when application
|
||||
/// focus changes and how the system handle input while running in the background.
|
||||
/// </summary>
|
||||
public BackgroundBehavior background_behavior;
|
||||
|
||||
// Note: InputSettings.filterNoiseOnCurrent not present since already deprecated when these analytics
|
||||
// where added.
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultDeadzoneMin"/>
|
||||
/// </summary>
|
||||
public float default_deadzone_min;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultDeadzoneMax"/>
|
||||
/// </summary>
|
||||
public float default_deadzone_max;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultButtonPressPoint"/>
|
||||
/// </summary>
|
||||
public float default_button_press_point;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.buttonReleaseThreshold"/>
|
||||
/// </summary>
|
||||
public float button_release_threshold;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultSlowTapTime"/>
|
||||
/// </summary>
|
||||
public float default_tap_time;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultSlowTapTime"/>
|
||||
/// </summary>
|
||||
public float default_slow_tap_time;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.defaultHoldTime"/>
|
||||
/// </summary>
|
||||
public float default_hold_time;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.tapRadius"/>
|
||||
/// </summary>
|
||||
public float tap_radius;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.multiTapDelayTime"/>
|
||||
/// </summary>
|
||||
public float multi_tap_delay_time;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.editorInputBehaviorInPlayMode"/>
|
||||
/// </summary>
|
||||
public EditorInputBehaviorInPlayMode editor_input_behavior_in_playmode;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.inputActionPropertyDrawerMode"/>
|
||||
/// </summary>
|
||||
public InputActionPropertyDrawerMode input_action_property_drawer_mode;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.maxEventBytesPerUpdate"/>
|
||||
/// </summary>
|
||||
public int max_event_bytes_per_update;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.maxQueuedEventsPerUpdate"/>
|
||||
/// </summary>
|
||||
public int max_queued_events_per_update;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.supportedDevices"/>
|
||||
/// </summary>
|
||||
public string[] supported_devices;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.disableRedundantEventsMerging"/>
|
||||
/// </summary>
|
||||
public bool disable_redundant_events_merging;
|
||||
|
||||
/// <summary>
|
||||
/// Represents <see cref="InputSettings.shortcutKeysConsumeInput"/>
|
||||
/// </summary>
|
||||
public bool shortcut_keys_consume_input;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Feature flag settings
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kUseOptimizedControls"/> as defined
|
||||
/// in Input System 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_optimized_controls_enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kUseReadValueCaching" /> as defined
|
||||
/// in Input System 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_read_value_caching_enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kParanoidReadValueCachingChecks" />
|
||||
/// as defined in InputSystem 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_paranoid_read_value_caching_checks_enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kUseIMGUIEditorForAssets" />
|
||||
/// as defined in InputSystem 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_use_imgui_editor_for_assets;
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kDisableUnityRemoteSupport" />
|
||||
/// as defined in InputSystem 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_disable_unity_remote_support;
|
||||
|
||||
/// <summary>
|
||||
/// Represents internal feature flag <see cref="InputFeatureNames.kRunPlayerUpdatesInEditMode" />
|
||||
/// as defined in InputSystem 1.8.x.
|
||||
/// </summary>
|
||||
public bool feature_run_player_updates_in_editmode;
|
||||
|
||||
#endregion
|
||||
|
||||
#region
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether the project is using a project-wide input actions asset or not.
|
||||
/// </summary>
|
||||
public bool has_projectwide_input_action_asset;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether the project is using a user-provided settings asset or not.
|
||||
/// </summary>
|
||||
public bool has_settings_asset;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether the settings asset (if present) of the built project is equal to default settings
|
||||
/// or not. In case of no settings asset this is also true since implicitly using default settings.
|
||||
/// </summary>
|
||||
public bool has_default_settings;
|
||||
|
||||
/// <summary>
|
||||
/// A unique GUID identifying the build.
|
||||
/// </summary>
|
||||
public string build_guid;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input System build analytics.
|
||||
/// </summary>
|
||||
internal class ReportProcessor : IPostprocessBuildWithReport
|
||||
{
|
||||
public int callbackOrder => int.MaxValue;
|
||||
|
||||
public void OnPostprocessBuild(BuildReport report)
|
||||
{
|
||||
InputSystem.s_Manager?.m_Runtime?.SendAnalytic(new InputBuildAnalytic(report));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f760afcbd6744a0e8c9d0b7039dda306
|
||||
timeCreated: 1719312637
|
@@ -0,0 +1,89 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration type identifying a Input System MonoBehavior component.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
internal enum InputSystemComponent
|
||||
{
|
||||
// Feature components
|
||||
PlayerInput = 1,
|
||||
PlayerInputManager = 2,
|
||||
OnScreenStick = 3,
|
||||
OnScreenButton = 4,
|
||||
VirtualMouseInput = 5,
|
||||
|
||||
// Debug components
|
||||
TouchSimulation = 1000,
|
||||
|
||||
// Integration components
|
||||
StandaloneInputModule = 2000,
|
||||
InputSystemUIInputModule = 2001,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Analytics record for tracking engagement with Input Component editor(s).
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class InputComponentEditorAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_component_editor_closed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
/// <summary>
|
||||
/// The associated component type.
|
||||
/// </summary>
|
||||
private readonly InputSystemComponent m_Component;
|
||||
|
||||
/// <summary>
|
||||
/// Represents component inspector editor data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ideally this struct should be readonly but then Unity cannot serialize/deserialize it.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c>ComponentEditorData</c> instance.
|
||||
/// </summary>
|
||||
/// <param name="component">The associated component.</param>
|
||||
public Data(InputSystemComponent component)
|
||||
{
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the associated component.
|
||||
/// </summary>
|
||||
public InputSystemComponent component;
|
||||
}
|
||||
|
||||
public InputComponentEditorAnalytic(InputSystemComponent component)
|
||||
{
|
||||
info = new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
m_Component = component;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
data = new Data(m_Component);
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info { get; }
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b36e69515ff4a45be02062b5584e1a8
|
||||
timeCreated: 1719312182
|
@@ -0,0 +1,46 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
internal static class InputEditorAnalytics
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents notification behavior setting associated with <see cref="PlayerInput"/> and
|
||||
/// <see cref="PlayerInputManager"/>.
|
||||
/// </summary>
|
||||
internal enum PlayerNotificationBehavior
|
||||
{
|
||||
SendMessages = 0,
|
||||
BroadcastMessages = 1,
|
||||
UnityEvents = 2,
|
||||
CSharpEvents = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from current <see cref="PlayerNotifications"/> type to analytics counterpart.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to be converted.</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">If there is no available remapping.</exception>
|
||||
internal static PlayerNotificationBehavior ToNotificationBehavior(PlayerNotifications value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case PlayerNotifications.SendMessages:
|
||||
return PlayerNotificationBehavior.SendMessages;
|
||||
case PlayerNotifications.BroadcastMessages:
|
||||
return PlayerNotificationBehavior.BroadcastMessages;
|
||||
case PlayerNotifications.InvokeUnityEvents:
|
||||
return PlayerNotificationBehavior.UnityEvents;
|
||||
case PlayerNotifications.InvokeCSharpEvents:
|
||||
return PlayerNotificationBehavior.CSharpEvents;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af8ecd25eda841f98ce3f6555888e43b
|
||||
timeCreated: 1704878014
|
@@ -0,0 +1,165 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class InputExitPlayModeAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_exit_playmode";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration type for code authoring APIs mapping to <see cref="InputActionSetupExtensions"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This enumeration type may be added to, but NEVER changed, since it would break older data.
|
||||
/// </remarks>
|
||||
public enum Api
|
||||
{
|
||||
AddBinding = 0,
|
||||
AddCompositeBinding = 1,
|
||||
ChangeBinding = 2,
|
||||
ChangeCompositeBinding = 3,
|
||||
Rename = 4,
|
||||
AddControlScheme = 5,
|
||||
RemoveControlScheme = 6,
|
||||
ControlSchemeWithBindingGroup = 7,
|
||||
ControlSchemeWithDevice = 8,
|
||||
ControlSchemeWithRequiredDevice = 9,
|
||||
ControlSchemeWithOptionalDevice = 10,
|
||||
ControlSchemeOrWithRequiredDevice = 11,
|
||||
ControlSchemeOrWithOptionalDevice = 12
|
||||
}
|
||||
|
||||
private static readonly int[] m_Counters = new int[Enum.GetNames(typeof(Api)).Length];
|
||||
|
||||
/// <summary>
|
||||
/// Registers a call to the associated API.
|
||||
/// </summary>
|
||||
/// <param name="api">Enumeration identifying the API.</param>
|
||||
public static void Register(Api api)
|
||||
{
|
||||
if (suppress)
|
||||
return;
|
||||
|
||||
// Note: Currently discards detailed information and only sets a boolean (aggregated) value.
|
||||
++m_Counters[(int)api];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses the registration of analytics.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// May be used to temporarily suppress analytics to avoid false positives from internal usage.
|
||||
/// </remarks>
|
||||
public static bool suppress
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
// Cache delegate
|
||||
private static readonly Action<PlayModeStateChange> PlayModeChanged = OnPlayModeStateChange;
|
||||
|
||||
// Note: Internal visibility to simplify unit testing
|
||||
internal static void OnPlayModeStateChange(PlayModeStateChange change)
|
||||
{
|
||||
if (change == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
// Reset all counters when exiting edit mode
|
||||
Array.Clear(m_Counters, 0, m_Counters.Length);
|
||||
|
||||
// Make sure not suppressed
|
||||
suppress = false;
|
||||
}
|
||||
if (change == PlayModeStateChange.ExitingPlayMode)
|
||||
{
|
||||
// Send analytics and unhook delegate when exiting play-mode
|
||||
EditorApplication.playModeStateChanged -= PlayModeChanged;
|
||||
new InputExitPlayModeAnalytic().Send();
|
||||
|
||||
// No reason to not suppress
|
||||
suppress = true;
|
||||
}
|
||||
}
|
||||
|
||||
[InitializeOnEnterPlayMode]
|
||||
private static void Hook()
|
||||
{
|
||||
// Make sure only a single play-mode change delegate is registered
|
||||
EditorApplication.playModeStateChanged -= PlayModeChanged;
|
||||
EditorApplication.playModeStateChanged += PlayModeChanged;
|
||||
}
|
||||
|
||||
private InputExitPlayModeAnalytic()
|
||||
{
|
||||
info = new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents data collected when exiting play-mode..
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ideally this struct should be readonly but then Unity cannot serialize/deserialize it.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <c>Data</c> instance.
|
||||
/// </summary>
|
||||
/// <param name="usesCodeAuthoring">Specifies whether code authoring has been used during play-mode.</param>
|
||||
public Data(bool usesCodeAuthoring)
|
||||
{
|
||||
uses_code_authoring = usesCodeAuthoring;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether code-authoring (Input Action setup via extensions) was used at least once during play-mode.
|
||||
/// </summary>
|
||||
public bool uses_code_authoring;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
// Determine aggregated perspective, i.e. was "any" code-authoring API used
|
||||
var usedCodeAuthoringDuringPlayMode = false;
|
||||
for (var i = 0; i < m_Counters.Length; ++i)
|
||||
{
|
||||
if (m_Counters[i] > 0)
|
||||
{
|
||||
usedCodeAuthoringDuringPlayMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = new Data(usedCodeAuthoringDuringPlayMode);
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info { get; }
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UNITY_EDITOR
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07c4c48bac384a9e91c29c2f04328c0b
|
||||
timeCreated: 1724231031
|
@@ -0,0 +1,92 @@
|
||||
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_ENABLE_UI
|
||||
using System;
|
||||
using UnityEngine.InputSystem.OnScreen;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Analytics record for tracking engagement with Input Action Asset editor(s).
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey, version: 2)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class OnScreenStickEditorAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_onscreenstick_editor_destroyed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
/// <summary>
|
||||
/// Represents select configuration data of interest related to an <see cref="OnScreenStick"/> component.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
internal struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
public enum OnScreenStickBehaviour
|
||||
{
|
||||
RelativePositionWithStaticOrigin = 0,
|
||||
ExactPositionWithStaticOrigin = 1,
|
||||
ExactPositionWithDynamicOrigin = 2,
|
||||
}
|
||||
|
||||
private static OnScreenStickBehaviour ToBehaviour(OnScreenStick.Behaviour value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case OnScreenStick.Behaviour.RelativePositionWithStaticOrigin:
|
||||
return OnScreenStickBehaviour.RelativePositionWithStaticOrigin;
|
||||
case OnScreenStick.Behaviour.ExactPositionWithDynamicOrigin:
|
||||
return OnScreenStickBehaviour.ExactPositionWithDynamicOrigin;
|
||||
case OnScreenStick.Behaviour.ExactPositionWithStaticOrigin:
|
||||
return OnScreenStickBehaviour.ExactPositionWithStaticOrigin;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
public Data(OnScreenStick value)
|
||||
{
|
||||
behavior = ToBehaviour(value.behaviour);
|
||||
movement_range = value.movementRange;
|
||||
dynamic_origin_range = value.dynamicOriginRange;
|
||||
use_isolated_input_actions = value.useIsolatedInputActions;
|
||||
}
|
||||
|
||||
public OnScreenStickBehaviour behavior;
|
||||
public float movement_range;
|
||||
public float dynamic_origin_range;
|
||||
public bool use_isolated_input_actions;
|
||||
}
|
||||
|
||||
private readonly UnityEditor.Editor m_Editor;
|
||||
|
||||
public OnScreenStickEditorAnalytic(UnityEditor.Editor editor)
|
||||
{
|
||||
m_Editor = editor;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
data = new Data(m_Editor.target as OnScreenStick);
|
||||
error = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info =>
|
||||
new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2167295510884d5eb4722df2ba677996
|
||||
timeCreated: 1719232380
|
@@ -0,0 +1,71 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Analytics for tracking Player Input component user engagement in the editor.
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class PlayerInputEditorAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_playerinput_editor_destroyed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
private readonly UnityEditor.Editor m_Editor;
|
||||
|
||||
public PlayerInputEditorAnalytic(UnityEditor.Editor editor)
|
||||
{
|
||||
m_Editor = editor;
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info =>
|
||||
new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
data = new Data(m_Editor.target as PlayerInput);
|
||||
error = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
public InputEditorAnalytics.PlayerNotificationBehavior behavior;
|
||||
public bool has_actions;
|
||||
public bool has_default_map;
|
||||
public bool has_ui_input_module;
|
||||
public bool has_camera;
|
||||
|
||||
public Data(PlayerInput playerInput)
|
||||
{
|
||||
behavior = InputEditorAnalytics.ToNotificationBehavior(playerInput.notificationBehavior);
|
||||
has_actions = playerInput.actions != null;
|
||||
has_default_map = playerInput.defaultActionMap != null;
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_UI
|
||||
has_ui_input_module = playerInput.uiInputModule != null;
|
||||
#else
|
||||
has_ui_input_module = false;
|
||||
#endif
|
||||
has_camera = playerInput.camera != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56bc028967c346c2bd33842d7b252123
|
||||
timeCreated: 1719232552
|
@@ -0,0 +1,84 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class PlayerInputManagerEditorAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_playerinputmanager_editor_destroyed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info =>
|
||||
new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
|
||||
private readonly UnityEditor.Editor m_Editor;
|
||||
|
||||
public PlayerInputManagerEditorAnalytic(UnityEditor.Editor editor)
|
||||
{
|
||||
m_Editor = editor;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
data = new Data(m_Editor.target as PlayerInputManager);
|
||||
error = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
public enum PlayerJoinBehavior
|
||||
{
|
||||
JoinPlayersWhenButtonIsPressed = 0, // default
|
||||
JoinPlayersWhenJoinActionIsTriggered = 1,
|
||||
JoinPlayersManually = 2
|
||||
}
|
||||
|
||||
public InputEditorAnalytics.PlayerNotificationBehavior behavior;
|
||||
public PlayerJoinBehavior join_behavior;
|
||||
public bool joining_enabled_by_default;
|
||||
public int max_player_count;
|
||||
|
||||
public Data(PlayerInputManager value)
|
||||
{
|
||||
behavior = InputEditorAnalytics.ToNotificationBehavior(value.notificationBehavior);
|
||||
join_behavior = ToPlayerJoinBehavior(value.joinBehavior);
|
||||
joining_enabled_by_default = value.joiningEnabled;
|
||||
max_player_count = value.maxPlayerCount;
|
||||
}
|
||||
|
||||
private static PlayerJoinBehavior ToPlayerJoinBehavior(UnityEngine.InputSystem.PlayerJoinBehavior value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case UnityEngine.InputSystem.PlayerJoinBehavior.JoinPlayersWhenButtonIsPressed:
|
||||
return PlayerJoinBehavior.JoinPlayersWhenButtonIsPressed;
|
||||
case UnityEngine.InputSystem.PlayerJoinBehavior.JoinPlayersWhenJoinActionIsTriggered:
|
||||
return PlayerJoinBehavior.JoinPlayersWhenJoinActionIsTriggered;
|
||||
case UnityEngine.InputSystem.PlayerJoinBehavior.JoinPlayersManually:
|
||||
return PlayerJoinBehavior.JoinPlayersManually;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 199b31cbe22b4c269aa78f8139347afd
|
||||
timeCreated: 1719232662
|
@@ -0,0 +1,95 @@
|
||||
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_ENABLE_UI
|
||||
using System;
|
||||
using UnityEngine.InputSystem.UI;
|
||||
|
||||
namespace UnityEngine.InputSystem.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Analytics record for tracking engagement with Input Action Asset editor(s).
|
||||
/// </summary>
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
[UnityEngine.Analytics.AnalyticInfo(eventName: kEventName, maxEventsPerHour: kMaxEventsPerHour,
|
||||
maxNumberOfElements: kMaxNumberOfElements, vendorKey: UnityEngine.InputSystem.InputAnalytics.kVendorKey)]
|
||||
#endif // UNITY_2023_2_OR_NEWER
|
||||
internal class VirtualMouseInputEditorAnalytic : UnityEngine.InputSystem.InputAnalytics.IInputAnalytic
|
||||
{
|
||||
public const string kEventName = "input_virtualmouseinput_editor_destroyed";
|
||||
public const int kMaxEventsPerHour = 100; // default: 1000
|
||||
public const int kMaxNumberOfElements = 100; // default: 1000
|
||||
|
||||
[Serializable]
|
||||
internal struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps to <see cref="VirtualMouseInput.cursorMode"/>. Determines which cursor representation to use.
|
||||
/// </summary>
|
||||
public CursorMode cursor_mode;
|
||||
|
||||
/// <summary>
|
||||
/// Maps to <see cref="VirtualMouseInput.cursorSpeed" />. Speed in pixels per second with which to move the cursor.
|
||||
/// </summary>
|
||||
public float cursor_speed;
|
||||
|
||||
/// <summary>
|
||||
/// Maps to <see cref="VirtualMouseInput.cursorMode"/>. Multiplier for values received from <see cref="VirtualMouseInput.scrollWheelAction"/>.
|
||||
/// </summary>
|
||||
public float scroll_speed;
|
||||
|
||||
public enum CursorMode
|
||||
{
|
||||
SoftwareCursor = 0,
|
||||
HardwareCursorIfAvailable = 1
|
||||
}
|
||||
|
||||
private static CursorMode ToCursorMode(VirtualMouseInput.CursorMode value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case VirtualMouseInput.CursorMode.SoftwareCursor:
|
||||
return CursorMode.SoftwareCursor;
|
||||
case VirtualMouseInput.CursorMode.HardwareCursorIfAvailable:
|
||||
return CursorMode.HardwareCursorIfAvailable;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
public Data(VirtualMouseInput value)
|
||||
{
|
||||
cursor_mode = ToCursorMode(value.cursorMode);
|
||||
cursor_speed = value.cursorSpeed;
|
||||
scroll_speed = value.scrollSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
public InputAnalytics.InputAnalyticInfo info =>
|
||||
new InputAnalytics.InputAnalyticInfo(kEventName, kMaxEventsPerHour, kMaxNumberOfElements);
|
||||
|
||||
private readonly UnityEditor.Editor m_Editor;
|
||||
|
||||
public VirtualMouseInputEditorAnalytic(UnityEditor.Editor editor)
|
||||
{
|
||||
m_Editor = editor;
|
||||
}
|
||||
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
public bool TryGatherData(out UnityEngine.Analytics.IAnalytic.IData data, out Exception error)
|
||||
#else
|
||||
public bool TryGatherData(out InputAnalytics.IInputAnalyticData data, out Exception error)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
data = new Data(m_Editor.target as VirtualMouseInput);
|
||||
error = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
data = null;
|
||||
error = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 183f7887e5104e1593ce980b9d0159e3
|
||||
timeCreated: 1719232500
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5c84a68c16874bd5ba1a9d15a5e5044
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5b4f9c3390c14106a5006fd5d3d3cbe
|
||||
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: 9e1e1ebbe5ff04f03bf06ab5398454cf
|
||||
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: eb55afc2c109f42f2af37941a8c9300e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d295e36fd3cd747f4a2123088241bd6a
|
||||
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: 713b035f669b942adbd1cc05c4fb6e1d
|
||||
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: 76d591911f4ae4f62953b13f6ff50429
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8afcd24f0b647f4f9f8c539d613ee6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da649da79e1b9455791f5ddd31355edc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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 |
@@ -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 |
@@ -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:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95391b99439094c00a105cd26ba61b1b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@@ -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:
|
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
@@ -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:
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@@ -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:
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@@ -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:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user