diff --git a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj index 3672103003..203433e117 100644 --- a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj @@ -1,4 +1,4 @@ - + @@ -7,7 +7,7 @@ false false false - latest + 10.0 1701 diff --git a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/Data.cs b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/Data.cs index 6e100ee65e..0a7938fabc 100644 --- a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/Data.cs +++ b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/Data.cs @@ -34,7 +34,6 @@ public class ConfigurationData public string UnityVersion; public Version UnityVersionNumeric; public string UnitySourceCodePath; - public bool AdvancedLicense; public bool Batchmode; public bool EmitDataForBeeWhy; public string NamedPipeOrUnixSocket; diff --git a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs index 35507fb75a..48b52443eb 100644 --- a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs +++ b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs @@ -92,7 +92,12 @@ public class Il2CppConfig public string[] AdditionalCppFiles = new string[0]; public string[] AdditionalArgs = new string[0]; public string CompilerFlags; + public string[] AdditionalLibraries; + public string[] AdditionalDefines; + public string[] AdditionalIncludeDirectories; + public string[] AdditionalLinkDirectories; public string LinkerFlags; + public string LinkerFlagsFile; public string ExtraTypes; public bool CreateSymbolFiles; public bool AllowDebugging; @@ -109,6 +114,7 @@ public class Services public bool EnablePerformanceReporting; public bool EnableAnalytics; public bool EnableCrashReporting; + public bool EnableInsights; } public class StreamingAssetsFile diff --git a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj index 3f29c8f429..e0d902cbeb 100644 --- a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj @@ -1,4 +1,4 @@ - + @@ -7,7 +7,7 @@ false false false - latest + 10.0 1701 PlayerBuildProgramLibrary.Data diff --git a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/Data.cs b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/Data.cs index e496ccbdd9..fc674d689c 100644 --- a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/Data.cs +++ b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/Data.cs @@ -56,6 +56,7 @@ public class AssemblyData public class ScriptCompilationData_Out { public AssemblyData_Out[] Assemblies; + public bool LocalizeCompilerMessages; } public class AssemblyData_Out diff --git a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj index d714f512c1..d6bea2d0e6 100644 --- a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj +++ b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj @@ -1,4 +1,4 @@ - + @@ -7,7 +7,7 @@ false false false - latest + 10.0 1701 diff --git a/Editor/Mono/2D/SpriteAtlas/EditorSpriteAtlas.bindings.cs b/Editor/Mono/2D/SpriteAtlas/EditorSpriteAtlas.bindings.cs index fe01b8454a..6f031931e2 100644 --- a/Editor/Mono/2D/SpriteAtlas/EditorSpriteAtlas.bindings.cs +++ b/Editor/Mono/2D/SpriteAtlas/EditorSpriteAtlas.bindings.cs @@ -104,8 +104,23 @@ public static class SpriteAtlasExtensions extern public static void SetTextureSettings([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlasTextureSettings src); extern public static SpriteAtlasPackingSettings GetPackingSettings([NotNull] this SpriteAtlas spriteAtlas); extern public static void SetPackingSettings([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlasPackingSettings src); - extern public static TextureImporterPlatformSettings GetPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, string buildTarget); - extern public static void SetPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src); + + [NativeName("GetPlatformSettings")] + extern private static TextureImporterPlatformSettings GetPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, string buildTarget); + public static TextureImporterPlatformSettings GetPlatformSettings(this SpriteAtlas spriteAtlas, string buildTarget) + { + buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + return GetPlatformSettings_Internal(spriteAtlas, buildTarget); + } + + [NativeName("SetPlatformSettings")] + extern private static void SetPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src); + public static void SetPlatformSettings(this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src) + { + src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + SetPlatformSettings_Internal(spriteAtlas, src); + } + extern public static void SetIncludeInBuild([NotNull] this SpriteAtlas spriteAtlas, bool value); extern public static void SetIsVariant([NotNull] this SpriteAtlas spriteAtlas, bool value); extern public static void SetMasterAtlas([NotNull] this SpriteAtlas spriteAtlas, SpriteAtlas value); @@ -119,8 +134,23 @@ public static class SpriteAtlasExtensions extern internal static TextureFormat GetTextureFormat([NotNull] this SpriteAtlas spriteAtlas, BuildTarget target); extern internal static Sprite[] GetPackedSprites([NotNull] this SpriteAtlas spriteAtlas); extern internal static Hash128 GetStoredHash([NotNull] this SpriteAtlas spriteAtlas); - extern internal static TextureImporterPlatformSettings GetSecondaryPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, string buildTarget, string secondaryTextureName); - extern internal static void SetSecondaryPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src, string secondaryTextureName); + + [NativeName("GetSecondaryPlatformSettings")] + extern private static TextureImporterPlatformSettings GetSecondaryPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, string buildTarget, string secondaryTextureName); + internal static TextureImporterPlatformSettings GetSecondaryPlatformSettings(this SpriteAtlas spriteAtlas, string buildTarget, string secondaryTextureName) + { + buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + return GetSecondaryPlatformSettings_Internal(spriteAtlas, buildTarget, secondaryTextureName); + } + + [NativeName("SetSecondaryPlatformSettings")] + extern private static void SetSecondaryPlatformSettings_Internal([NotNull] this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src, string secondaryTextureName); + internal static void SetSecondaryPlatformSettings(this SpriteAtlas spriteAtlas, TextureImporterPlatformSettings src, string secondaryTextureName) + { + src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + SetSecondaryPlatformSettings_Internal(spriteAtlas, src, secondaryTextureName); + } + extern internal static bool GetSecondaryColorSpace([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName); extern internal static void SetSecondaryColorSpace([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName, bool srGB); extern internal static void DeleteSecondaryPlatformSettings([NotNull] this SpriteAtlas spriteAtlas, string secondaryTextureName); diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs index 71a6d39d3a..8aacc02e7f 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs @@ -15,7 +15,7 @@ namespace UnityEditor.U2D { // SpriteAtlas Importer lets you modify [[SpriteAtlas]] - [HelpURL("https://docs.unity3d.com/2023.2/Documentation/Manual/SpriteAtlasV2.html")] + [HelpURL("https://docs.unity3d.com/6000.0/Documentation/Manual/sprite/atlas/v2/sprite-atlas-v2.html")] [NativeHeader("Editor/Src/2D/SpriteAtlas/SpriteAtlasImporter.h")] public sealed partial class SpriteAtlasImporter : AssetImporter { @@ -24,11 +24,41 @@ public sealed partial class SpriteAtlasImporter : AssetImporter extern public bool includeInBuild { get; set; } extern public SpriteAtlasPackingSettings packingSettings { get; set; } extern public SpriteAtlasTextureSettings textureSettings { get; set; } - extern public void SetPlatformSettings(TextureImporterPlatformSettings src); - extern public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget); + + [NativeName("SetPlatformSettings")] + extern private void SetPlatformSettings_Internal(TextureImporterPlatformSettings src); + public void SetPlatformSettings(TextureImporterPlatformSettings src) + { + src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + SetPlatformSettings_Internal(src); + } + + [NativeName("GetPlatformSettings")] + extern private TextureImporterPlatformSettings GetPlatformSettings_Internal(string buildTarget); + public TextureImporterPlatformSettings GetPlatformSettings(string buildTarget) + { + buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + return GetPlatformSettings_Internal(buildTarget); + } + extern internal TextureFormat GetTextureFormat(BuildTarget target); - extern internal TextureImporterPlatformSettings GetSecondaryPlatformSettings(string buildTarget, string secondaryTextureName); - extern internal void SetSecondaryPlatformSettings(TextureImporterPlatformSettings src, string secondaryTextureName); + + [NativeName("GetSecondaryPlatformSettings")] + extern private TextureImporterPlatformSettings GetSecondaryPlatformSettings_Internal(string buildTarget, string secondaryTextureName); + internal TextureImporterPlatformSettings GetSecondaryPlatformSettings(string buildTarget, string secondaryTextureName) + { + buildTarget = TextureImporter.GetTexturePlatformSerializationName(buildTarget); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + return GetSecondaryPlatformSettings_Internal(buildTarget, secondaryTextureName); + } + + [NativeName("SetSecondaryPlatformSettings")] + extern private void SetSecondaryPlatformSettings_Internal(TextureImporterPlatformSettings src, string secondaryTextureName); + internal void SetSecondaryPlatformSettings(TextureImporterPlatformSettings src, string secondaryTextureName) + { + src.name = TextureImporter.GetTexturePlatformSerializationName(src.name); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + SetSecondaryPlatformSettings_Internal(src, secondaryTextureName); + } + extern internal bool GetSecondaryColorSpace(string secondaryTextureName); extern internal void SetSecondaryColorSpace(string secondaryTextureName, bool srGB); extern internal void DeleteSecondaryPlatformSettings(string secondaryTextureName); diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs index 2251994103..b19491450f 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs @@ -284,6 +284,8 @@ private SerializedObject GetSerializedAssetObject() public override void OnEnable() { base.OnEnable(); + if (!AreImporterTargetsValid()) // asset gone: base already logged and bailed + return; m_FilterMode = serializedObject.FindProperty("m_TextureSettings.filterMode"); m_AnisoLevel = serializedObject.FindProperty("m_TextureSettings.anisoLevel"); diff --git a/Editor/Mono/AI/EditorAIAssistantAnalytics.cs b/Editor/Mono/AI/EditorAIAssistantAnalytics.cs new file mode 100644 index 0000000000..74830a376d --- /dev/null +++ b/Editor/Mono/AI/EditorAIAssistantAnalytics.cs @@ -0,0 +1,57 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Analytics; + +namespace UnityEditor.Toolbars +{ + enum UITriggerLocalEventSubType + { + AIDropdownOpened, + AIInstallAccepted, + } + + internal static class EditorAIAssistantAnalytics + { + [Serializable] + class UITriggerLocalEventData : IAnalytic.IData + { + public UITriggerLocalEventData(UITriggerLocalEventSubType subType) => SubType = subType.ToString(); + + public string SubType; + } + + [AnalyticInfo(eventName: "AIAssistantUITriggerLocalEvent", vendorKey: "unity.ai.assistant")] + class UITriggerLocalEvent : IAnalytic + { + readonly UITriggerLocalEventData m_Data; + + public UITriggerLocalEvent(UITriggerLocalEventData data) => m_Data = data; + + public bool TryGatherData(out IAnalytic.IData data, out Exception error) + { + error = null; + data = m_Data; + return true; + } + } + + static void ReportUITriggerLocalEvent(UITriggerLocalEventData data) + { + if (EditorAnalytics.enabled) + EditorAnalytics.SendAnalytic(new UITriggerLocalEvent(data)); + } + + internal static void ReportAIDropdownOpenedEvent() + { + ReportUITriggerLocalEvent(new UITriggerLocalEventData(UITriggerLocalEventSubType.AIDropdownOpened)); + } + + internal static void ReportAIInstallAcceptedEvent() + { + ReportUITriggerLocalEvent(new UITriggerLocalEventData(UITriggerLocalEventSubType.AIInstallAccepted)); + } + } +} diff --git a/Editor/Mono/Animation/AnimationMode.bindings.cs b/Editor/Mono/Animation/AnimationMode.bindings.cs index e2ace069ce..507d04aaab 100644 --- a/Editor/Mono/Animation/AnimationMode.bindings.cs +++ b/Editor/Mono/Animation/AnimationMode.bindings.cs @@ -39,6 +39,10 @@ public class AnimationMode static internal event Action onAnimationRecordingStart; static internal event Action onAnimationRecordingStop; + static internal event Action onAnimationPlaybackStart; + static internal event Action onAnimationPlaybackStop; + static internal event Action onAnimationSampleEnd; + static internal event Action onAnimationModeStop; static private PrefColor s_AnimatedPropertyColor = new PrefColor("Animation/Property Animated", 0.82f, 0.97f, 1.00f, 1.00f, 0.54f, 0.85f, 1.00f, 1.00f); static private PrefColor s_RecordedPropertyColor = new PrefColor("Animation/Property Recorded", 1.00f, 0.60f, 0.60f, 1.00f, 1.00f, 0.50f, 0.50f, 1.00f); @@ -66,12 +70,16 @@ static private AnimationModeDriver DummyDriver() public static void StopAnimationMode() { Internal_StopAnimationMode(DummyDriver()); + + onAnimationModeStop?.Invoke(); } // Stops animation mode, as used by the animation editor. public static void StopAnimationMode(AnimationModeDriver driver) { Internal_StopAnimationMode(driver); + + onAnimationModeStop?.Invoke(); } // Returns true if the editor is currently in animation mode. @@ -102,6 +110,8 @@ public static void StartAnimationMode(AnimationModeDriver driver) internal static void StopAnimationPlaybackMode() { s_InAnimationPlaybackMode = false; + + onAnimationPlaybackStop?.Invoke(); } // Returns true if the editor is currently in animation playback mode. @@ -114,6 +124,7 @@ internal static bool InAnimationPlaybackMode() internal static void StartAnimationPlaybackMode() { s_InAnimationPlaybackMode = true; + onAnimationPlaybackStart?.Invoke(); } internal static void StopAnimationRecording() @@ -140,6 +151,18 @@ internal static void StartCandidateRecording(AnimationModeDriver driver) Internal_StartCandidateRecording(driver); } + public static void BeginSampling() + { + Internal_BeginSampling(); + } + + public static void EndSampling() + { + Internal_EndSampling(); + + onAnimationSampleEnd?.Invoke(); + } + [NativeThrows] extern internal static void AddCandidate(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride); @@ -150,12 +173,6 @@ internal static void StartCandidateRecording(AnimationModeDriver driver) extern internal static bool IsRecordingCandidates(); - [NativeThrows] - extern public static void BeginSampling(); - - [NativeThrows] - extern public static void EndSampling(); - [NativeThrows] extern public static void SampleAnimationClip([NotNull] GameObject gameObject, [NotNull] AnimationClip clip, float time); @@ -198,6 +215,12 @@ internal static void StartCandidateRecording(AnimationModeDriver driver) // Return editor curve bindings for animator hierarhcy that need to be snapshot for animation mode. extern internal static EditorCurveBinding[] GetAnimatorBindings([NotNull] GameObject root); + [NativeThrows] + extern private static void Internal_BeginSampling(); + + [NativeThrows] + extern private static void Internal_EndSampling(); + extern private static void Internal_StartAnimationMode(Object driver); extern private static void Internal_StopAnimationMode(Object driver); diff --git a/Editor/Mono/Animation/AnimationUtility.bindings.cs b/Editor/Mono/Animation/AnimationUtility.bindings.cs index 2300fb495c..28e6a2a34b 100644 --- a/Editor/Mono/Animation/AnimationUtility.bindings.cs +++ b/Editor/Mono/Animation/AnimationUtility.bindings.cs @@ -130,7 +130,12 @@ public static AnimationClip[] GetAnimationClips(GameObject gameObject) var extraClips = new List(); clipSources[i].GetAnimationClips(extraClips); - allClips.AddRange(extraClips); + allClips.Capacity = allClips.Count + extraClips.Count; + foreach (var clip in extraClips) + { + if (clip != null) + allClips.Add(clip); + } } return allClips.ToArray(); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs index 7aa757d3d1..3722967fa4 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs @@ -207,8 +207,8 @@ public void OnAnimEditorGUI(EditorWindow parent, Rect position) GUILayout.BeginVertical(); // First row of controls - GUILayout.BeginHorizontal(AnimationWindowStyles.animPlayToolBar); - PlayControlsOnGUI(); + Rect playControlsRect = EditorGUILayout.BeginHorizontal(AnimationWindowStyles.animPlayToolBar); + PlayControlsOnGUI(playControlsRect); GUILayout.EndHorizontal(); // Second row of controls @@ -788,8 +788,14 @@ private void AddKeyframeButtonOnGUI() } } - private void PlayControlsOnGUI() + private void PlayControlsOnGUI(Rect playControlsRect) { + // Remove keyfocus when clicking within control to ensure play control shortcuts are received (UUM-113412) + if (Event.current.type == EventType.MouseDown && playControlsRect.Contains(Event.current.mousePosition)) + { + GUIUtility.keyboardControl = 0; + } + using (new EditorGUI.DisabledScope(!m_State.canPreview)) { PreviewButtonOnGUI(); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs index bd82bca45e..3f9b76cee8 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs @@ -214,6 +214,8 @@ void OnEnable() OnSelectionChange(); Undo.undoRedoEvent += UndoRedoPerformed; + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + AssemblyReloadEvents.beforeAssemblyReload += PurgeSelection; } void OnDisable() @@ -222,6 +224,8 @@ void OnDisable() m_AnimEditor.OnDisable(); Undo.undoRedoEvent -= UndoRedoPerformed; + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; + AssemblyReloadEvents.beforeAssemblyReload -= PurgeSelection; } void OnDestroy() @@ -477,6 +481,48 @@ private void UndoRedoPerformed(in UndoRedoInfo info) Repaint(); } + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.ExitingEditMode) + { + // Purge selection before domain reload to prevent stale GameObject references + PurgeSelection(); + } + else + { + // Purge selection before domain reload on ExitingPlayMode + if (state == PlayModeStateChange.ExitingPlayMode) + { + PurgeSelection(); + } + + if (state == PlayModeStateChange.EnteredEditMode) + { + // Reload selection when exiting play mode + OnSelectionChange(); + } + + if (state == PlayModeStateChange.EnteredPlayMode) + { + // Reload selection when entering play mode + OnSelectionChange(); + } + } + } + + private void PurgeSelection() + { + // Clear selection to prevent stale GameObject references during domain reload. + // Note: Dispose() will also stop preview by disposing the controller. + // This matches the behavior during assembly reload (script compilation). + if (state != null) + { + state.linkedWithSequencer = false; + state.overrideControlInterface = null; + state.selection = null; + } + } + public void AddItemsToMenu(GenericMenu menu) { m_LockTracker.AddItemsToMenu(menu, m_AnimEditor.stateDisabled); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs index b0b6991af4..27d95861ab 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs @@ -150,7 +150,6 @@ private AnimationClip DoClipPopup(AnimationClip clip, GUIStyle style) if (evt.button == 0 && position.Contains(evt.mousePosition)) { DisplayClipMenu(position, controlID, clip); - GUIUtility.keyboardControl = controlID; evt.Use(); } break; diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs index bbb79c3da4..f0eb5bccbf 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs @@ -129,18 +129,15 @@ private static bool HasFlag(ResampleFlags flags, ResampleFlags flag) private AnimationClipPlayable m_CandidateClipPlayable; private AnimationClipPlayable m_DefaultPosePlayable; private bool m_UsesPostProcessComponents = false; - HashSet m_ObjectsModifiedDuringAnimationMode = new HashSet(); private static ProfilerMarker s_ResampleAnimationMarker = new ProfilerMarker("AnimationWindowControl.ResampleAnimation"); public void OnEnable() { - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } public void OnDisable() { - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; } public void OnCreate(AnimationWindow animationWindow, Component component) @@ -163,15 +160,6 @@ public void OnSelectionChanged() StopPreview(); } - void OnPlayModeStateChanged(PlayModeStateChange state) - { - if (state == PlayModeStateChange.ExitingPlayMode || - state == PlayModeStateChange.ExitingEditMode) - { - StopPreview(); - } - } - public float time { get => m_Time.time; @@ -597,7 +585,7 @@ private void ResampleAnimation(ResampleFlags flags) if (state.activeAnimationClip != null) { var animationPlayer = state.activeAnimationPlayer; - bool usePlayableGraph = animationPlayer is Animator; + bool usePlayableGraph = animationPlayer is Animator && !state.activeAnimationClip.legacy; if (usePlayableGraph) { @@ -717,42 +705,30 @@ private bool AllowRecordingPrefabPropertyOverridesFor(UnityEngine.Object compone if (componentOrGameObject == null) throw new ArgumentNullException(nameof(componentOrGameObject)); - GameObject inputGameObject = null; - if (componentOrGameObject is Component) - { - inputGameObject = ((Component)componentOrGameObject).gameObject; - } - else if (componentOrGameObject is GameObject) - { - inputGameObject = (GameObject)componentOrGameObject; - } - else - { + if (componentOrGameObject is not Component && componentOrGameObject is not GameObject) return true; - } var rootOfAnimation = state.activeRootGameObject; if (rootOfAnimation == null) return true; - // If the input object is a child of the current root of animation then disallow recording of prefab property overrides - // since the input object is currently being setup for animation recording - return inputGameObject.transform.IsChildOf(rootOfAnimation.transform) == false; + return false; } void OnExitingAnimationMode() { Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; PrefabUtility.allowRecordingPrefabPropertyOverridesFor -= AllowRecordingPrefabPropertyOverridesFor; + } - // Ensures Prefab instance overrides are recorded for properties that was changed while in AnimationMode - foreach (var obj in m_ObjectsModifiedDuringAnimationMode) + void RecordPropertyOverridesForNonAnimatedProperties(UndoPropertyModification[] modifications) + { + PrefabUtility.allowRecordingPrefabPropertyOverridesFor -= AllowRecordingPrefabPropertyOverridesFor; + foreach (var mod in modifications) { - if (obj != null) - EditorUtility.SetDirty(obj); + PrefabUtility.RecordPrefabInstancePropertyModifications(mod.currentValue.target); } - - m_ObjectsModifiedDuringAnimationMode.Clear(); + PrefabUtility.allowRecordingPrefabPropertyOverridesFor += AllowRecordingPrefabPropertyOverridesFor; } private UndoPropertyModification[] PostprocessAnimationRecordingModifications(UndoPropertyModification[] modifications) @@ -769,17 +745,15 @@ private UndoPropertyModification[] PostprocessAnimationRecordingModifications(Un else if (previewing) modifications = RegisterCandidates(modifications); + // Fix for UUM-61742: Unrecorded Prefab overloads should be recorded immediately + RecordPropertyOverridesForNonAnimatedProperties(modifications); + RefreshDisplayNamesOnArrayTopologicalChange(modifications); // Only resample when playable graph has been customized with post process nodes. if (m_UsesPostProcessComponents) ResampleAnimation(ResampleFlags.None); - foreach (var mod in modifications) - { - m_ObjectsModifiedDuringAnimationMode.Add(mod.currentValue.target); - } - return modifications; } diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs index 4b3cce3606..92acd0cfa6 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs @@ -55,11 +55,13 @@ public AnimationEventEditorState() } } - internal class AnimationWindowEvent : ScriptableObject + [HelpURL("script-AnimationWindowEvent")] + class AnimationWindowEvent : ScriptableObject { public GameObject root; public AnimationClip clip; - public AnimationClipInfoProperties clipInfo; + // Only used within AnimationClipEditor. + [NonSerialized] public AnimationClipInfoProperties clipInfo; public int eventIndex; static public AnimationWindowEvent CreateAndEdit(GameObject root, AnimationClip clip, float time) diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs index 2147351f6a..634f44d4e2 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs @@ -44,6 +44,7 @@ internal class AnimationWindowHierarchy // Animation window shared state private AnimationWindowState m_State; private TreeViewController m_TreeView; + private AnimationWindowHierarchyGUI m_HierarchyGUI; public Vector2 GetContentSize() { @@ -65,6 +66,7 @@ public void OnGUI(Rect position) { m_TreeView.OnEvent(); m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard)); + m_HierarchyGUI.ReclaimPendingFieldFocus(); } public void Init(EditorWindow owner, Rect rect) @@ -74,9 +76,10 @@ public void Init(EditorWindow owner, Rect rect) m_TreeView = new TreeViewController(owner, m_State.hierarchyState); m_State.hierarchyData = new AnimationWindowHierarchyDataSource(m_TreeView, m_State); + m_HierarchyGUI = new AnimationWindowHierarchyGUI(m_TreeView, m_State); m_TreeView.Init(rect, m_State.hierarchyData, - new AnimationWindowHierarchyGUI(m_TreeView, m_State), + m_HierarchyGUI, null ); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs index 1154cf213e..d7f6d4f641 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs @@ -30,6 +30,9 @@ internal class AnimationWindowHierarchyGUI : TreeViewGUI private int[] m_HierarchyItemValueControlIDs; private int[] m_HierarchyItemButtonControlIDs; + private bool m_NeedsToReclaimFieldFocus; + private int m_FieldToReclaimFocus; + private const float k_RowRightOffset = 10; private const float k_ValueFieldDragWidth = 15; private const float k_ValueFieldWidth = 80; @@ -280,15 +283,15 @@ private void DoIconAndName(Rect rect, AnimationWindowHierarchyNode node, bool se nodePrefix = string.IsNullOrEmpty(gameObjectName) ? "" : gameObjectName + " : "; } - Styles.content = new GUIContent(nodePrefix + node.displayName + warningText, GetIconForItem(node), tooltipText); + Styles.content = new GUIContent(nodePrefix + node.displayName + warningText, GetEffectiveIcon(node, selected, focused), tooltipText); - textColor = EditorGUIUtility.isProSkin ? Color.gray * 1.35f : Color.black; + textColor = EditorStyles.label.normal.textColor; } else { - Styles.content = new GUIContent(node.displayName + warningText, GetIconForItem(node), tooltipText); + Styles.content = new GUIContent(node.displayName + warningText, GetEffectiveIcon(node, selected, focused), tooltipText); - textColor = EditorGUIUtility.isProSkin ? Color.gray : m_LightSkinPropertyTextColor; + textColor = EditorStyles.label.normal.textColor; var phantomColor = selected ? m_PhantomCurveColor * k_SelectedPhantomCurveColorMultiplier : m_PhantomCurveColor; textColor = isPhantom ? phantomColor : textColor; @@ -352,11 +355,12 @@ private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row) && Event.current.type == EventType.KeyDown && (Event.current.character == '\n' || (int)Event.current.character == 3)); - // Force back keyboard focus to float field editor when editing it. - // TreeView forces keyboard focus on itself at mouse down and we lose focus here. + // Force back keyboard focus to float field editor when editing it since the TreeView forces keyboard focus on itself at mouse down. + // The focus will be reclaimed after the TreeViewController.OnGUI call. if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition)) { - GUIUtility.keyboardControl = id; + m_NeedsToReclaimFieldFocus = true; + m_FieldToReclaimFocus = id; } if (curve.isDiscreteCurve) @@ -421,6 +425,15 @@ private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row) } } + internal void ReclaimPendingFieldFocus() + { + if (m_NeedsToReclaimFieldFocus) + { + GUIUtility.keyboardControl = m_FieldToReclaimFocus; + m_NeedsToReclaimFieldFocus = false; + } + } + private bool DoTreeViewButton(int id, Rect position, GUIContent content, GUIStyle style) { Event evt = Event.current; diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs index d0c4120b18..4171930801 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs @@ -328,18 +328,10 @@ public void ForceRefresh() refresh = RefreshType.Everything; } - private void PurgeSelection() - { - linkedWithSequencer = false; - m_OverrideControlInterface = null; - m_Selection = null; - } - public void OnEnable() { AnimationUtility.onCurveWasModified += CurveWasModified; Undo.undoRedoEvent += UndoRedoPerformed; - AssemblyReloadEvents.beforeAssemblyReload += PurgeSelection; // NoOps... onStartLiveEdit += () => {}; @@ -360,7 +352,6 @@ public void OnDisable() { AnimationUtility.onCurveWasModified -= CurveWasModified; Undo.undoRedoEvent -= UndoRedoPerformed; - AssemblyReloadEvents.beforeAssemblyReload -= PurgeSelection; m_ControlInterface.OnDisable(); previewing = false; @@ -697,7 +688,7 @@ void RebuildAllCurvesCacheIfNecessary() m_AllCurvesCache.Clear(); var animationClip = activeAnimationClip; - if (animationClip == null) + if (animationClip == null || (!selection.animationIsEditable && !showReadOnly)) return; EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(animationClip); diff --git a/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs b/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs index 05000b27e2..6678280c1d 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs @@ -29,7 +29,10 @@ public static object GetCurrentValue(AnimationWindowState state, EditorCurveBind // Otherwise, evaluate AnimationWindowCurve at current time. public static object GetCurrentValue(AnimationWindowState state, AnimationWindowCurve curve) { - if (state.previewing && curve.rootGameObject != null) + // UUM-66112 - state.linkedWithSequencer - Padding for issue in Timeline where muscle + // values are not updated in the editor when previewing in the Animation Window. + // Fallback to curve values. + if (state.previewing && curve.rootGameObject != null && !state.linkedWithSequencer) { return GetCurrentValue(state, curve.binding); } diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs index 86e23e41ff..afc8c86d47 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs @@ -30,12 +30,13 @@ public enum NormalizationMode } //const int kToolbarHeight = 17; - const int kPresetsHeight = 46; + const int kPresetsHeight = 50; static CurveEditorWindow s_SharedCurveEditor; internal CurveEditor m_CurveEditor; + Vector2 m_PresetScrollPosition; AnimationCurve m_Curve; Color m_Color; @@ -469,20 +470,38 @@ void OnGUI() m_CurveEditor.OnGUI(); // Preset swatch area - GUI.Box(new Rect(0, position.height - kPresetsHeight, position.width, kPresetsHeight), "", ms_Styles.curveSwatchArea); + var presetRect = new Rect(0, position.height - kPresetsHeight, position.width, kPresetsHeight); + GUI.Box(presetRect, "", ms_Styles.curveSwatchArea); + Color curveColor = m_Color; curveColor.a *= 0.6f; - const float margin = 45f; const float width = 40f; const float height = 25f; - float yPos = position.height - kPresetsHeight + (kPresetsHeight - height) * 0.5f; + const float spaceBetweenSwatches = 5f; + const float presetDropdownSize = 16f; + const float horizontalScrollbarHeight = 15f; + const float presetDropdownCenteringOffset = 2f; + float yPos = (kPresetsHeight - height) * 0.5f; InitCurvePresets(); CurvePresetLibrary curveLibrary = m_CurvePresets.GetPresetLibraryEditor().GetCurrentLib(); if (curveLibrary != null) { - for (int i = 0; i < curveLibrary.Count(); i++) + var numPresets = curveLibrary.Count(); + var presetDropDownRect = new Rect(spaceBetweenSwatches, yPos + presetDropdownCenteringOffset, presetDropdownSize, presetDropdownSize); + Rect contentRect = new Rect(0, 0, numPresets * (width + spaceBetweenSwatches) + presetDropDownRect.xMax, presetRect.height - horizontalScrollbarHeight); + m_PresetScrollPosition = GUI.BeginScrollView( + presetRect, // Rectangle of the visible area + m_PresetScrollPosition, // Current scroll position + contentRect, // Rectangle containing all content + false, // Always show horizontal scrollbar + false // Always show vertical scrollbar + ); + + PresetDropDown(presetDropDownRect); + + Rect swatchRect = new Rect(presetDropDownRect.xMax + spaceBetweenSwatches, yPos, width, height); + for (int i = 0; i < numPresets; i++) { - Rect swatchRect = new Rect(margin + (width + 5f) * i, yPos, width, height); m_GUIContent.tooltip = curveLibrary.GetName(i); if (GUI.Button(swatchRect, m_GUIContent, ms_Styles.curveSwatch)) { @@ -496,14 +515,11 @@ void OnGUI() if (Event.current.type == EventType.Repaint) curveLibrary.Draw(swatchRect, i); - if (swatchRect.xMax > position.width - 2 * margin) - break; + swatchRect.x += width + spaceBetweenSwatches; } + GUI.EndScrollView(); } - Rect presetDropDownButtonRect = new Rect(margin - 20f, yPos + 5f, 20, 20); - PresetDropDown(presetDropDownButtonRect); - // For adding default preset curves //if (EditorGUI.DropdownButton(new Rect (position.width -26, yPos, 20, 20), GUIContent.none, FocusType.Passive, "OL Plus")) // AddDefaultPresetsToCurrentLib (); diff --git a/Editor/Mono/Animation/StateMachine.cs b/Editor/Mono/Animation/StateMachine.cs index f438f78a37..7a0a5c021d 100644 --- a/Editor/Mono/Animation/StateMachine.cs +++ b/Editor/Mono/Animation/StateMachine.cs @@ -100,11 +100,12 @@ public void RemoveCondition(AnimatorCondition condition) } } - + [HelpURL("StateMachineTransitions")] internal class AnimatorDefaultTransition : ScriptableObject { } + [HelpURL("class-State")] public partial class AnimatorState : Object { private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); @@ -242,6 +243,7 @@ public int uniqueNameHash } } + [HelpURL("NestedStateMachines")] public partial class AnimatorStateMachine : Object { private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); diff --git a/Editor/Mono/Annotation/AnnotationWindow.cs b/Editor/Mono/Annotation/AnnotationWindow.cs index 3ae0d13aeb..f7568e6a9f 100644 --- a/Editor/Mono/Annotation/AnnotationWindow.cs +++ b/Editor/Mono/Annotation/AnnotationWindow.cs @@ -171,7 +171,7 @@ internal static bool ShowAtPosition(Rect buttonRect, bool isGameView) { // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; + bool justClosed = nowMilliSeconds < s_LastClosedTime + 400; if (!justClosed) { Event.current.Use(); diff --git a/Editor/Mono/Annotation/LayerVisibilityWindow.cs b/Editor/Mono/Annotation/LayerVisibilityWindow.cs index adbcf89971..c65667c8a7 100644 --- a/Editor/Mono/Annotation/LayerVisibilityWindow.cs +++ b/Editor/Mono/Annotation/LayerVisibilityWindow.cs @@ -86,7 +86,7 @@ internal static bool ShowAtPosition(Rect buttonRect) { // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; + bool justClosed = nowMilliSeconds < s_LastClosedTime + 400; if (!justClosed) { Event.current.Use(); diff --git a/Editor/Mono/Annotation/SceneRenderModeWindow.cs b/Editor/Mono/Annotation/SceneRenderModeWindow.cs index e13ab71850..a455e6fcfd 100644 --- a/Editor/Mono/Annotation/SceneRenderModeWindow.cs +++ b/Editor/Mono/Annotation/SceneRenderModeWindow.cs @@ -138,7 +138,7 @@ static class Styles new SceneView.CameraMode(DrawCameraMode.AlphaChannel, "Alpha Channel", kMiscellaneous), new SceneView.CameraMode(DrawCameraMode.Overdraw, "Overdraw", kMiscellaneous), new SceneView.CameraMode(DrawCameraMode.Mipmaps, "Mipmaps", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.TextureStreaming, "Texture Streaming", kMiscellaneous), + new SceneView.CameraMode(DrawCameraMode.TextureStreaming, "Texture Mipmap Streaming", kMiscellaneous), new SceneView.CameraMode(DrawCameraMode.SpriteMask, "Sprite Mask", kMiscellaneous), new SceneView.CameraMode(DrawCameraMode.ValidateAlbedo, "Validate Albedo", kMiscellaneous), new SceneView.CameraMode(DrawCameraMode.ValidateMetalSpecular, "Validate Metal Specular", kMiscellaneous), @@ -146,6 +146,18 @@ static class Styles } + // Default CameraMode should be DrawCameraMode.GIContributorsReceivers + internal static SceneView.CameraMode defaultCameraMode + { + get + { + var mode = Styles.sBuiltinCameraModes [3]; + if(mode.drawMode != DrawCameraMode.GIContributorsReceivers) + Debug.LogError("Default Draw Camera mode should be set to DrawCameraMode.GIContributorsReceivers."); + return mode; + } + } + private Dictionary foldoutStates = new Dictionary(); private float windowHeight @@ -163,7 +175,7 @@ private float windowHeight modes = Styles.sBuiltinCameraModes.Count(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show) + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeSupported(mode) && mode.show); - return UpdatedHeight(headers, modes, GraphicsSettings.renderPipelineAsset != null); + return UpdatedHeight(headers, modes, GraphicsSettings.isScriptableRenderPipelineEnabled); } } @@ -295,7 +307,7 @@ private void Draw(float listElementWidth) } } - if (GraphicsSettings.renderPipelineAsset != null) + if (GraphicsSettings.isScriptableRenderPipelineEnabled) { DrawSeparator(ref drawPos); DrawRenderingDebuggerShortCut(drawPos); @@ -339,7 +351,7 @@ private float RecalculateWindowHeight() } } - return UpdatedHeight(headers, modes, GraphicsSettings.renderPipelineAsset != null); + return UpdatedHeight(headers, modes, GraphicsSettings.isScriptableRenderPipelineEnabled); } private float UpdatedHeight(int headers, int modes, bool isSRP) diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 52cfe0e7b3..46f5a12e56 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -19,22 +19,21 @@ [assembly: InternalsVisibleTo("Unity.Audio.Tests")] [assembly: InternalsVisibleTo("Unity.Burst")] [assembly: InternalsVisibleTo("Unity.Burst.Editor")] -[assembly: InternalsVisibleTo("Unity.Cloud.Collaborate.Editor")] [assembly: InternalsVisibleTo("Unity.CollabProxy.Editor")] -[assembly: InternalsVisibleTo("Unity.CollabProxy.EditorTests")] -[assembly: InternalsVisibleTo("Unity.CollabProxy.UI")] -[assembly: InternalsVisibleTo("Unity.CollabProxy.UI.Tests")] -[assembly: InternalsVisibleTo("Unity.CollabProxy.Client")] -[assembly: InternalsVisibleTo("Unity.CollabProxy.Client.Tests")] +[assembly: InternalsVisibleTo("Unity.PlasticSCM.Editor")] +[assembly: InternalsVisibleTo("Unity.PlasticSCM.EditorTests")] [assembly: InternalsVisibleTo("UnityEditor.Advertisements")] [assembly: InternalsVisibleTo("Unity.PackageManager")] [assembly: InternalsVisibleTo("Unity.PackageManagerStandalone")] [assembly: InternalsVisibleTo("Unity.AndroidBuildPipeline")] [assembly: InternalsVisibleTo("Unity.Automation")] +[assembly: InternalsVisibleTo("Unity.IntegrationTests.Android")] +[assembly: InternalsVisibleTo("Unity.IntegrationTests.Android.CommonUtils")] [assembly: InternalsVisibleTo("UnityEngine.Common")] [assembly: InternalsVisibleTo("Unity.PureCSharpTests")] [assembly: InternalsVisibleTo("Unity.IntegrationTests")] [assembly: InternalsVisibleTo("Unity.DeploymentTests.Services")] +[assembly: InternalsVisibleTo("Unity.IntegrationTests.EditorDeeplink")] [assembly: InternalsVisibleTo("Unity.IntegrationTests.ExternalVersionControl")] [assembly: InternalsVisibleTo("Unity.IntegrationTests.UnityAnalytics")] [assembly: InternalsVisibleTo("Unity.PerformanceIntegrationTests")] @@ -45,6 +44,7 @@ [assembly: InternalsVisibleTo("UnityEditor.Graphs")] [assembly: InternalsVisibleTo("UnityEditor.UWP.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.iOS.Extensions.Common")] +[assembly: InternalsVisibleTo("UnityEditor.Apple.Extensions.Common")] [assembly: InternalsVisibleTo("UnityEditor.iOS.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.VisionOS.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.AppleTV.Extensions")] @@ -53,12 +53,15 @@ [assembly: InternalsVisibleTo("UnityEditor.PS4.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.PS5.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.Switch.Extensions")] +[assembly: InternalsVisibleTo("UnityEditor.Switch2.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.WebGL.Extensions")] +[assembly: InternalsVisibleTo("Unity.Automation.Players.WebGL")] [assembly: InternalsVisibleTo("Unity.WebGL.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.LinuxStandalone.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.CloudRendering.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.EmbeddedLinux.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.QNX.Extensions")] +[assembly: InternalsVisibleTo("UnityEditor.Kepler.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.WindowsStandalone.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.OSXStandalone.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.Lumin.Extensions")] @@ -71,7 +74,6 @@ [assembly: InternalsVisibleTo("UnityEditor.Analytics")] [assembly: InternalsVisibleTo("UnityEditor.Purchasing")] [assembly: InternalsVisibleTo("UnityEditor.Lumin")] -[assembly: InternalsVisibleTo("UnityEditor.Switch.Extensions")] [assembly: InternalsVisibleTo("UnityEditor.EditorTestsRunner")] [assembly: InternalsVisibleTo("UnityEditor.TestRunner")] [assembly: InternalsVisibleTo("UnityEditor.TestRunner.Tests")] @@ -122,7 +124,7 @@ [assembly: InternalsVisibleTo("Unity.XR.Remoting.Editor")] [assembly: InternalsVisibleTo("UnityEngine.Common")] [assembly: InternalsVisibleTo("Unity.UI.Builder.Editor")] -[assembly: InternalsVisibleTo("UnityEditor.UIElements.Tests.Tests")] // for UI Test Framework +[assembly: InternalsVisibleTo("Unity.UI.TestFramework.Editor.Tests")] // for UI Test Framework [assembly: InternalsVisibleTo("UnityEditor.UIBuilderModule")] [assembly: InternalsVisibleTo("Unity.UI.Builder.EditorTests")] [assembly: InternalsVisibleTo("Unity.GraphViewTestUtilities.Editor")] @@ -140,6 +142,7 @@ [assembly: InternalsVisibleTo("Unity.Testing.VisualEffectGraph.EditorTests")] [assembly: InternalsVisibleTo("Unity.VisualEffectGraph.EditorTests")] [assembly: InternalsVisibleTo("Unity.RenderPipelines.Multiple_SRP.EditorTests")] +[assembly: InternalsVisibleTo("Unity.ShaderGraph.Editor")] [assembly: InternalsVisibleTo("Unity.SceneTemplate.Editor")] [assembly: InternalsVisibleTo("com.unity.purchasing.udp.Editor")] @@ -149,6 +152,12 @@ [assembly: InternalsVisibleTo("Unity.Entities.Build")] +[assembly: InternalsVisibleTo("Unity.Muse.Common.Bridge")] +[assembly: InternalsVisibleTo("Unity.Muse.Chat.Bridge")] + +[assembly: InternalsVisibleTo("Unity.Multiplayer.Playmode.Editor.Bridge")] +[assembly: InternalsVisibleTo("Unity.DedicatedServer.Editor.Bridge")] + [assembly: InternalsVisibleTo("Unity.Scenes")] // This should move with the AnimationWindow to a module at some point @@ -157,6 +166,7 @@ [assembly: InternalsVisibleTo("UnityEditor.Modules.Physics.Tests")] [assembly: InternalsVisibleTo("UnityEditor.Switch.Tests")] +[assembly: InternalsVisibleTo("UnityEditor.Switch2.Tests")] [assembly: InternalsVisibleTo("UnityEditor.BuildProfileModule.Tests")] diff --git a/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs b/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs index 1597fff5e5..0c8d68f847 100644 --- a/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs +++ b/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs @@ -19,7 +19,11 @@ public static string[] FindAssets(string filter) return FindAssets(filter, null); } - public static string[] FindAssets(string filter, string[] searchInFolders) + public static GUID[] FindAssetGUIDs(string filter) + { + return FindAssetGUIDs(filter, null); + } + private static SearchFilter CreateSearchFilter(string filter, string[] searchInFolders) { var searchFilter = new SearchFilter { searchArea = SearchFilter.SearchArea.AllAssets }; SearchUtility.ParseSearchString(filter, searchFilter); @@ -28,15 +32,26 @@ public static string[] FindAssets(string filter, string[] searchInFolders) searchFilter.folders = searchInFolders; searchFilter.searchArea = SearchFilter.SearchArea.SelectedFolders; } - + return searchFilter; + } + public static string[] FindAssets(string filter, string[] searchInFolders) + { + var searchFilter = CreateSearchFilter(filter, searchInFolders); return FindAssets(searchFilter); } - + public static GUID[] FindAssetGUIDs(string filter, string[] searchInFolders) + { + var searchFilter = CreateSearchFilter(filter, searchInFolders); + return FindAssetGUIDs(searchFilter); + } internal static string[] FindAssets(SearchFilter searchFilter) { return FindAllAssets(searchFilter).Select(property => property.guid).Distinct().ToArray(); } - + internal static GUID[] FindAssetGUIDs(SearchFilter searchFilter) + { + return FindAllAssets(searchFilter).Select(property => property.assetGUID).Distinct().ToArray(); + } [VisibleToOtherModules("UnityEditor.UIBuilderModule")] internal static IEnumerable FindAllAssets(SearchFilter searchFilter) { diff --git a/Editor/Mono/AssetModificationProcessor.cs b/Editor/Mono/AssetModificationProcessor.cs index 3c49382af1..1ff4bb026d 100644 --- a/Editor/Mono/AssetModificationProcessor.cs +++ b/Editor/Mono/AssetModificationProcessor.cs @@ -161,6 +161,14 @@ static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSav MethodInfo method = assetModificationProcessorClass.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (method != null) { + if (ContainsNullOrWhiteSpaceString(assetsThatShouldBeSaved)) + { + int originalCount = assetsThatShouldBeSaved.Length; + assetsThatShouldBeSaved = Array.FindAll(assetsThatShouldBeSaved, s => !string.IsNullOrWhiteSpace(s)); + int skippedCount = originalCount - assetsThatShouldBeSaved.Length; + Debug.LogWarning($"OnWillSaveAssets: Skipped {skippedCount} null or empty path(s)."); + } + object[] args = { assetsThatShouldBeSaved }; if (!CheckArguments(args, method)) continue; @@ -610,5 +618,10 @@ internal static bool MakeEditable(string[] paths, string prompt, List ou return true; } + + internal static bool ContainsNullOrWhiteSpaceString(string[] stringArray) + { + return Array.Exists(stringArray, string.IsNullOrWhiteSpace); + } } } diff --git a/Editor/Mono/AssetPipeline/BumpMapSettings.bindings.cs b/Editor/Mono/AssetPipeline/BumpMapSettings.bindings.cs index dd9c4c80b7..d177927130 100644 --- a/Editor/Mono/AssetPipeline/BumpMapSettings.bindings.cs +++ b/Editor/Mono/AssetPipeline/BumpMapSettings.bindings.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using UnityEngine; using UnityEngine.Bindings; @@ -11,13 +12,12 @@ namespace UnityEditor [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/BumpMapSettings.h")] internal class BumpMapSettings { - public static extern bool silentMode { get; set; } - public static extern void PerformBumpMapCheck([NotNull] Material material); } public static class MaterialEditorExtensions { + [Obsolete("PerformBumpMapCheck is obsolete.", false)] public static void PerformBumpMapCheck(this Material material) { BumpMapSettings.PerformBumpMapCheck(material); diff --git a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Importer.cs b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Importer.cs index 28c853c1ff..eec1335d57 100644 --- a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Importer.cs +++ b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9Importer.cs @@ -21,7 +21,9 @@ namespace UnityEditor.SpeedTree.Importer { - [ScriptedImporter(1, "st9", AllowCaching = true)] + // [2024-09-27] version: 3 + // Fixed code that would lead to m_LODCount vs m_PerLODSettings.arraySize mismatching in GUI + [ScriptedImporter(version: 3, ext: "st9", AllowCaching = true)] public class SpeedTree9Importer : ScriptedImporter { const int SPEEDTREE_9_WIND_VERSION = 1; @@ -30,23 +32,16 @@ public class SpeedTree9Importer : ScriptedImporter internal static class ImporterSettings { internal const string kGameObjectName = "SpeedTree"; - internal const string kHDRPShaderName = "HDRP/Nature/SpeedTree9_HDRP"; - internal const string kURPShaderName = "Universal Render Pipeline/Nature/SpeedTree9_URP"; internal const string kLegacyShaderName = "Nature/SpeedTree9"; internal const string kWindAssetName = "SpeedTreeWind"; - internal const string kSRPDependencyName = "srp/default-pipeline"; + internal const string kSRPDependencyName = "SpeedTree9Importer_DefaultShader"; internal const string kMaterialSettingsDependencyname = "SpeedTree9Importer_MaterialSettings"; - - // In some very specific scenarios, the Shader cannot be found using "Shader.Find" (e.g project upgrade). - // Adding an extra-security is necessary to avoid that, by manually forcing the load of the Shader using - // "AssetDatabase.LoadAssetAtPath". It only happens for SRPs during project upgrades. - internal const string kHDRPShaderPath = "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Nature/SpeedTree9_HDRP.shadergraph"; - internal const string kURPShaderPath = "Packages/com.unity.render-pipelines.universal/Shaders/Nature/SpeedTree9_URP.shadergraph"; + internal const string kIconName = "UnityEditor/SpeedTree9Importer Icon"; } private static class Styles { - internal static readonly Texture2D kIcon = EditorGUIUtility.FindTexture("UnityEditor/SpeedTree9Importer Icon"); + internal static readonly Texture2D kIcon = EditorGUIUtility.FindTexture(ImporterSettings.kIconName); } private struct STMeshGeometry @@ -115,13 +110,18 @@ public STMeshGeometry(int vertexCount, int UVCount, int indexLod) /// public delegate void OnCustomEditorSettings(ref SerializedProperty diffusionProfileAsset, ref SerializedProperty diffusionProfileHash); + [SerializeField] + internal SpeedTreeImporterOutputData m_OutputImporterData; + + private static ulong s_DefaultShaderHash; + private static readonly TimeSpan k_CheckDependencyFrequency = TimeSpan.FromSeconds(5); + private static DateTime s_LastCheck; + // Cache main objects, created during import process. private AssetImportContext m_Context; private SpeedTree9Reader m_Tree; - private SpeedTreeImporterOutputData m_OutputImporterData; private Shader m_Shader; private SpeedTreeWindAsset m_WindAsset; - private STRenderPipeline m_RenderPipeline; // Values cached at the begining of the import process. private bool m_HasFacingData; @@ -155,11 +155,9 @@ public override void OnImportAsset(AssetImportContext ctx) CacheTreeImporterValues(ctx.assetPath); - m_RenderPipeline = GetCurrentRenderPipelineType(); - ctx.DependsOnCustomDependency(ImporterSettings.kSRPDependencyName); - if (!TryGetShaderForCurrentRenderPipeline(m_RenderPipeline, out m_Shader)) + if (!TryGetShaderForCurrentRenderPipeline(out m_Shader)) { ctx.LogImportError("SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset."); return; @@ -214,10 +212,12 @@ public override void OnImportAsset(AssetImportContext ctx) ctx.AddObjectToAsset(m_OutputImporterData.name, m_OutputImporterData); ctx.DependsOnCustomDependency(ImporterSettings.kMaterialSettingsDependencyname); - TriggerAllCabback(); + AddDependencyOnExtractedMaterials(); + + TriggerAllCallbacks(); } - private void TriggerAllCabback() + private void TriggerAllCallbacks() { var allMethods = AttributeHelper.GetMethodsWithAttribute().methodsWithAttributes; foreach (var method in allMethods) @@ -230,10 +230,20 @@ private void TriggerAllCabback() private void CacheTreeImporterValues(string assetPath) { // Variables used a lot are cached, since accessing any Reader array has a non-negligeable cost. + m_LODCount = (uint)m_Tree.Lod.Length; + if(m_LODCount > LODGroupGUI.kLODColors.Length) + { + Debug.LogWarningFormat("Number of LOD meshes in asset ({0}) is larger than the maximum number supported by Unity GUI ({1})." + + "\nImporting only the first {1} LOD meshes." + , m_LODCount, LODGroupGUI.kLODColors.Length); + + // LODGroup GUI won't draw if we're above this limit, so we prevent future assertions here. + m_LODCount = (uint)LODGroupGUI.kLODColors.Length; + } + m_HasFacingData = TreeHasFacingData(); m_HasBranch2Data = m_Tree.Wind.DoBranch2; m_LastLodIsBillboard = m_Tree.BillboardInfo.LastLodIsBillboard; - m_LODCount = (uint)m_Tree.Lod.Length; m_CollisionObjectsCount = (uint)m_Tree.CollisionObjects.Length; WindConfigSDK windCfg = m_Tree.Wind; @@ -261,7 +271,7 @@ internal void RegenerateMaterials() RegenerateAndPopulateExternalMaterials(this.assetPath); - TriggerAllCabback(); + TriggerAllCallbacks(); } finally { @@ -269,6 +279,61 @@ internal void RegenerateMaterials() } } + [InitializeOnLoadMethod] + static void InitializeEditorCallback() + { + EditorApplication.update += DirtyCustomDependencies; + s_DefaultShaderHash = ComputeDefaultShaderHash(); + AssetDatabase.RegisterCustomDependency(ImporterSettings.kSRPDependencyName, new Hash128(s_DefaultShaderHash, 0)); + } + + + static ulong CombineHash(ulong h1, ulong h2) + { + unchecked + { + return h1 ^ h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2); // Similar to c++ boost::hash_combine + } + } + + static ulong ComputeDefaultShaderHash() + { + ulong newDefaultShaderHash = 0UL; + if (GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9) == null) + { + newDefaultShaderHash = 0; + } + else + { + if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9), out var guid, + out long fileId)) + { + newDefaultShaderHash = CombineHash((ulong)guid.GetHashCode(), (ulong)fileId); + } + } + + return newDefaultShaderHash; + } + + static void DirtyCustomDependencies() + { + DateTime now = DateTime.UtcNow; + if (Application.isPlaying || ((now - s_LastCheck) < k_CheckDependencyFrequency)) + { + return; + } + + s_LastCheck = now; + + ulong newDefaultShaderHash = ComputeDefaultShaderHash(); + if (s_DefaultShaderHash != newDefaultShaderHash) + { + s_DefaultShaderHash = newDefaultShaderHash; + AssetDatabase.RegisterCustomDependency(ImporterSettings.kSRPDependencyName, new Hash128(s_DefaultShaderHash, 0)); + AssetDatabase.Refresh(); + } + } + #region Mesh Geometry & Renderers private Mesh CreateMeshAndGeometry(Lod lod, int lodIndex) { @@ -293,17 +358,13 @@ private Mesh CreateMeshAndGeometry(Lod lod, int lodIndex) mesh.SetUVs(0, sTMeshGeometry.uvs[0]); mesh.SetUVs(1, sTMeshGeometry.uvs[1]); - if (!isBillboard) { - if (m_HasBranch2Data || m_HasFacingData) - { - mesh.SetUVs(2, sTMeshGeometry.uvs[2]); - } - if (m_HasBranch2Data && m_HasFacingData) - { - mesh.SetUVs(3, sTMeshGeometry.uvs[3]); - } + // SpeedTree shader expects certain UV2 & UV3 values for leaf facing & wind. + // if we don't claim them here now, tree rendering may break when Unity + // uses UV2 & UV3 and the shader finds unexpected values. + mesh.SetUVs(2, sTMeshGeometry.uvs[2]); // Branch2Pos, Branch2Dir, Branch2Weight, + mesh.SetUVs(3, sTMeshGeometry.uvs[3]); // 2/3 Anchor XYZ, FacingFlag } return mesh; @@ -352,17 +413,12 @@ private void CalculateMeshGeometry(STMeshGeometry sTMeshGeometry, Lod lod, bool STVertex vertex = vertices[i]; sTMeshGeometry.vertices[i].Set( - vertex.Anchor.X + vertex.Offset.X, + vertex.Anchor.X + (vertex.CameraFacing ? -vertex.Offset.X : vertex.Offset.X), vertex.Anchor.Y + vertex.Offset.Y, vertex.Anchor.Z + vertex.Offset.Z); sTMeshGeometry.vertices[i] *= m_MeshSettings.scaleFactor; - if (vertex.CameraFacing) - { - sTMeshGeometry.vertices[i].x = vertex.Anchor.X - vertex.Offset.X; - } - sTMeshGeometry.normals[i].Set(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z); Vector3 vertexTangent = new Vector3(vertex.Tangent.X, vertex.Tangent.Y, vertex.Tangent.Z); @@ -405,23 +461,23 @@ private void CalculateMeshGeometry(STMeshGeometry sTMeshGeometry, Lod lod, bool if (!isBillboard) { - if (m_HasBranch2Data) - { - sTMeshGeometry.uvs[currentUV++][i].Set( - vertex.BranchWind2.X, - vertex.BranchWind2.Y, - vertex.BranchWind2.Z, - 0.0f); - } - - if (m_HasFacingData) - { - sTMeshGeometry.uvs[currentUV++][i].Set( - vertex.Anchor.X * m_MeshSettings.scaleFactor, - vertex.Anchor.Y * m_MeshSettings.scaleFactor, - vertex.Anchor.Z * m_MeshSettings.scaleFactor, - vertex.CameraFacing ? 1.0f : 0.0f); - } + float anchorX = m_HasFacingData ? vertex.Anchor.X * m_MeshSettings.scaleFactor : 0.0f; + float anchorY = m_HasFacingData ? vertex.Anchor.Y * m_MeshSettings.scaleFactor : 0.0f; + float anchorZ = m_HasFacingData ? vertex.Anchor.Z * m_MeshSettings.scaleFactor : 0.0f; + float leafFacingFlag = vertex.CameraFacing ? 1.0f : 0.0f; + + sTMeshGeometry.uvs[currentUV++][i].Set( + m_HasBranch2Data ? vertex.BranchWind2.X : anchorX, + m_HasBranch2Data ? vertex.BranchWind2.Y : anchorY, + m_HasBranch2Data ? vertex.BranchWind2.Z : anchorZ, + m_HasBranch2Data ? 0.0f /*UNUSED*/ : leafFacingFlag); + + bool useUV3 = m_HasBranch2Data && m_HasFacingData; + sTMeshGeometry.uvs[currentUV++][i].Set( + useUV3 ? anchorX : 0.0f, + useUV3 ? anchorY : 0.0f, + useUV3 ? anchorZ : 0.0f, + useUV3 ? leafFacingFlag : 0.0f); } } } @@ -454,15 +510,7 @@ private int CalculateNumUVs(bool isBillboard) int numUVs = 2; if (!isBillboard) { - if (m_HasBranch2Data) - { - numUVs += 1; - } - - if (m_HasFacingData) - { - numUVs += 1; - } + numUVs += 2; // reserve UV2 & UV3 for 3D-geometry to detect leaf facing (VS effect) correctly } return numUVs; } @@ -492,6 +540,7 @@ private void CalculateBillboardAndPerLODSettings() } else if (m_PerLODSettings.Count < m_LODCount) { + m_PerLODSettings.Clear(); for (int i = 0; i < m_LODCount; ++i) { bool isBillboardLOD = m_LastLodIsBillboard && i == m_LODCount - 1; @@ -621,7 +670,7 @@ private void CreateMaterialsForCurrentLOD(STMaterial stMaterial, int lodIndex, b // Explicity regenerate materials, should happen when bumping the material version for example. if (regenerateMaterials) { - extractedMat = CreateMaterial(stMaterial, lodIndex, stMatName, m_PathFromDirectory); + extractedMat = CreateMaterial(stMaterial, lodIndex, extractedMat.name, m_PathFromDirectory); SetMaterialTextureAndColorProperties(stMaterial, extractedMat, lodIndex, m_PathFromDirectory); } @@ -630,10 +679,10 @@ private void CreateMaterialsForCurrentLOD(STMaterial stMaterial, int lodIndex, b RetrieveMaterialSpecialProperties(extractedMat); } - var existedMatIndex = m_OutputImporterData.lodMaterials.materials.FindIndex(m => m.material.name == stMatName); + var existedMatIndex = m_OutputImporterData.lodMaterials.materials.FindIndex(m => m.defaultName == stMatName); if (existedMatIndex == -1) { - m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = extractedMat, exported = true }); + m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = extractedMat, defaultName = stMatName, exported = true }); m_OutputImporterData.lodMaterials.matNameToIndex[stMatName] = m_OutputImporterData.lodMaterials.materials.Count - 1; } else @@ -646,7 +695,7 @@ private void CreateMaterialsForCurrentLOD(STMaterial stMaterial, int lodIndex, b { Material newMat = CreateMaterial(stMaterial, lodIndex, stMatName, m_PathFromDirectory); - m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = newMat, exported = false }); + m_OutputImporterData.lodMaterials.materials.Add(new MaterialInfo { material = newMat, defaultName = stMatName, exported = false }); m_OutputImporterData.lodMaterials.matNameToIndex.Add(stMatName, m_OutputImporterData.lodMaterials.materials.Count - 1); } @@ -675,7 +724,7 @@ private void CreateAssetIdentifiersAndAddMaterialsToContext() } } - m_OutputImporterData.materialsIdentifiers.Add(new AssetIdentifier(matInfo.material.GetType(), matInfo.material.name)); + m_OutputImporterData.materialsIdentifiers.Add(new AssetIdentifier(matInfo.material.GetType(), matInfo.defaultName)); } } @@ -713,9 +762,7 @@ private void RegenerateAndPopulateExternalMaterials(string assetPath) CacheTreeImporterValues(assetPath); - m_RenderPipeline = GetCurrentRenderPipelineType(); - - if (!TryGetShaderForCurrentRenderPipeline(m_RenderPipeline, out m_Shader)) + if (!TryGetShaderForCurrentRenderPipeline(out m_Shader)) { Debug.LogError("SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset."); return; @@ -738,7 +785,7 @@ private void RegenerateAndPopulateExternalMaterials(string assetPath) m_OutputImporterData.materialsIdentifiers.Add(new AssetIdentifier(matInfo.material.GetType(), matInfo.material.name)); // Remap the new material to the importer 'ExternalObjectMap'. - if (TryGetExternalMaterial(matInfo.material.name, out var extractedMat)) + if (TryGetExternalMaterial(matInfo.defaultName, out var extractedMat)) { string newMatPath = AssetDatabase.GetAssetPath(extractedMat); @@ -750,7 +797,7 @@ private void RegenerateAndPopulateExternalMaterials(string assetPath) AssetDatabase.CreateAsset(matInfo.material, newMatPath); } - if (TryGetSourceAssetIdentifierFromName(matInfo.material.name, out var assetIdentifier)) + if (TryGetSourceAssetIdentifierFromName(matInfo.defaultName, out var assetIdentifier)) { AddRemap(assetIdentifier, matInfo.material); } @@ -816,17 +863,17 @@ private bool SetMaterialTexture(Material mat, STMaterial stMaterial, int indexMa { MaterialMap stMatMap = stMaterial.Maps[indexMap]; string mapPath = stMatMap.Path; - if (stMatMap.Used && !string.IsNullOrEmpty(mapPath)) - { - string finalTexturePath = path + mapPath; - Texture2D tex = (m_Context != null) - ? m_Context.GetReferenceToAssetMainObject(finalTexturePath) as Texture2D - : AssetDatabase.LoadAssetAtPath(finalTexturePath, typeof(Texture2D)) as Texture2D; + if (!stMatMap.Used) + return false; + + if (!string.IsNullOrEmpty(mapPath)) + { + Texture2D texture = LoadTexture(mapPath, path); - if (tex != null) + if (texture != null) { - mat.SetTexture(property, tex); + mat.SetTexture(property, texture); return true; } } @@ -835,6 +882,35 @@ private bool SetMaterialTexture(Material mat, STMaterial stMaterial, int indexMa return false; } + private Texture2D LoadTexture(string mapPath, string path) + { + string texturePath = path + mapPath; + + Texture2D texture = (m_Context != null) + ? m_Context.GetReferenceToAssetMainObject(texturePath) as Texture2D + : AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)) as Texture2D; + + if (texture != null) + return texture; + + // Textures are not located near the asset, let's check if they were moved somewhere else. + string mapPathWithoutExtension = Path.GetFileNameWithoutExtension(mapPath); + string[] textureAssets = AssetDatabase.FindAssets(mapPathWithoutExtension); + + if (textureAssets != null && textureAssets.Length > 0) + { + string assetPathFromGUID = AssetDatabase.GUIDToAssetPath(textureAssets[0]); + + texture = (m_Context != null) + ? m_Context.GetReferenceToAssetMainObject(assetPathFromGUID) as Texture2D + : AssetDatabase.LoadAssetAtPath(assetPathFromGUID, typeof(Texture2D)) as Texture2D; + + return texture; + } + + return null; + } + private bool TryGetInstanceIDFromMaterialProperty(Material material, int propertyName, out int id) { if (!material.HasProperty(propertyName)) @@ -966,22 +1042,24 @@ private void SetMaterialOtherProperties(STMaterial stMaterial, Material mat) } mat.SetFloat(MaterialProperties.LeafFacingKwToggleID, m_HasFacingData ? 1.0f : 0.0f); - if (m_RenderPipeline == STRenderPipeline.HDRP) - { + if (mat.HasFloat(MaterialProperties.DoubleSidedToggleID)) mat.SetFloat(MaterialProperties.DoubleSidedToggleID, stMaterial.TwoSided ? 1.0f : 0.0f); + + if (mat.HasFloat(MaterialProperties.DoubleSidedNormalModeID)) mat.SetFloat(MaterialProperties.DoubleSidedNormalModeID, stMaterial.FlipNormalsOnBackside ? 0.0f : 2.0f); + if (mat.HasVector(MaterialProperties.DiffusionProfileAssetID)) mat.SetVector(MaterialProperties.DiffusionProfileAssetID, m_MaterialSettings.diffusionProfileAssetID); + + if (mat.HasFloat(MaterialProperties.DiffusionProfileID)) mat.SetFloat(MaterialProperties.DiffusionProfileID, m_MaterialSettings.diffusionProfileID); - } - else if (m_RenderPipeline == STRenderPipeline.URP) - { + + if (mat.HasFloat(MaterialProperties.BackfaceNormalModeID)) mat.SetFloat(MaterialProperties.BackfaceNormalModeID, stMaterial.FlipNormalsOnBackside ? 0.0f : 2.0f); - } - else // legacy rendering pipeline - { + + if (mat.HasFloat(MaterialProperties.TwoSidedID)) mat.SetFloat(MaterialProperties.TwoSidedID, stMaterial.TwoSided ? 0.0f : 2.0f); // matches cull mode. 0: no cull - } + mat.enableInstancing = true; mat.doubleSidedGI = stMaterial.TwoSided; } @@ -1075,25 +1153,30 @@ internal string GetMaterialFolderPath() return FileUtil.DeleteLastPathNameComponent(assetPath) + "/"; } - internal string GetShaderNameFromPipeline(STRenderPipeline renderPipeline) - { - switch (renderPipeline) - { - case STRenderPipeline.HDRP: - return ImporterSettings.kHDRPShaderName; - case STRenderPipeline.URP: - return ImporterSettings.kURPShaderName; - case STRenderPipeline.Legacy: - default: - return ImporterSettings.kLegacyShaderName; - } - } - internal void SetMaterialsVersionToCurrent() { m_MaterialVersion = SPEEDTREE_9_MATERIAL_VERSION; MarkDirty(); } + + private void AddDependencyOnExtractedMaterials() + { + Dictionary extMap = GetExternalObjectMap(); + + foreach (var entry in extMap) + { + if (entry.Value != null) + { + string matPath = AssetDatabase.GetAssetPath(entry.Value); + + m_Context.DependsOnImportedAsset(matPath); + + // Necessary to avoid the warning "Import of asset setup artifact dependency to but dependency isn't used + // and therefore not registered in the asset database". + AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)); + } + } + } #endregion #region Wind @@ -1177,6 +1260,7 @@ bool RippleHasAllCurvesValid(in WindRipple r) // st9 cfg.branch1StretchLimit = wind.Branch1StretchLimit * scaleFactor; cfg.branch2StretchLimit = wind.Branch2StretchLimit * scaleFactor; + cfg.importScale = scaleFactor; cfg.treeExtentX = (treeBounds.Max.X - treeBounds.Min.X) * scaleFactor; cfg.treeExtentY = (treeBounds.Max.Y - treeBounds.Min.Y) * scaleFactor; cfg.treeExtentZ = (treeBounds.Max.Z - treeBounds.Min.Z) * scaleFactor; @@ -1190,7 +1274,7 @@ bool RippleHasAllCurvesValid(in WindRipple r) CopyCurve(shared.Turbulence, cfg.turbulenceShared); CopyCurve(shared.Flexibility, cfg.flexibilityShared); cfg.independenceShared = shared.Independence; - cfg.sharedHeightStart = wind.SharedStartHeight * scaleFactor; + cfg.sharedHeightStart = wind.SharedStartHeight; // this is a % value if (BranchHasAllCurvesValid(in shared)) { cfg.doShared = 1; @@ -1260,29 +1344,25 @@ private void SetWindParameters(ref SpeedTreeWindConfig9 cfg) #region Others private void CalculateScaleFactorFromUnit() { - float scaleFactor = m_MeshSettings.scaleFactor; - switch (m_MeshSettings.unitConversion) { // Use units in the imported file without any conversion. case STUnitConversion.kLeaveAsIs: - scaleFactor = 1.0f; + m_MeshSettings.scaleFactor = 1.0f; break; case STUnitConversion.kFeetToMeters: - scaleFactor = SpeedTreeConstants.kFeetToMetersRatio; + m_MeshSettings.scaleFactor = SpeedTreeConstants.kFeetToMetersRatio; break; case STUnitConversion.kCentimetersToMeters: - scaleFactor = SpeedTreeConstants.kCentimetersToMetersRatio; + m_MeshSettings.scaleFactor = SpeedTreeConstants.kCentimetersToMetersRatio; break; case STUnitConversion.kInchesToMeters: - scaleFactor = SpeedTreeConstants.kInchesToMetersRatio; + m_MeshSettings.scaleFactor = SpeedTreeConstants.kInchesToMetersRatio; break; case STUnitConversion.kCustomConversion: /* no-op */ break; } - - m_MeshSettings.scaleFactor = scaleFactor; } private bool TreeHasFacingData() @@ -1301,27 +1381,12 @@ private bool TreeHasFacingData() return false; } - private bool TryGetShaderForCurrentRenderPipeline(STRenderPipeline renderPipeline, out Shader shader) + internal static bool TryGetShaderForCurrentRenderPipeline(out Shader shader) { - switch (renderPipeline) + shader = GraphicsSettings.GetDefaultShader(DefaultShaderType.SpeedTree9); + if (shader == null) { - case STRenderPipeline.URP: - shader = Shader.Find(ImporterSettings.kURPShaderName); - if (shader == null) - { - shader = m_Context.GetReferenceToAssetMainObject(ImporterSettings.kURPShaderPath) as Shader; - } - break; - case STRenderPipeline.HDRP: - shader = Shader.Find(ImporterSettings.kHDRPShaderName); - if (shader == null) - { - shader = m_Context.GetReferenceToAssetMainObject(ImporterSettings.kHDRPShaderPath) as Shader; - } - break; - default: - shader = Shader.Find(ImporterSettings.kLegacyShaderName); - break; + shader = Shader.Find(ImporterSettings.kLegacyShaderName); } return shader != null; @@ -1453,7 +1518,7 @@ private static bool TryGetHashSpeedTreeAttributeMaterialSettings(out List importers public override void OnEnable() { + if (!AreImporterTargetsValid()) + { + base.OnEnable(); // lets the base mark the editor enabled/inert (OnDisable symmetry) + return; + } + m_STImporter = target as SpeedTree9Importer; if (tabs == null) @@ -67,9 +73,14 @@ public override void OnEnable() public override void OnDisable() { - foreach (var tab in tabs) + // The tabs are only built by OnEnable when the importer targets are still valid. base.OnDisable + // must run either way: it is what unsubscribes this editor from the static header GUI events. + if (tabs != null) { - tab.OnDisable(); + foreach (var tab in tabs) + { + tab.OnDisable(); + } } base.OnDisable(); } diff --git a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterModelEditor.cs b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterModelEditor.cs index dc59855ba7..29ff3dbadf 100644 --- a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterModelEditor.cs +++ b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTree9ImporterModelEditor.cs @@ -280,14 +280,19 @@ internal bool DoMaterialsHaveDifferentShader() importerArray.Add(importer); } - var renderPipeline = SpeedTreeImporterCommon.GetCurrentRenderPipelineType(); + string defaultShaderName = String.Empty; + if (TryGetShaderForCurrentRenderPipeline(out var shader)) + { + defaultShaderName = shader.name; + } + else + { + Debug.LogWarning("SpeedTree9 shader is invalid, cannot create Materials for this SpeedTree asset."); + } // In tests assetTargets can become null for (int i = 0; i < Math.Min(importerArray.Count, prefabs?.Length ?? 0); ++i) { - var im = importerArray[i]; - var defaultShaderName = im.GetShaderNameFromPipeline(renderPipeline); - foreach (var mr in prefabs[i].transform.GetComponentsInChildren()) { foreach (var mat in mr.sharedMaterials) @@ -488,7 +493,12 @@ private void DrawLODGroupFoldouts(List lods) private string GetLODSubmeshAndTriCountLabel(int numLODs, int lodGroupIndex, SpeedTree9Importer im, LODGroup lodGroup) { LOD[] lods = lodGroup.GetLODs(); - Debug.Assert(lods.Length == numLODs); + + if(lods.Length != numLODs) + { + Debug.LogWarningFormat("Number of LODs mismatch between serialized object & LODGroup: {0}\nPlease re-import the asset and kindly report a bug if this warning keeps coming back.", im.assetPath); + numLODs = lods.Length; + } int[][] primitiveCounts = new int[numLODs][]; int[] submeshCounts = new int[numLODs]; @@ -542,6 +552,11 @@ private string GetLODSubmeshAndTriCountLabel(int numLODs, int lodGroupIndex, Spe return $"{totalTriCount} {LODGroupGUI.GUIStyles.m_TriangleCountLabel.text} {triangleChangeLabel} {submeshCountLabel}"; } + private Color GetLODGroupColor(int lodIndex) + { + return LODGroupGUI.kLODColors[lodIndex % LODGroupGUI.kLODColors.Length]; + } + private void DrawLODGroupFoldout(Camera camera, int lodGroupIndex, ref SavedBool foldoutState, List lodInfoList) { GameObject[] ObjectArrayToGameObjectArray(UnityEngine.Object[] objects) @@ -593,7 +608,7 @@ GameObject[] ObjectArrayToGameObjectArray(UnityEngine.Object[] objects) , foldoutState.value , LODFoldoutHeaderLabel , m_LODColorTextures[lodGroupIndex] - , LODGroupGUI.kLODColors[lodGroupIndex] * 0.6f // 0.5f magic number is copied from LODGroupsGUI.cs + , GetLODGroupColor(lodGroupIndex) * 0.6f // 0.5f magic number is copied from LODGroupsGUI.cs , LODFoldoutHeaderGroupAdditionalText ); @@ -722,13 +737,13 @@ void InitAndSetFoldoutLabelTextures() for (int i = 0; i < m_LODColorTextures.Length; i++) { m_LODColorTextures[i] = new Texture2D(1, 1); - m_LODColorTextures[i].SetPixel(0, 0, LODGroupGUI.kLODColors[i]); + m_LODColorTextures[i].SetPixel(0, 0, GetLODGroupColor(i)); } } void ResetFoldoutLists() { - int lodArraySize = m_PerLODSettings.arraySize; + int lodArraySize = Mathf.Min(m_PerLODSettings.arraySize, LODGroupGUI.kLODColors.Length); m_LODGroupFoldoutHeaderValues = new SavedBool[lodArraySize]; for (int i = 0; i < lodArraySize; i++) { diff --git a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterCommon.cs b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterCommon.cs index 72373ac7b9..eaee480758 100644 --- a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterCommon.cs +++ b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterCommon.cs @@ -20,13 +20,6 @@ class SpeedTreeConstants static class SpeedTreeImporterCommon { - internal enum STRenderPipeline - { - Legacy, - URP, - HDRP - } - internal enum STUnitConversion { kLeaveAsIs = 0, @@ -84,41 +77,6 @@ internal static class MaterialKeywords internal static readonly string VBSetupID = "VB_SETUP"; internal static readonly string BillboardID = "_BILLBOARD"; } - - internal static STRenderPipeline GetCurrentRenderPipelineType() - { - var renderPipelineAsset = GraphicsSettings.renderPipelineAsset; - if (renderPipelineAsset != null) - { - if (renderPipelineAsset.name.Contains("UniversalRP") || - renderPipelineAsset.name.Contains("URP")) - { - return STRenderPipeline.URP; - } - else if (renderPipelineAsset.name.Contains("HDRenderPipeline") || - renderPipelineAsset.name.Contains("HDRP")) - { - return STRenderPipeline.HDRP; - } - } - - renderPipelineAsset = QualitySettings.renderPipeline; - if (renderPipelineAsset != null) - { - if (renderPipelineAsset.name.Contains("UniversalRP") || - renderPipelineAsset.name.Contains("URP")) - { - return STRenderPipeline.URP; - } - else if (renderPipelineAsset.name.Contains("HDRenderPipeline") || - renderPipelineAsset.name.Contains("HDRP")) - { - return STRenderPipeline.HDRP; - } - } - - return STRenderPipeline.Legacy; - } } static class SpeedTreeImporterCommonEditor @@ -128,7 +86,7 @@ internal class Styles // Meshes labels public static GUIContent MeshesHeader = EditorGUIUtility.TrTextContent("Meshes"); public static GUIContent UnitConversion = EditorGUIUtility.TrTextContent("Unit Conversion", "Select the unit conversion to apply to the imported SpeedTree asset."); - public static GUIContent ScaleFactor = EditorGUIUtility.TrTextContent("Scale Factor", "How much to scale the tree model, interpreting the exported units as meters"); + public static GUIContent ScaleFactor = EditorGUIUtility.TrTextContent("Scale Factor", "How much to scale the tree model, interpreting the exported units as meters. Must be positive."); public static GUIContent[] UnitConversionNames = { new GUIContent("Leave As Is") @@ -223,6 +181,14 @@ static internal void ShowMeshGUI( if (bShowCustomScaleFactor) { EditorGUILayout.PropertyField(scaleFactor, Styles.ScaleFactor); + if (scaleFactor.floatValue < 0f) + { + scaleFactor.floatValue = 0f; + } + if (scaleFactor.floatValue == 0f) + { + EditorGUILayout.HelpBox("Scale factor must be positive.", MessageType.Warning); + } } } diff --git a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterSettings.cs b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterSettings.cs index 3e5d07af25..a6a84b45ee 100644 --- a/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterSettings.cs +++ b/Editor/Mono/AssetPipeline/SpeedTree/SpeedTreeImporterSettings.cs @@ -85,6 +85,7 @@ internal class PerLODSettings internal class MaterialInfo { public Material material = null; + public string defaultName = null; public bool exported = false; } diff --git a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs index 9ccb5d0de8..7c1eb764c4 100644 --- a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs @@ -248,11 +248,16 @@ public static unsafe class TextureGenerator { public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray colorBuffer) { - return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf()); + return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf(), 4); + } + + public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray colorBuffer) + { + return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf(), 16); } [NativeThrows] [NativeMethod("GenerateTextureScripting")] - extern static unsafe TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, void* colorBuffer, int colorBufferLength); + extern static unsafe TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, void* colorBuffer, int colorBufferLength, int bytesPerPixel); } } diff --git a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs index e6788fee09..e304c3437b 100644 --- a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs @@ -17,11 +17,12 @@ namespace UnityEditor [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporter.h")] [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporter.deprecated.h")] [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporterUtils.h")] + [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporterPlatformSettingsUtils.h")] [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] public sealed partial class TextureImporter : AssetImporter { [FreeFunction] - internal static extern string GetFixedPlatformName(string platform); + internal static extern string GetTexturePlatformSerializationName(string platformName); [Obsolete("textureFormat is no longer accessible at the TextureImporter level. For old 'simple' formats use the textureCompression property for the equivalent automatic choice (Uncompressed for TrueColor, Compressed and HQCommpressed for 16 bits). For platform specific formats use the [[PlatformTextureSettings]] API. Using this setter will setup various parameters to match the new automatic system as well as possible. Getter will return the last value set.")] public extern TextureImporterFormat textureFormat @@ -103,8 +104,7 @@ public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, // public API will always return a valid TextureImporterPlatformSettings, creating it based on the default one if it did not exist. public TextureImporterPlatformSettings GetPlatformTextureSettings(string platform) { - // make sure we are converting the settings to use the proper BuildTarget name to get them (the way it works on other importers) - platform = GetFixedPlatformName(platform); + platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". TextureImporterPlatformSettings dest = GetPlatformTextureSetting_Internal(platform); if (platform != dest.name) @@ -122,27 +122,24 @@ public TextureImporterPlatformSettings GetDefaultPlatformTextureSettings() public TextureImporterFormat GetAutomaticFormat(string platform) { - platform = GetFixedPlatformName(platform); + platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". TextureImporterSettings settings = new TextureImporterSettings(); ReadTextureSettings(settings); TextureImporterPlatformSettings platformSettings = GetPlatformTextureSettings(platform); - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - foreach (BuildPlatform bp in validPlatforms) + BuildTarget buildTarget = BuildPipeline.GetBuildTargetByName(platform); + if (buildTarget != BuildTarget.NoTarget) { - if (bp.name == platform) - { - return DefaultFormatFromTextureParameters(settings, - !platformSettings.overridden ? GetDefaultPlatformTextureSettings() : platformSettings, - DoesSourceTextureHaveAlpha(), - IsSourceTextureHDR(), - bp.defaultTarget); - - // Regarding the "GetDefaultPlatformTextureSettings" call: in case 1281084, we made it so that platform settings stop automatically - // resetting to the default platform's settings when the platform override is disabled. This introduced a regression where - // "GetAutomaticFormat" would not return the actual format used by platforms with a disabled override, (as in, the one indicated in - // the default platform's settings) which is why we pass in the default platform's settings instead. - } + return DefaultFormatFromTextureParameters(settings, + !platformSettings.overridden ? GetDefaultPlatformTextureSettings() : platformSettings, + DoesSourceTextureHaveAlpha(), + IsSourceTextureHDR(), + buildTarget); + + // Regarding the "GetDefaultPlatformTextureSettings" call: in case 1281084, we made it so that platform settings stop automatically + // resetting to the default platform's settings when the platform override is disabled. This introduced a regression where + // "GetAutomaticFormat" would not return the actual format used by platforms with a disabled override, (as in, the one indicated in + // the default platform's settings) which is why we pass in the default platform's settings instead. } return TextureImporterFormat.Automatic; @@ -183,8 +180,7 @@ public void SetPlatformTextureSettings(string platform, int maxTextureSize, Text // Set specific target platform settings public void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings) { - // we need to fix the name in case the user changed it to some mismatching value - platformSettings.name = GetFixedPlatformName(platformSettings.name); + platformSettings.name = GetTexturePlatformSerializationName(platformSettings.name); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". SetPlatformTextureSettings_Internal(platformSettings); } @@ -194,7 +190,8 @@ public void SetPlatformTextureSettings(TextureImporterPlatformSettings platformS public void ClearPlatformTextureSettings(string platform) { - ClearPlatformTextureSettings_Internal(GetFixedPlatformName(platform)); + platform = GetTexturePlatformSerializationName(platform); // String may refer to a platform group: if != "Standalone", ensure it refers to a platform instead. E.g.: "iOS", not "iPhone". + ClearPlatformTextureSettings_Internal(platform); } [FreeFunction] @@ -452,9 +449,30 @@ public void ReadTextureSettings(TextureImporterSettings dest) // Set texture importers settings from [[TextureImporterSettings]] class. public void SetTextureSettings(TextureImporterSettings src) { + ValidateAndCorrectTextureImporterSettings(src); settings = src; } + private void ValidateAndCorrectTextureImporterSettings(TextureImporterSettings m_Settings) + { + switch (m_Settings.textureType) + { + case TextureImporterType.Sprite: + m_Settings.npotScale = ValidateAndCorrectSetting(m_Settings.npotScale, TextureImporterNPOTScale.None, nameof(m_Settings.npotScale)); + break; + } + } + + private T ValidateAndCorrectSetting(T actual, T expected, string settingName) + { + if (!actual.Equals(expected)) + { + Debug.LogWarning($"You cannot set {settingName} to {actual} for this texture type. It has been reset to {expected}."); + return expected; + } + return actual; + } + private extern TextureImporterSettings settings { get; set; } [NativeName("GetImportInspectorWarning")] diff --git a/Editor/Mono/AssetPreviewUpdater.cs b/Editor/Mono/AssetPreviewUpdater.cs index f3844fd70a..c58d13d430 100644 --- a/Editor/Mono/AssetPreviewUpdater.cs +++ b/Editor/Mono/AssetPreviewUpdater.cs @@ -36,18 +36,9 @@ public static Texture2D CreatePreview(Object obj, Object[] subAssets, string ass var editor = Editor.CreateEditor(obj); if (editor == null) return null; - - //Check that Render Pipeline is ready - //Beware: AssetImportWorkers have their own Render Pipeline instance. Render Pipeline will be separately created for each one of them. - var pipelineWasNotInitialized = !RenderPipelineManager.pipelineSwitchCompleted; - - //We always keep this call to initialize Render Pipeline when Render Pipeline was not ready + var previewTexture = editor.RenderStaticPreview(assetPath, subAssets, width, height); - //If after render our Render Pipeline is initialized we re-render to have a valid result - if (pipelineWasNotInitialized && RenderPipelineManager.pipelineSwitchCompleted) - previewTexture = editor.RenderStaticPreview(assetPath, subAssets, width, height); - // For debugging we write the preview to a file (keep) //{ // var bytes = tex.EncodeToPNG(); diff --git a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs b/Editor/Mono/AssetStore/AssetStorePreviewManager.cs index f7579935f2..30fa6b3c6d 100644 --- a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs +++ b/Editor/Mono/AssetStore/AssetStorePreviewManager.cs @@ -107,7 +107,7 @@ public static int Downloading public static string StatsString() { - return string.Format("Reqs: {0}, Ok: {1}, Abort: {2}, CacheDel: {3}, Cache: {4}/{5}, CacheHit: {6}", + return string.Format("Reqs: {0}, OK: {1}, Abort: {2}, CacheDel: {3}, Cache: {4}/{5}, CacheHit: {6}", Instance.Requested, Instance.m_Success, Instance.m_Aborted, Instance.m_CacheRemove, AssetStorePreviewManager.CachedAssetStoreImages.Count, Instance.m_MaxCachedAssetStoreImages, diff --git a/Editor/Mono/AssetStore/AssetStoreWindow.cs b/Editor/Mono/AssetStore/AssetStoreWindow.cs index b497413d8a..3004202686 100644 --- a/Editor/Mono/AssetStore/AssetStoreWindow.cs +++ b/Editor/Mono/AssetStore/AssetStoreWindow.cs @@ -42,7 +42,7 @@ public static void OpenAssetStoreInBrowser() [MenuItem("Window/My Assets", false, 1498)] public static void OpenMyAssetsInPackageManager() { - PackageManagerWindow.SelectPackageAndPageStatic(pageId: PackageManager.UI.Internal.MyAssetsPage.k_Id); + PackageManagerWindow.OpenAndSelectPage(PackageManager.UI.Internal.MyAssetsPage.k_Id); } public void OnEnable() @@ -100,7 +100,7 @@ private void OnVisitWebsiteButtonClicked() private void OnLaunchPackageManagerButtonClicked() { - PackageManagerWindow.OpenPackageManager(null); + PackageManagerWindow.OpenAndSelectPackage(null); } private void SetMinMaxSizes() diff --git a/Editor/Mono/AssetStoreCachePathManager.cs b/Editor/Mono/AssetStoreCachePathManager.cs index 6cf4345d18..31fba1756c 100644 --- a/Editor/Mono/AssetStoreCachePathManager.cs +++ b/Editor/Mono/AssetStoreCachePathManager.cs @@ -19,7 +19,7 @@ public enum ConfigStatus InvalidPath, ReadOnly, EnvironmentOverride, - NotFound, + Default, Failed }; diff --git a/Editor/Mono/AttributeHelper.cs b/Editor/Mono/AttributeHelper.cs index 95d72e45d3..2719d77a50 100644 --- a/Editor/Mono/AttributeHelper.cs +++ b/Editor/Mono/AttributeHelper.cs @@ -112,7 +112,7 @@ static MonoGizmoMethod[] ExtractGizmos(Assembly assembly) } [RequiredByNativeCode] - static string GetComponentMenuName(Type type) + static object GetComponentMenuName(Type type) { var attrs = type.GetCustomAttributes(typeof(AddComponentMenu), false); if (attrs.Length > 0) diff --git a/Editor/Mono/Audio/AudioContainerWindow.cs b/Editor/Mono/Audio/AudioContainerWindow.cs index c608ed7f67..03355b2a14 100644 --- a/Editor/Mono/Audio/AudioContainerWindow.cs +++ b/Editor/Mono/Audio/AudioContainerWindow.cs @@ -20,6 +20,15 @@ namespace UnityEditor; sealed class AudioContainerWindow : EditorWindow { + enum Icons + { + Play = 0, + Stop = 1, + Skip = 2, + DiceOff = 3, + DiceOn = 4 + } + /// /// The cached instance of the window, if it is open. /// @@ -32,8 +41,8 @@ sealed class AudioContainerWindow : EditorWindow /// Only used locally in these methods, but it's a global member to avoid GC. /// readonly List m_AddedElements = new(); - readonly string k_EmptyGuidString = Guid.Empty.ToString("N"); + readonly Texture2D[] k_IconTextureCache = new Texture2D[Enum.GetNames(typeof(Icons)).Length]; VisualElement m_ContainerRootVisualElement; VisualElement m_Day0RootVisualElement; @@ -91,15 +100,11 @@ sealed class AudioContainerWindow : EditorWindow Label m_AutomaticTriggerModeLabel; Label m_LoopLabel; - // Shared icon references - Texture2D m_DiceIconOff; - Texture2D m_DiceIconOn; - bool m_IsVisible; - bool m_IsSubscribedToGUICallbacksAndEvents; bool m_IsInitializing; bool m_Day0ElementsInitialized; bool m_ContainerElementsInitialized; + bool m_IsSubscribedToGUICallbacksAndEvents; bool m_ClipFieldProgressBarsAreCleared = true; /// @@ -114,6 +119,12 @@ internal static void CreateAudioRandomContainerWindow() window.Show(); } + // Used by tests. + internal bool IsInitializedForTargetDisplay() + { + return m_ContainerElementsInitialized && m_IsSubscribedToGUICallbacksAndEvents; + } + static void OnCreateButtonClicked() { ProjectWindowUtil.CreateAudioRandomContainer(); @@ -121,24 +132,36 @@ static void OnCreateButtonClicked() void OnEnable() { - Instance = this; - - m_DiceIconOff = EditorGUIUtility.IconContent("AudioRandomContainer On Icon").image as Texture2D; - m_DiceIconOn = EditorGUIUtility.IconContent("AudioRandomContainer Icon").image as Texture2D; + if (Instance == null) + { + Instance = this; + } SetTitle(); - - m_IsInitializing = false; - m_Day0ElementsInitialized = false; - m_ContainerElementsInitialized = false; } void OnDisable() { - Instance = null; State.OnDestroy(); + UnsubscribeFromGUICallbacksAndEvents(); + m_IsInitializing = false; + m_Day0ElementsInitialized = false; + m_ContainerElementsInitialized = false; m_CachedElements.Clear(); m_AddedElements.Clear(); + + if (Instance == this) + { + Instance = null; + } + } + + void OnFocus() + { + if (State.AudioContainer != null) + { + UpdateTransportButtonStates(); + } } void Update() @@ -146,12 +169,12 @@ void Update() if (!m_IsVisible) return; - if (State.IsPlayingOrPaused()) { UpdateClipFieldProgressBars(); } + if (State.IsPreviewPlayingOrPaused()) { UpdateClipFieldProgressBars(); } else if (!m_ClipFieldProgressBarsAreCleared) { ClearClipFieldProgressBars(); } if (m_Meter != null) { - if (State.IsPlayingOrPaused()) + if (State.IsPreviewPlayingOrPaused()) { if (State != null) { m_Meter.Value = State.GetMeterValue(); } else { m_Meter.Value = -80.0f; } @@ -172,7 +195,7 @@ void SetTitle() titleContent = new GUIContent(titleString) { - image = m_DiceIconOff + image = GetIconTexture(Icons.DiceOff) }; } @@ -234,6 +257,7 @@ void CreateGUI() m_Day0RootVisualElement.style.display = DisplayStyle.None; m_ContainerRootVisualElement.style.display = DisplayStyle.Flex; + m_CachedElements = State.AudioContainer.elements.ToList(); m_ClipsListView.Rebuild(); // Force a list rebuild when the list has changed or it will not always render correctly due to a UI toolkit bug. } } @@ -272,23 +296,35 @@ void InitializeContainerElements() void SubscribeToGUICallbacksAndEvents() { + if (!m_ContainerElementsInitialized || m_IsSubscribedToGUICallbacksAndEvents) + { + return; + } + SubscribeToPreviewCallbacksAndEvents(); SubscribeToVolumeCallbacksAndEvents(); SubscribeToPitchCallbacksAndEvents(); SubscribeToClipListCallbacksAndEvents(); SubscribeToAutomaticTriggerCallbacksAndEvents(); SubscribeToTooltipCallbacksAndEvents(); + SubscribeToAudioMasterMuteCallbacksAndEvents(); m_IsSubscribedToGUICallbacksAndEvents = true; } void UnsubscribeFromGUICallbacksAndEvents() { + if (!m_ContainerElementsInitialized || !m_IsSubscribedToGUICallbacksAndEvents) + { + return; + } + UnsubscribeFromPreviewCallbacksAndEvents(); UnsubscribeFromVolumeCallbacksAndEvents(); UnsubscribeFromPitchCallbacksAndEvents(); UnsubscribeFromClipListCallbacksAndEvents(); UnsubscribeFromAutomaticTriggerCallbacksAndEvents(); UnsubscribeFromTooltipCallbacksAndEvents(); + UnsubscribeFromAudioMasterMuteCallbacksAndEvents(); m_IsSubscribedToGUICallbacksAndEvents = false; } @@ -313,8 +349,6 @@ void OnTargetChanged(object sender, EventArgs e) m_CachedElements.Clear(); else m_CachedElements = State.AudioContainer.elements.ToList(); - - m_AddedElements.Clear(); } void OnSerializedObjectChanged(SerializedObject obj) @@ -351,9 +385,7 @@ void InitializePreviewElements() m_PlayStopButtonImage = UIToolkitUtilities.GetChildByName(m_ContainerRootVisualElement, "play-button-image"); m_SkipButton = UIToolkitUtilities.GetChildByName