UI 자동화를 위해 바인딩 기능 구현
- 유니티 에셋 인증 오류로 meta 재생성
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user