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

View File

@@ -0,0 +1,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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d771fd88f0934b4dbe724b2690a9f330
timeCreated: 1719312605

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f760afcbd6744a0e8c9d0b7039dda306
timeCreated: 1719312637

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4b36e69515ff4a45be02062b5584e1a8
timeCreated: 1719312182

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: af8ecd25eda841f98ce3f6555888e43b
timeCreated: 1704878014

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 07c4c48bac384a9e91c29c2f04328c0b
timeCreated: 1724231031

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2167295510884d5eb4722df2ba677996
timeCreated: 1719232380

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 56bc028967c346c2bd33842d7b252123
timeCreated: 1719232552

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 199b31cbe22b4c269aa78f8139347afd
timeCreated: 1719232662

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 183f7887e5104e1593ce980b9d0159e3
timeCreated: 1719232500