A game about forced loneliness, made by TACStudios
1#define WRITE_TO_JSON
2using System;
3using System.Collections.Generic;
4using UnityEngine.Analytics;
5using UnityEngine;
6
7namespace UnityEditor.U2D.Animation
8{
9 [Serializable]
10 enum AnimationToolType
11 {
12 UnknownTool = 0,
13 Visibilility = 6,
14 PreviewPose = 7,
15 EditPose = 8,
16 CreateBone = 9,
17 SplitBone = 10,
18 ReparentBone = 11,
19 EditGeometry = 12,
20 CreateVertex = 13,
21 CreateEdge = 14,
22 SplitEdge = 15,
23 GenerateGeometry = 16,
24 WeightSlider = 17,
25 WeightBrush = 18,
26 BoneInfluence = 19,
27 GenerateWeights = 20,
28 SpriteInfluence = 21
29 }
30
31 [Serializable]
32 enum AnimationEventType
33 {
34 Truncated = -1,
35 SelectedSpriteChanged = 0,
36 SkeletonPreviewPoseChanged = 1,
37 SkeletonBindPoseChanged = 2,
38 SkeletonTopologyChanged = 3,
39 MeshChanged = 4,
40 MeshPreviewChanged = 5,
41 SkinningModuleModeChanged = 6,
42 BoneSelectionChanged = 7,
43 BoneNameChanged = 8,
44 CharacterPartChanged = 9,
45 ToolChanged = 10,
46 RestoreBindPose = 11,
47 Copy = 12,
48 Paste = 13,
49 BoneDepthChanged = 14,
50 Shortcut = 15,
51 Visibility = 16
52 }
53
54 [Serializable]
55 struct AnimationEvent
56#if USE_NEW_EDITOR_ANALYTICS
57 : IAnalytic.IData
58#endif
59 {
60 [SerializeField]
61 public AnimationEventType sub_type;
62 [SerializeField]
63 public int repeated_event;
64 [SerializeField]
65 public string data;
66 }
67
68 [Serializable]
69 struct AnimationToolUsageEvent
70#if USE_NEW_EDITOR_ANALYTICS
71 : IAnalytic.IData
72#endif
73 {
74 public const string name = "u2dAnimationToolUsage";
75
76 [SerializeField]
77 public int instance_id;
78 [SerializeField]
79 public AnimationToolType animation_tool;
80 [SerializeField]
81 public bool character_mode;
82 [SerializeField]
83 public int time_start_s;
84 [SerializeField]
85 public int time_end_s;
86 [SerializeField]
87 public List<AnimationEvent> animation_events;
88 }
89
90#if USE_NEW_EDITOR_ANALYTICS
91 [AnalyticInfo(eventName: "u2dAnimationToolUsage",
92 vendorKey: UnityAnalyticsStorage.vendorKey,
93 version: UnityAnalyticsStorage.version,
94 maxEventsPerHour: AnalyticConstant.k_MaxEventsPerHour,
95 maxNumberOfElements: AnalyticConstant.k_MaxNumberOfElements)]
96 class AnimationToolUsageEventAnalytic : IAnalytic
97 {
98 AnimationToolUsageEvent m_EvtData;
99 public AnimationToolUsageEventAnalytic(AnimationToolUsageEvent evtData)
100 {
101 m_EvtData = evtData;
102 }
103 public bool TryGatherData(out IAnalytic.IData data, out Exception error)
104 {
105 data = m_EvtData;
106 error = null;
107 return true;
108 }
109 }
110
111 [AnalyticInfo(eventName: nameof(AnimationEvent),
112 vendorKey: UnityAnalyticsStorage.vendorKey,
113 version: UnityAnalyticsStorage.version,
114 maxEventsPerHour: AnalyticConstant.k_MaxEventsPerHour,
115 maxNumberOfElements: AnalyticConstant.k_MaxNumberOfElements)]
116 class AnimationEventAnalytic : IAnalytic
117 {
118 AnimationEvent m_EvtData;
119 public AnimationEventAnalytic(AnimationEvent evtData)
120 {
121 m_EvtData = evtData;
122 }
123 public bool TryGatherData(out IAnalytic.IData data, out Exception error)
124 {
125 data = m_EvtData;
126 error = null;
127 return true;
128 }
129 }
130
131 [AnalyticInfo(eventName: AnimationToolApplyEvent.name,
132 vendorKey: UnityAnalyticsStorage.vendorKey,
133 version: UnityAnalyticsStorage.version,
134 maxEventsPerHour: AnalyticConstant.k_MaxEventsPerHour,
135 maxNumberOfElements: AnalyticConstant.k_MaxNumberOfElements)]
136 class AnimationToolApplyEventAnalytic : IAnalytic
137 {
138 AnimationToolApplyEvent m_EvtData;
139
140 public AnimationToolApplyEventAnalytic(AnimationToolApplyEvent evtData)
141 {
142 m_EvtData = evtData;
143 }
144 public bool TryGatherData(out IAnalytic.IData data, out Exception error)
145 {
146 data = m_EvtData;
147 error = null;
148 return true;
149 }
150 }
151#endif
152
153 [Serializable]
154 struct AnimationToolApplyEvent
155#if USE_NEW_EDITOR_ANALYTICS
156 : IAnalytic.IData
157#endif
158 {
159 public const string name = "u2dAnimationToolApply";
160
161 [SerializeField]
162 public bool character_mode;
163 [SerializeField]
164 public int instance_id;
165 [SerializeField]
166 public int sprite_count;
167 [SerializeField]
168 public int[] bone_sprite_count;
169 [SerializeField]
170 public int[] bone_count;
171 [SerializeField]
172 public int[] bone_depth;
173 [SerializeField]
174 public int[] bone_chain_count;
175 [SerializeField]
176 public int bone_root_count;
177 }
178
179 internal interface IAnimationAnalyticsModel
180 {
181 bool hasCharacter { get; }
182 SkinningMode mode { get; }
183 ITool selectedTool { get; }
184 ITool GetTool(Tools tool);
185 int selectedBoneCount { get; }
186 int applicationElapseTime { get; }
187 }
188
189 internal class SkinningModuleAnalyticsModel : IAnimationAnalyticsModel
190 {
191 public SkinningCache skinningCache { get; private set; }
192
193 public bool hasCharacter => skinningCache.hasCharacter;
194
195 public SkinningMode mode => skinningCache.mode;
196
197 public ITool selectedTool => skinningCache.selectedTool;
198
199 public ITool GetTool(Tools tool) => skinningCache.GetTool(tool);
200
201 public int selectedBoneCount => skinningCache.skeletonSelection.Count;
202
203 public int applicationElapseTime => (int)EditorApplication.timeSinceStartup;
204
205 public SkinningModuleAnalyticsModel(SkinningCache s)
206 {
207 skinningCache = s;
208 }
209 }
210
211 [Serializable]
212 internal class AnimationAnalytics
213 {
214 const int k_AnimationEventElementCount = 3;
215 const int k_AnimationToolUsageEventElementCount = 6;
216 IAnalyticsStorage m_AnalyticsStorage;
217 SkinningEvents m_EventBus;
218 IAnimationAnalyticsModel m_Model;
219
220 AnimationToolUsageEvent? m_CurrentEvent;
221 int m_InstanceId;
222
223 public AnimationAnalytics(IAnalyticsStorage analyticsStorage, SkinningEvents eventBus, IAnimationAnalyticsModel model, int instanceId)
224 {
225 m_Model = model;
226 m_AnalyticsStorage = analyticsStorage;
227 m_InstanceId = instanceId;
228 m_EventBus = eventBus;
229 m_EventBus.selectedSpriteChanged.AddListener(OnSelectedSpriteChanged);
230 m_EventBus.skeletonPreviewPoseChanged.AddListener(OnSkeletonPreviewPoseChanged);
231 m_EventBus.skeletonBindPoseChanged.AddListener(OnSkeletonBindPoseChanged);
232 m_EventBus.skeletonTopologyChanged.AddListener(OnSkeletonTopologyChanged);
233 m_EventBus.meshChanged.AddListener(OnMeshChanged);
234 m_EventBus.meshPreviewChanged.AddListener(OnMeshPreviewChanged);
235 m_EventBus.skinningModeChanged.AddListener(OnSkinningModuleModeChanged);
236 m_EventBus.boneSelectionChanged.AddListener(OnBoneSelectionChanged);
237 m_EventBus.boneNameChanged.AddListener(OnBoneNameChanged);
238 m_EventBus.boneDepthChanged.AddListener(OnBoneDepthChanged);
239 m_EventBus.characterPartChanged.AddListener(OnCharacterPartChanged);
240 m_EventBus.toolChanged.AddListener(OnToolChanged);
241 m_EventBus.restoreBindPose.AddListener(OnRestoreBindPose);
242 m_EventBus.copy.AddListener(OnCopy);
243 m_EventBus.paste.AddListener(OnPaste);
244 m_EventBus.shortcut.AddListener(OnShortcut);
245 m_EventBus.boneVisibility.AddListener(OnBoneVisibility);
246
247 OnToolChanged(model.selectedTool);
248 }
249
250 public void Dispose()
251 {
252 m_EventBus.selectedSpriteChanged.RemoveListener(OnSelectedSpriteChanged);
253 m_EventBus.skeletonPreviewPoseChanged.RemoveListener(OnSkeletonPreviewPoseChanged);
254 m_EventBus.skeletonBindPoseChanged.RemoveListener(OnSkeletonBindPoseChanged);
255 m_EventBus.skeletonTopologyChanged.RemoveListener(OnSkeletonTopologyChanged);
256 m_EventBus.meshChanged.RemoveListener(OnMeshChanged);
257 m_EventBus.meshPreviewChanged.RemoveListener(OnMeshPreviewChanged);
258 m_EventBus.skinningModeChanged.RemoveListener(OnSkinningModuleModeChanged);
259 m_EventBus.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged);
260 m_EventBus.boneNameChanged.RemoveListener(OnBoneNameChanged);
261 m_EventBus.boneDepthChanged.AddListener(OnBoneDepthChanged);
262 m_EventBus.characterPartChanged.RemoveListener(OnCharacterPartChanged);
263 m_EventBus.toolChanged.RemoveListener(OnToolChanged);
264 m_EventBus.copy.RemoveListener(OnCopy);
265 m_EventBus.paste.RemoveListener(OnPaste);
266 m_EventBus.shortcut.RemoveListener(OnShortcut);
267 m_EventBus.boneVisibility.RemoveListener(OnBoneVisibility);
268 m_AnalyticsStorage.Dispose();
269 }
270
271 void OnBoneVisibility(string s)
272 {
273 SetAnimationEvent(new AnimationEvent()
274 {
275 sub_type = AnimationEventType.Visibility,
276 data = s
277 });
278 }
279
280 void OnShortcut(string s)
281 {
282 SetAnimationEvent(new AnimationEvent()
283 {
284 sub_type = AnimationEventType.Shortcut,
285 data = s
286 });
287 }
288
289 void OnCopy()
290 {
291 SetAnimationEvent(new AnimationEvent()
292 {
293 sub_type = AnimationEventType.Copy,
294 data = ""
295 });
296 }
297
298 void OnPaste(bool bone, bool mesh, bool flipX, bool flipY)
299 {
300 SetAnimationEvent(new AnimationEvent()
301 {
302 sub_type = AnimationEventType.Paste,
303 data = string.Format("b:{0} m:{1} x:{2} y:{3}", bone, mesh, flipX, flipY)
304 });
305 }
306
307 void OnSelectedSpriteChanged(SpriteCache sprite)
308 {
309 SetAnimationEvent(new AnimationEvent()
310 {
311 sub_type = AnimationEventType.SelectedSpriteChanged,
312 data = sprite == null ? "false" : "true"
313 });
314 }
315
316 void OnSkeletonPreviewPoseChanged(SkeletonCache skeleton)
317 {
318 SetAnimationEvent(new AnimationEvent()
319 {
320 sub_type = AnimationEventType.SkeletonPreviewPoseChanged,
321 data = ""
322 });
323 }
324
325 void OnSkeletonBindPoseChanged(SkeletonCache skeleton)
326 {
327 SetAnimationEvent(new AnimationEvent()
328 {
329 sub_type = AnimationEventType.SkeletonBindPoseChanged,
330 data = ""
331 });
332 }
333
334 void OnSkeletonTopologyChanged(SkeletonCache skeleton)
335 {
336 SetAnimationEvent(new AnimationEvent()
337 {
338 sub_type = AnimationEventType.SkeletonTopologyChanged,
339 data = ""
340 });
341 }
342
343 void OnMeshChanged(MeshCache mesh)
344 {
345 SetAnimationEvent(new AnimationEvent()
346 {
347 sub_type = AnimationEventType.MeshChanged,
348 data = ""
349 });
350 }
351
352 void OnMeshPreviewChanged(MeshPreviewCache mesh) { }
353
354 void OnSkinningModuleModeChanged(SkinningMode mode)
355 {
356 SetAnimationEvent(new AnimationEvent()
357 {
358 sub_type = AnimationEventType.SkinningModuleModeChanged,
359 data = mode.ToString()
360 });
361 }
362
363 void OnBoneSelectionChanged()
364 {
365 SetAnimationEvent(new AnimationEvent()
366 {
367 sub_type = AnimationEventType.BoneSelectionChanged,
368 data = m_Model.selectedBoneCount.ToString()
369 });
370 }
371
372 void OnBoneNameChanged(BoneCache bone)
373 {
374 SetAnimationEvent(new AnimationEvent()
375 {
376 sub_type = AnimationEventType.BoneNameChanged,
377 data = ""
378 });
379 }
380
381 void OnBoneDepthChanged(BoneCache bone)
382 {
383 SetAnimationEvent(new AnimationEvent()
384 {
385 sub_type = AnimationEventType.BoneDepthChanged,
386 data = ""
387 });
388 }
389
390 void OnCharacterPartChanged(CharacterPartCache part)
391 {
392 SetAnimationEvent(new AnimationEvent()
393 {
394 sub_type = AnimationEventType.CharacterPartChanged,
395 data = ""
396 });
397 }
398
399 void OnToolChanged(ITool tool)
400 {
401 if (tool == m_Model.GetTool(Tools.ReparentBone))
402 StartNewEvent(AnimationToolType.ReparentBone, m_Model.applicationElapseTime);
403 else if (tool == m_Model.GetTool(Tools.CreateBone))
404 StartNewEvent(AnimationToolType.CreateBone, m_Model.applicationElapseTime);
405 else if (tool == m_Model.GetTool(Tools.EditJoints))
406 StartNewEvent(AnimationToolType.EditPose, m_Model.applicationElapseTime);
407 else if (tool == m_Model.GetTool(Tools.EditPose))
408 StartNewEvent(AnimationToolType.PreviewPose, m_Model.applicationElapseTime);
409 else if (tool == m_Model.GetTool(Tools.SplitBone))
410 StartNewEvent(AnimationToolType.SplitBone, m_Model.applicationElapseTime);
411 else if (tool == m_Model.GetTool(Tools.CreateEdge))
412 StartNewEvent(AnimationToolType.CreateEdge, m_Model.applicationElapseTime);
413 else if (tool == m_Model.GetTool(Tools.CreateVertex))
414 StartNewEvent(AnimationToolType.CreateVertex, m_Model.applicationElapseTime);
415 else if (tool == m_Model.GetTool(Tools.EditGeometry))
416 StartNewEvent(AnimationToolType.EditGeometry, m_Model.applicationElapseTime);
417 else if (tool == m_Model.GetTool(Tools.GenerateGeometry))
418 StartNewEvent(AnimationToolType.GenerateGeometry, m_Model.applicationElapseTime);
419 else if (tool == m_Model.GetTool(Tools.SplitEdge))
420 StartNewEvent(AnimationToolType.SplitEdge, m_Model.applicationElapseTime);
421 else if (tool == m_Model.GetTool(Tools.Visibility))
422 StartNewEvent(AnimationToolType.Visibilility, m_Model.applicationElapseTime);
423 else if (tool == m_Model.GetTool(Tools.BoneInfluence))
424 StartNewEvent(AnimationToolType.BoneInfluence, m_Model.applicationElapseTime);
425 else if (tool == m_Model.GetTool(Tools.SpriteInfluence))
426 StartNewEvent(AnimationToolType.SpriteInfluence, m_Model.applicationElapseTime);
427 else if (tool == m_Model.GetTool(Tools.GenerateWeights))
428 StartNewEvent(AnimationToolType.GenerateWeights, m_Model.applicationElapseTime);
429 else if (tool == m_Model.GetTool(Tools.WeightBrush))
430 StartNewEvent(AnimationToolType.WeightBrush, m_Model.applicationElapseTime);
431 else if (tool == m_Model.GetTool(Tools.WeightSlider))
432 StartNewEvent(AnimationToolType.WeightSlider, m_Model.applicationElapseTime);
433 else
434 StartNewEvent(AnimationToolType.UnknownTool, m_Model.applicationElapseTime);
435 }
436
437 void OnRestoreBindPose()
438 {
439 SetAnimationEvent(new AnimationEvent()
440 {
441 sub_type = AnimationEventType.RestoreBindPose,
442 data = ""
443 });
444 }
445
446 void SetAnimationEvent(AnimationEvent evt)
447 {
448 if (m_CurrentEvent != null)
449 {
450 var toolEvent = m_CurrentEvent.Value;
451 var eventCount = toolEvent.animation_events.Count;
452 if (eventCount > 0 && toolEvent.animation_events[eventCount - 1].sub_type == evt.sub_type && toolEvent.animation_events[eventCount - 1].data == evt.data)
453 {
454 var e = toolEvent.animation_events[eventCount - 1];
455 e.repeated_event += 1;
456 toolEvent.animation_events[eventCount - 1] = e;
457 }
458 else
459 {
460 var elementCountPlus = k_AnimationToolUsageEventElementCount + (eventCount + 1 * k_AnimationEventElementCount);
461 if (elementCountPlus >= AnalyticConstant.k_MaxNumberOfElements)
462 {
463 // We reached the max number of events. Change the last one to truncated
464 var e = toolEvent.animation_events[eventCount - 1];
465 if (e.sub_type != AnimationEventType.Truncated)
466 {
467 e.sub_type = AnimationEventType.Truncated;
468 e.repeated_event = 0;
469 }
470
471 e.repeated_event += 1;
472 toolEvent.animation_events[eventCount - 1] = e;
473 }
474 else
475 toolEvent.animation_events.Add(evt);
476 }
477
478 m_CurrentEvent = toolEvent;
479 }
480 }
481
482 void StartNewEvent(AnimationToolType animationType, int tick)
483 {
484 SendLastEvent(tick);
485 m_CurrentEvent = new AnimationToolUsageEvent()
486 {
487 instance_id = m_InstanceId,
488 character_mode = m_Model.mode == SkinningMode.Character,
489 animation_tool = animationType,
490 time_start_s = tick,
491 animation_events = new List<AnimationEvent>()
492 };
493 }
494
495 void SendLastEvent(AnimationToolUsageEvent evt, int tick)
496 {
497 evt.time_end_s = tick;
498 m_AnalyticsStorage.SendUsageEvent(evt);
499 }
500
501 void SendLastEvent(int tick)
502 {
503 if (m_CurrentEvent != null)
504 {
505 SendLastEvent(m_CurrentEvent.Value, tick);
506 }
507
508 m_CurrentEvent = null;
509 }
510
511 public void FlushEvent()
512 {
513 SendLastEvent(m_Model.applicationElapseTime);
514 }
515
516 public void SendApplyEvent(int spriteCount, int[] spriteBoneCount, BoneCache[] bones)
517 {
518 int[] chainBoneCount = null;
519 int[] maxDepth = null;
520 int[] boneCount = null;
521 int boneRootCount = 0;
522 GetChainBoneStatistic(bones, out chainBoneCount, out maxDepth, out boneRootCount, out boneCount);
523 var applyEvent = new AnimationToolApplyEvent()
524 {
525 instance_id = m_InstanceId,
526 character_mode = m_Model.hasCharacter,
527 sprite_count = spriteCount,
528 bone_sprite_count = spriteBoneCount,
529 bone_depth = maxDepth,
530 bone_chain_count = chainBoneCount,
531 bone_root_count = boneRootCount,
532 bone_count = boneCount
533 };
534 m_AnalyticsStorage.SendApplyEvent(applyEvent);
535 }
536
537 static void GetChainBoneStatistic(BoneCache[] bones, out int[] chainBoneCount, out int[] maxDepth, out int boneRootCount, out int[] boneCount)
538 {
539 List<int> chainCountList = new List<int>();
540 List<int> boneDepthList = new List<int>();
541 List<int> countList = new List<int>();
542 boneRootCount = 0;
543 foreach (var b in bones)
544 {
545 if (b.parentBone == null)
546 {
547 ++boneRootCount;
548 var chain = 0;
549 var chainDepth = 0;
550 var tempBone = b;
551 var count = 1;
552 while (tempBone != null)
553 {
554 ++chainDepth;
555 tempBone = tempBone.chainedChild;
556 }
557
558 foreach (var b1 in bones)
559 {
560 // if this bone is part of this root
561 var parentBone = b1.parentBone;
562 while (parentBone != null)
563 {
564 if (parentBone == b)
565 {
566 ++count;
567
568 // the bone has a parent and the parent bone's chainedChild is not us, means we are a new chain
569 if (b1.parentBone != null && b1.parentBone.chainedChild != b1)
570 {
571 ++chain;
572 var chainDepth1 = 0;
573 tempBone = b1;
574 while (tempBone != null)
575 {
576 ++chainDepth1;
577 tempBone = tempBone.chainedChild;
578 }
579
580 chainDepth = chainDepth1 > chainDepth ? chainDepth1 : chainDepth;
581 }
582
583 break;
584 }
585
586 parentBone = parentBone.parentBone;
587 }
588 }
589
590 chainCountList.Add(chain);
591 boneDepthList.Add(chainDepth);
592 countList.Add(count);
593 }
594 }
595
596 chainBoneCount = chainCountList.ToArray();
597 maxDepth = boneDepthList.ToArray();
598 boneCount = countList.ToArray();
599 }
600 }
601
602 internal interface IAnalyticsStorage
603 {
604 AnalyticsResult SendUsageEvent(AnimationToolUsageEvent evt);
605 AnalyticsResult SendApplyEvent(AnimationToolApplyEvent evt);
606 void Dispose();
607 }
608
609 internal static class AnalyticConstant
610 {
611 public const int k_MaxEventsPerHour = 1000;
612 public const int k_MaxNumberOfElements = 1000;
613 }
614
615 internal class AnalyticsJsonStorage : IAnalyticsStorage
616 {
617 [Serializable]
618 struct AnimationToolEvents
619 {
620 [SerializeField]
621 public List<AnimationToolUsageEvent> events;
622 [SerializeField]
623 public AnimationToolApplyEvent applyEvent;
624 }
625
626 AnimationToolEvents m_TotalEvents = new AnimationToolEvents()
627 {
628 events = new List<AnimationToolUsageEvent>(),
629 applyEvent = new AnimationToolApplyEvent()
630 };
631
632 public AnalyticsResult SendUsageEvent(AnimationToolUsageEvent evt)
633 {
634 m_TotalEvents.events.Add(evt);
635 return AnalyticsResult.Ok;
636 }
637
638 public AnalyticsResult SendApplyEvent(AnimationToolApplyEvent evt)
639 {
640 m_TotalEvents.applyEvent = evt;
641 return AnalyticsResult.Ok;
642 }
643
644 public void Dispose()
645 {
646 try
647 {
648 string file = string.Format("analytics_{0}.json", System.DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss"));
649 if (System.IO.File.Exists(file))
650 System.IO.File.Delete(file);
651 System.IO.File.WriteAllText(file, JsonUtility.ToJson(m_TotalEvents, true));
652 }
653 catch (Exception ex)
654 {
655 Debug.Log(ex);
656 }
657 finally
658 {
659 m_TotalEvents.events.Clear();
660 }
661 }
662 }
663
664 [InitializeOnLoad]
665 internal class UnityAnalyticsStorage : IAnalyticsStorage
666 {
667 public const string vendorKey = "unity.2d.animation";
668 public const int version = 1;
669
670 static UnityAnalyticsStorage()
671 {
672#if !USE_NEW_EDITOR_ANALYTICS
673 EditorAnalytics.RegisterEventWithLimit(AnimationToolUsageEvent.name, AnalyticConstant.k_MaxEventsPerHour, AnalyticConstant.k_MaxNumberOfElements, vendorKey, version);
674 EditorAnalytics.RegisterEventWithLimit(AnimationToolApplyEvent.name, AnalyticConstant.k_MaxEventsPerHour, AnalyticConstant.k_MaxNumberOfElements, vendorKey, version);
675#endif
676 }
677
678 public AnalyticsResult SendUsageEvent(AnimationToolUsageEvent evt)
679 {
680#if USE_NEW_EDITOR_ANALYTICS
681 return EditorAnalytics.SendAnalytic(new AnimationToolUsageEventAnalytic(evt));
682#else
683 return EditorAnalytics.SendEventWithLimit(AnimationToolUsageEvent.name, evt, version);
684#endif
685 }
686
687 public AnalyticsResult SendApplyEvent(AnimationToolApplyEvent evt)
688 {
689#if USE_NEW_EDITOR_ANALYTICS
690 return EditorAnalytics.SendAnalytic(new AnimationToolApplyEventAnalytic(evt));
691#else
692 return EditorAnalytics.SendEventWithLimit(AnimationToolApplyEvent.name, evt, version);
693#endif
694 }
695
696 public void Dispose() { }
697 }
698}