Sin descripción
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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