#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
///
/// Enumeration type for code authoring APIs mapping to .
///
///
/// This enumeration type may be added to, but NEVER changed, since it would break older data.
///
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];
///
/// Registers a call to the associated API.
///
/// Enumeration identifying the API.
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];
}
///
/// Suppresses the registration of analytics.
///
///
/// May be used to temporarily suppress analytics to avoid false positives from internal usage.
///
public static bool suppress
{
get; set;
}
// Cache delegate
private static readonly Action 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);
}
///
/// Represents data collected when exiting play-mode..
///
///
/// Ideally this struct should be readonly but then Unity cannot serialize/deserialize it.
///
[Serializable]
public struct Data : UnityEngine.InputSystem.InputAnalytics.IInputAnalyticData
{
///
/// Creates a new Data instance.
///
/// Specifies whether code authoring has been used during play-mode.
public Data(bool usesCodeAuthoring)
{
uses_code_authoring = usesCodeAuthoring;
}
///
/// Specifies whether code-authoring (Input Action setup via extensions) was used at least once during play-mode.
///
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