暫無描述
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.

AnimationClipConverter.cs 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEditor.Rendering.Universal;
  6. using ClipPath = UnityEditor.Rendering.AnimationClipUpgrader.ClipPath;
  7. using ClipProxy = UnityEditor.Rendering.AnimationClipUpgrader.AnimationClipProxy;
  8. using UnityObject = UnityEngine.Object;
  9. namespace UnityEditor.Rendering.Universal
  10. {
  11. internal sealed class AnimationClipConverter : RenderPipelineConverter
  12. {
  13. public override string name => "Animation Clip Converter";
  14. public override string info => "This converter updates all animation clips so that they reference the correct Materials.";
  15. public override string category { get; }
  16. public override Type container => typeof(BuiltInToURPConverterContainer);
  17. List<GlobalObjectId> m_AssetsToConvert = new List<GlobalObjectId>(64);
  18. IDictionary<AnimationClipUpgrader.IAnimationClip, (ClipPath Path, EditorCurveBinding[] Bindings, SerializedShaderPropertyUsage Usage, IDictionary<EditorCurveBinding, string> PropertyRenames)> m_ClipData =
  19. new Dictionary<AnimationClipUpgrader.IAnimationClip, (ClipPath Path, EditorCurveBinding[] Bindings, SerializedShaderPropertyUsage Usage, IDictionary<EditorCurveBinding, string> PropertyRenames)>();
  20. public override void OnInitialize(InitializeConverterContext ctx, Action callback)
  21. {
  22. // get paths to all animation clips
  23. var clipPaths = AssetDatabase.FindAssets("t:AnimationClip")
  24. .Select(p => (ClipPath)AssetDatabase.GUIDToAssetPath(p))
  25. .ToArray();
  26. // retrieve clip assets with material animation
  27. m_ClipData = AnimationClipUpgrader.GetAssetDataForClipsFiltered(clipPaths);
  28. // collect all clips and add them to the context
  29. var keys = m_ClipData.Keys.ToArray();
  30. var clipIds = new GlobalObjectId[keys.Length];
  31. GlobalObjectId.GetGlobalObjectIdsSlow(keys.Select(c => c.Clip as UnityObject).ToArray(), clipIds);
  32. for (int i = 0; i < keys.Length; ++i)
  33. {
  34. AnimationClipUpgrader.IAnimationClip key = keys[i];
  35. var cd = m_ClipData[key];
  36. var clip = key.Clip;
  37. var item = new ConverterItemDescriptor()
  38. {
  39. name = clip.name,
  40. info = cd.Path,
  41. };
  42. // TODO: need to know how materials will be upgraded in order to generate warnings
  43. m_AssetsToConvert.Add(clipIds[i]);
  44. ctx.AddAssetToConvert(item);
  45. }
  46. callback.Invoke();
  47. }
  48. public override void OnPreRun()
  49. {
  50. // get paths to all animation clips
  51. var clipPaths = new HashSet<ClipPath>(m_ClipData.Values.Select(cd => cd.Path));
  52. // get paths to all prefabs and scenes in order to inspect clip usage
  53. var prefabPaths = AssetDatabase.FindAssets("t:Prefab")
  54. .Select(p => (AnimationClipUpgrader.PrefabPath)AssetDatabase.GUIDToAssetPath(p))
  55. .ToArray();
  56. var scenePaths = AssetDatabase.FindAssets("t:Scene")
  57. .Select(p => (AnimationClipUpgrader.ScenePath)AssetDatabase.GUIDToAssetPath(p))
  58. .ToArray();
  59. // create table mapping all upgrade paths to new shaders
  60. var upgraders = new UniversalRenderPipelineMaterialUpgrader().upgraders;
  61. var allUpgradePathsToNewShaders = UpgradeUtility.GetAllUpgradePathsToShaders(upgraders);
  62. // TODO: could pass in upgrade paths used by materials in the future
  63. // retrieve interdependencies with prefabs to figure out which clips can be safely upgraded
  64. AnimationClipUpgrader.GetClipDependencyMappings(clipPaths, prefabPaths, out var clipPrefabDependents, out var prefabDependencies);
  65. AnimationClipUpgrader.GatherClipsUsageInDependentPrefabs(
  66. clipPrefabDependents, prefabDependencies, m_ClipData, allUpgradePathsToNewShaders, default, default);
  67. // do the same for clips used by scenes
  68. AnimationClipUpgrader.GetClipDependencyMappings(clipPaths, scenePaths, out var clipSceneDependents, out var sceneDependencies);
  69. AnimationClipUpgrader.GatherClipsUsageInDependentScenes(
  70. clipSceneDependents, sceneDependencies, m_ClipData, allUpgradePathsToNewShaders, default, default);
  71. }
  72. HashSet<(AnimationClipUpgrader.IAnimationClip Clip, ClipPath Path, SerializedShaderPropertyUsage Usage)> m_Upgraded =
  73. new HashSet<(AnimationClipUpgrader.IAnimationClip Clip, ClipPath Path, SerializedShaderPropertyUsage Usage)>();
  74. HashSet<(AnimationClipUpgrader.IAnimationClip Clip, ClipPath Path, SerializedShaderPropertyUsage Usage)> m_NotUpgraded =
  75. new HashSet<(AnimationClipUpgrader.IAnimationClip Clip, ClipPath Path, SerializedShaderPropertyUsage Usage)>();
  76. IDictionary<AnimationClipUpgrader.IAnimationClip, (ClipPath Path, EditorCurveBinding[] Bindings, SerializedShaderPropertyUsage Usage, IDictionary<EditorCurveBinding, string> PropertyRenames)> m_TempClipData =
  77. new Dictionary<AnimationClipUpgrader.IAnimationClip, (ClipPath Path, EditorCurveBinding[] Bindings, SerializedShaderPropertyUsage Usage, IDictionary<EditorCurveBinding, string> PropertyRenames)>();
  78. public override void OnRun(ref RunItemContext ctx)
  79. {
  80. // filter flags are used to determine which clips to skip over during upgrade process
  81. // we want to process all clips that are not ambiguously upgraded
  82. const SerializedShaderPropertyUsage kFilterFlags =
  83. ~(
  84. SerializedShaderPropertyUsage.UsedByUpgraded
  85. | SerializedShaderPropertyUsage.UsedByNonUpgraded
  86. );
  87. const SerializedShaderPropertyUsage kSuccessFlags =
  88. SerializedShaderPropertyUsage.UsedByUpgraded;
  89. var clipKey = (ClipProxy)GlobalObjectId.GlobalObjectIdentifierToObjectSlow(m_AssetsToConvert[ctx.item.index]);
  90. m_TempClipData.Clear();
  91. m_TempClipData[clipKey] = m_ClipData[clipKey];
  92. m_Upgraded.Clear();
  93. m_NotUpgraded.Clear();
  94. AnimationClipUpgrader.UpgradeClips(m_TempClipData, kFilterFlags, m_Upgraded, m_NotUpgraded, default);
  95. var usage = m_TempClipData[clipKey].Usage;
  96. // Success
  97. if ((usage & kSuccessFlags) != 0 && (usage & kFilterFlags) == 0)
  98. return;
  99. if (usage == SerializedShaderPropertyUsage.Unknown)
  100. {
  101. ctx.didFail = true;
  102. ctx.info = L10n.Tr("The animation clip is not used by any objects with renderers currently in the project, so it may not be safe to automatically upgrade.");
  103. return;
  104. }
  105. var sb = new StringBuilder();
  106. sb.Append(L10n.Tr("The animation clip was not modified for one or more reasons:"));
  107. if ((usage & SerializedShaderPropertyUsage.UsedByAmbiguouslyUpgraded) != 0)
  108. {
  109. ctx.didFail = true;
  110. sb.Append(L10n.Tr("\n - The animation clip is used by objects with materials that took different upgrade paths for the animated property."));
  111. }
  112. if ((usage & SerializedShaderPropertyUsage.UsedByNonUpgraded) != 0)
  113. {
  114. ctx.didFail = true;
  115. sb.Append(L10n.Tr("\n - The animation clip is used by objects with materials that have not been upgraded."));
  116. }
  117. if (ctx.didFail)
  118. ctx.info = sb.ToString();
  119. }
  120. public override void OnClicked(int index)
  121. {
  122. var id = m_AssetsToConvert[index];
  123. var clip = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(id);
  124. if (clip == null)
  125. return;
  126. EditorGUIUtility.PingObject(clip);
  127. }
  128. }
  129. }