DisplayWindow.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. using System;
  2. using UnityEditor.UIElements;
  3. using UnityEngine;
  4. using UnityEngine.Rendering;
  5. using UnityEngine.UIElements;
  6. using RenderPipelineManager = UnityEngine.Rendering.RenderPipelineManager;
  7. namespace UnityEditor.Rendering.LookDev
  8. {
  9. /// <summary>Interface that must implement the viewer to communicate with the compositor and data management</summary>
  10. public interface IViewDisplayer
  11. {
  12. /// <summary>Get the displayed rect to use</summary>
  13. /// <param name="index">Index of this view</param>
  14. /// <returns>The Rect to draw</returns>
  15. Rect GetRect(ViewCompositionIndex index);
  16. /// <summary>Set the computed texture in the view</summary>
  17. /// <param name="index">Index of this view</param>
  18. /// <param name="texture">The texture used</param>
  19. void SetTexture(ViewCompositionIndex index, Texture texture);
  20. /// <summary>Repaint the UI</summary>
  21. void Repaint();
  22. /// <summary>Callback on layout changed</summary>
  23. event Action<Layout, SidePanel> OnLayoutChanged;
  24. /// <summary>Callback on RenderDoc acquisition is triggered</summary>
  25. event Action OnRenderDocAcquisitionTriggered;
  26. /// <summary>Callback on ;ouse events in the view</summary>
  27. event Action<IMouseEvent> OnMouseEventInView;
  28. /// <summary>Callback on object changed in the view</summary>
  29. event Action<GameObject, ViewCompositionIndex, Vector2> OnChangingObjectInView;
  30. /// <summary>Callback on environment changed in the view</summary>
  31. event Action<UnityEngine.Object, ViewCompositionIndex, Vector2> OnChangingEnvironmentInView;
  32. /// <summary>Callback on closed</summary>
  33. event Action OnClosed;
  34. /// <summary>Callback on update requested</summary>
  35. event Action OnUpdateRequested;
  36. }
  37. partial class DisplayWindow : EditorWindow, IViewDisplayer
  38. {
  39. static partial class Style
  40. {
  41. internal const string k_IconFolder = @"Packages/com.unity.render-pipelines.core/Editor/LookDev/Icons/";
  42. internal const string k_uss = @"Packages/com.unity.render-pipelines.core/Editor/LookDev/DisplayWindow.uss";
  43. internal const string k_uss_personal_overload = @"Packages/com.unity.render-pipelines.core/Editor/LookDev/DisplayWindow-PersonalSkin.uss";
  44. internal static readonly GUIContent k_WindowTitleAndIcon = EditorGUIUtility.TrTextContentWithIcon("Look Dev", CoreEditorUtils.LoadIcon(k_IconFolder, "LookDev", forceLowRes: true));
  45. internal static readonly (Texture2D icon, string tooltip) k_Layout1Icon =
  46. (CoreEditorUtils.LoadIcon(Style.k_IconFolder, "Layout1", forceLowRes: true),
  47. "First view");
  48. internal static readonly (Texture2D icon, string tooltip) k_Layout2Icon =
  49. (CoreEditorUtils.LoadIcon(Style.k_IconFolder, "Layout2", forceLowRes: true),
  50. "Second view");
  51. internal static readonly (Texture2D icon, string tooltip) k_LayoutVerticalIcon =
  52. (CoreEditorUtils.LoadIcon(Style.k_IconFolder, "LayoutVertical", forceLowRes: true),
  53. "Both views split vertically");
  54. internal static readonly (Texture2D icon, string tooltip) k_LayoutHorizontalIcon =
  55. (CoreEditorUtils.LoadIcon(Style.k_IconFolder, "LayoutHorizontal", forceLowRes: true),
  56. "Both views split horizontally");
  57. internal static readonly (Texture2D icon, string tooltip) k_LayoutStackIcon =
  58. (CoreEditorUtils.LoadIcon(Style.k_IconFolder, "LayoutCustom", forceLowRes: true),
  59. "Both views stacked");
  60. internal static readonly Texture2D k_Camera1Icon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "Camera1", forceLowRes: true);
  61. internal static readonly Texture2D k_Camera2Icon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "Camera2", forceLowRes: true);
  62. internal static readonly Texture2D k_LinkIcon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "Link", forceLowRes: true);
  63. internal static readonly Texture2D k_RightIcon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "RightArrow", forceLowRes: true);
  64. internal static readonly Texture2D k_LeftIcon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "LeftArrow", forceLowRes: true);
  65. internal static readonly Texture2D k_RenderdocIcon = CoreEditorUtils.LoadIcon(Style.k_IconFolder, "RenderDoc", forceLowRes: true);
  66. internal const string k_RenderDocLabel = " Content";
  67. internal const string k_CameraSyncTooltip = "Synchronize camera movement amongst views";
  68. internal const string k_CameraMenuSync1On2 = "Align Camera 1 with Camera 2";
  69. internal const string k_CameraMenuSync2On1 = "Align Camera 2 with Camera 1";
  70. internal const string k_CameraMenuReset = "Reset Cameras";
  71. internal const string k_EnvironmentSidePanelName = "Environment";
  72. internal const string k_DebugSidePanelName = "Debug";
  73. internal const string k_DragAndDropObject = "Drag and drop object here";
  74. internal const string k_DragAndDropEnvironment = "Drag and drop environment from side panel here";
  75. // /!\ WARNING:
  76. //The following const are used in the uss.
  77. //If you change them, update the uss file too.
  78. internal const string k_MainContainerName = "mainContainer";
  79. internal const string k_ViewContainerName = "viewContainer";
  80. internal const string k_FirstViewName = "firstView";
  81. internal const string k_SecondViewName = "secondView";
  82. internal const string k_ToolbarName = "toolbar";
  83. internal const string k_ToolbarRadioName = "toolbarRadio";
  84. internal const string k_TabsRadioName = "tabsRadio";
  85. internal const string k_SideToolbarName = "sideToolbar";
  86. internal const string k_SharedContainerClass = "container";
  87. internal const string k_FirstViewClass = "firstView";
  88. internal const string k_SecondViewsClass = "secondView";
  89. internal const string k_VerticalViewsClass = "verticalSplit";
  90. internal const string k_DebugContainerName = "debugContainer";
  91. internal const string k_ShowDebugPanelClass = "showDebugPanel";
  92. internal const string k_EnvironmentContainerName = "environmentContainer";
  93. internal const string k_ShowEnvironmentPanelClass = "showEnvironmentPanel";
  94. internal const string k_CameraMenuName = "cameraMenu";
  95. internal const string k_CameraButtonName = "cameraButton";
  96. internal const string k_CameraSeparatorName = "cameraSeparator";
  97. internal const string k_RenderDocContentName = "renderdoc-content";
  98. }
  99. VisualElement m_MainContainer;
  100. VisualElement m_ViewContainer;
  101. VisualElement m_DebugContainer;
  102. Label m_NoEnvironmentList;
  103. Label m_NoObject1;
  104. Label m_NoEnvironment1;
  105. Label m_NoObject2;
  106. Label m_NoEnvironment2;
  107. Image[] m_Views = new Image[2];
  108. LayoutContext layout
  109. => LookDev.currentContext.layout;
  110. Layout viewLayout
  111. {
  112. get => layout.viewLayout;
  113. set
  114. {
  115. if (layout.viewLayout != value)
  116. {
  117. OnLayoutChangedInternal?.Invoke(value, sidePanel);
  118. ApplyLayout(value);
  119. }
  120. }
  121. }
  122. SidePanel sidePanel
  123. {
  124. get => layout.showedSidePanel;
  125. set
  126. {
  127. if (layout.showedSidePanel != value)
  128. {
  129. OnLayoutChangedInternal?.Invoke(viewLayout, value);
  130. ApplySidePanelChange(layout.showedSidePanel);
  131. }
  132. }
  133. }
  134. event Action<Layout, SidePanel> OnLayoutChangedInternal;
  135. event Action<Layout, SidePanel> IViewDisplayer.OnLayoutChanged
  136. {
  137. add => OnLayoutChangedInternal += value;
  138. remove => OnLayoutChangedInternal -= value;
  139. }
  140. event Action OnRenderDocAcquisitionTriggeredInternal;
  141. event Action IViewDisplayer.OnRenderDocAcquisitionTriggered
  142. {
  143. add => OnRenderDocAcquisitionTriggeredInternal += value;
  144. remove => OnRenderDocAcquisitionTriggeredInternal -= value;
  145. }
  146. event Action<IMouseEvent> OnMouseEventInViewPortInternal;
  147. event Action<IMouseEvent> IViewDisplayer.OnMouseEventInView
  148. {
  149. add => OnMouseEventInViewPortInternal += value;
  150. remove => OnMouseEventInViewPortInternal -= value;
  151. }
  152. event Action<GameObject, ViewCompositionIndex, Vector2> OnChangingObjectInViewInternal;
  153. event Action<GameObject, ViewCompositionIndex, Vector2> IViewDisplayer.OnChangingObjectInView
  154. {
  155. add => OnChangingObjectInViewInternal += value;
  156. remove => OnChangingObjectInViewInternal -= value;
  157. }
  158. //event Action<Material, ViewCompositionIndex, Vector2> OnChangingMaterialInViewInternal;
  159. //event Action<Material, ViewCompositionIndex, Vector2> IViewDisplayer.OnChangingMaterialInView
  160. //{
  161. // add => OnChangingMaterialInViewInternal += value;
  162. // remove => OnChangingMaterialInViewInternal -= value;
  163. //}
  164. event Action<UnityEngine.Object, ViewCompositionIndex, Vector2> OnChangingEnvironmentInViewInternal;
  165. event Action<UnityEngine.Object, ViewCompositionIndex, Vector2> IViewDisplayer.OnChangingEnvironmentInView
  166. {
  167. add => OnChangingEnvironmentInViewInternal += value;
  168. remove => OnChangingEnvironmentInViewInternal -= value;
  169. }
  170. event Action OnClosedInternal;
  171. event Action IViewDisplayer.OnClosed
  172. {
  173. add => OnClosedInternal += value;
  174. remove => OnClosedInternal -= value;
  175. }
  176. event Action OnUpdateRequestedInternal;
  177. event Action IViewDisplayer.OnUpdateRequested
  178. {
  179. add => OnUpdateRequestedInternal += value;
  180. remove => OnUpdateRequestedInternal -= value;
  181. }
  182. StyleSheet styleSheet = null;
  183. StyleSheet styleSheetLight = null;
  184. SwitchableCameraController m_FirstOrCompositeManipulator;
  185. CameraController m_SecondManipulator;
  186. ComparisonGizmoController m_GizmoManipulator;
  187. void ReloadStyleSheets()
  188. {
  189. if(styleSheet == null || styleSheet.Equals(null))
  190. {
  191. styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(Style.k_uss);
  192. if(styleSheet == null || styleSheet.Equals(null))
  193. {
  194. //Debug.LogWarning("[LookDev] Could not load Stylesheet.");
  195. return;
  196. }
  197. }
  198. if(!rootVisualElement.styleSheets.Contains(styleSheet))
  199. rootVisualElement.styleSheets.Add(styleSheet);
  200. //Additively load Light Skin
  201. if(!EditorGUIUtility.isProSkin)
  202. {
  203. if(styleSheetLight == null || styleSheetLight.Equals(null))
  204. {
  205. styleSheetLight = AssetDatabase.LoadAssetAtPath<StyleSheet>(Style.k_uss_personal_overload);
  206. if(styleSheetLight == null || styleSheetLight.Equals(null))
  207. {
  208. //Debug.LogWarning("[LookDev] Could not load Light skin.");
  209. return;
  210. }
  211. }
  212. if(!rootVisualElement.styleSheets.Contains(styleSheetLight))
  213. rootVisualElement.styleSheets.Add(styleSheetLight);
  214. }
  215. }
  216. void CreateGUI()
  217. {
  218. ReloadStyleSheets();
  219. //Call the open function to configure LookDev
  220. // in case the window where open when last editor session finished.
  221. // (Else it will open at start and has nothing to display).
  222. if (!LookDev.open)
  223. LookDev.Initialize(this);
  224. titleContent = Style.k_WindowTitleAndIcon;
  225. // /!\ be sure to have a minSize that will allow a non negative sized viewport even with side panel open
  226. this.minSize = new Vector2(600, 400);
  227. CreateToolbar();
  228. m_MainContainer = new VisualElement() { name = Style.k_MainContainerName };
  229. m_MainContainer.AddToClassList(Style.k_SharedContainerClass);
  230. rootVisualElement.Add(m_MainContainer);
  231. CreateViews();
  232. CreateEnvironment();
  233. CreateDebug();
  234. CreateDropAreas();
  235. ApplyLayout(viewLayout);
  236. ApplySidePanelChange(layout.showedSidePanel);
  237. }
  238. void OnEnable()
  239. {
  240. Undo.undoRedoPerformed += FullRefreshEnvironmentList;
  241. }
  242. void OnDisable()
  243. {
  244. Undo.undoRedoPerformed -= FullRefreshEnvironmentList;
  245. OnClosedInternal?.Invoke();
  246. }
  247. void CreateToolbar()
  248. {
  249. // Layout swapper part
  250. var layoutRadio = new ToolbarRadio() { name = Style.k_ToolbarRadioName };
  251. layoutRadio.AddRadios(new[] {
  252. Style.k_Layout1Icon,
  253. Style.k_Layout2Icon,
  254. Style.k_LayoutVerticalIcon,
  255. Style.k_LayoutHorizontalIcon,
  256. Style.k_LayoutStackIcon,
  257. });
  258. layoutRadio.RegisterCallback((ChangeEvent<int> evt)
  259. => viewLayout = (Layout)evt.newValue);
  260. layoutRadio.SetValueWithoutNotify((int)viewLayout);
  261. var cameraMenu = new ToolbarMenu() { name = Style.k_CameraMenuName };
  262. cameraMenu.variant = ToolbarMenu.Variant.Popup;
  263. var cameraToggle = new ToolbarToggle() { name = Style.k_CameraButtonName };
  264. cameraToggle.value = LookDev.currentContext.cameraSynced;
  265. cameraToggle.tooltip = Style.k_CameraSyncTooltip;
  266. //Note: when having Image on top of the Toggle nested in the Menu, RegisterValueChangedCallback is not called
  267. //cameraToggle.RegisterValueChangedCallback(evt => LookDev.currentContext.cameraSynced = evt.newValue);
  268. cameraToggle.RegisterCallback<MouseUpEvent>(evt =>
  269. {
  270. LookDev.currentContext.cameraSynced ^= true;
  271. cameraToggle.SetValueWithoutNotify(LookDev.currentContext.cameraSynced);
  272. });
  273. var cameraSeparator = new ToolbarToggle() { name = Style.k_CameraSeparatorName };
  274. cameraToggle.Add(new Image() { image = Style.k_Camera1Icon });
  275. cameraToggle.Add(new Image() { image = Style.k_LinkIcon });
  276. cameraToggle.Add(new Image() { image = Style.k_Camera2Icon });
  277. cameraMenu.Add(cameraSeparator);
  278. cameraMenu.Add(cameraToggle);
  279. cameraMenu.menu.AppendAction(Style.k_CameraMenuSync1On2,
  280. (DropdownMenuAction a) => LookDev.currentContext.SynchronizeCameraStates(ViewIndex.Second),
  281. DropdownMenuAction.AlwaysEnabled);
  282. cameraMenu.menu.AppendAction(Style.k_CameraMenuSync2On1,
  283. (DropdownMenuAction a) => LookDev.currentContext.SynchronizeCameraStates(ViewIndex.First),
  284. DropdownMenuAction.AlwaysEnabled);
  285. cameraMenu.menu.AppendAction(Style.k_CameraMenuReset,
  286. (DropdownMenuAction a) =>
  287. {
  288. LookDev.currentContext.GetViewContent(ViewIndex.First).ResetCameraState();
  289. LookDev.currentContext.GetViewContent(ViewIndex.Second).ResetCameraState();
  290. },
  291. DropdownMenuAction.AlwaysEnabled);
  292. // Side part
  293. var sideRadio = new ToolbarRadio(canDeselectAll: true)
  294. {
  295. name = Style.k_TabsRadioName
  296. };
  297. sideRadio.AddRadios(new[] {
  298. Style.k_EnvironmentSidePanelName,
  299. Style.k_DebugSidePanelName,
  300. });
  301. sideRadio.SetValueWithoutNotify((int)sidePanel);
  302. sideRadio.RegisterCallback((ChangeEvent<int> evt)
  303. => sidePanel = (SidePanel)evt.newValue);
  304. // Aggregate parts
  305. var toolbar = new UIElements.Toolbar() { name = Style.k_ToolbarName };
  306. toolbar.Add(layoutRadio);
  307. toolbar.Add(new ToolbarSpacer());
  308. toolbar.Add(cameraMenu);
  309. toolbar.Add(new ToolbarSpacer() { flex = true });
  310. if (UnityEditorInternal.RenderDoc.IsInstalled() && UnityEditorInternal.RenderDoc.IsLoaded())
  311. {
  312. var renderDocButton = new ToolbarButton(() => OnRenderDocAcquisitionTriggeredInternal?.Invoke())
  313. {
  314. name = Style.k_RenderDocContentName
  315. };
  316. renderDocButton.Add(new Image() { image = Style.k_RenderdocIcon });
  317. renderDocButton.Add(new Label() { text = Style.k_RenderDocLabel });
  318. toolbar.Add(renderDocButton);
  319. toolbar.Add(new ToolbarSpacer());
  320. }
  321. toolbar.Add(sideRadio);
  322. rootVisualElement.Add(toolbar);
  323. }
  324. void CreateViews()
  325. {
  326. if (m_MainContainer == null || m_MainContainer.Equals(null))
  327. throw new System.MemberAccessException("m_MainContainer should be assigned prior CreateViews()");
  328. m_ViewContainer = new VisualElement() { name = Style.k_ViewContainerName };
  329. m_ViewContainer.AddToClassList(LookDev.currentContext.layout.isMultiView ? Style.k_SecondViewsClass : Style.k_FirstViewClass);
  330. m_ViewContainer.AddToClassList(Style.k_SharedContainerClass);
  331. m_MainContainer.Add(m_ViewContainer);
  332. m_ViewContainer.RegisterCallback<MouseDownEvent>(evt => OnMouseEventInViewPortInternal?.Invoke(evt));
  333. m_ViewContainer.RegisterCallback<MouseUpEvent>(evt => OnMouseEventInViewPortInternal?.Invoke(evt));
  334. m_ViewContainer.RegisterCallback<MouseMoveEvent>(evt => OnMouseEventInViewPortInternal?.Invoke(evt));
  335. m_Views[(int)ViewIndex.First] = new Image() { name = Style.k_FirstViewName, image = Texture2D.blackTexture };
  336. m_ViewContainer.Add(m_Views[(int)ViewIndex.First]);
  337. m_Views[(int)ViewIndex.Second] = new Image() { name = Style.k_SecondViewName, image = Texture2D.blackTexture };
  338. m_ViewContainer.Add(m_Views[(int)ViewIndex.Second]);
  339. m_FirstOrCompositeManipulator = new SwitchableCameraController(
  340. this,
  341. index =>
  342. {
  343. LookDev.currentContext.SetFocusedCamera(index);
  344. var environment = LookDev.currentContext.GetViewContent(index).environment;
  345. if (sidePanel == SidePanel.Environment && environment != null && LookDev.currentContext.environmentLibrary != null)
  346. m_EnvironmentList.selectedIndex = LookDev.currentContext.environmentLibrary.IndexOf(environment);
  347. });
  348. m_SecondManipulator = new CameraController(
  349. this,
  350. () =>
  351. {
  352. LookDev.currentContext.SetFocusedCamera(ViewIndex.Second);
  353. var environment = LookDev.currentContext.GetViewContent(ViewIndex.Second).environment;
  354. if (sidePanel == SidePanel.Environment && environment != null && LookDev.currentContext.environmentLibrary != null)
  355. m_EnvironmentList.selectedIndex = LookDev.currentContext.environmentLibrary.IndexOf(environment);
  356. });
  357. m_GizmoManipulator = new ComparisonGizmoController(m_FirstOrCompositeManipulator);
  358. m_Views[(int)ViewIndex.First].AddManipulator(m_GizmoManipulator); //must take event first to switch the firstOrCompositeManipulator
  359. m_Views[(int)ViewIndex.First].AddManipulator(m_FirstOrCompositeManipulator);
  360. m_Views[(int)ViewIndex.Second].AddManipulator(m_SecondManipulator);
  361. m_NoObject1 = new Label(Style.k_DragAndDropObject);
  362. m_NoObject1.style.flexGrow = 1;
  363. m_NoObject1.style.unityTextAlign = TextAnchor.MiddleCenter;
  364. m_NoObject2 = new Label(Style.k_DragAndDropObject);
  365. m_NoObject2.style.flexGrow = 1;
  366. m_NoObject2.style.unityTextAlign = TextAnchor.MiddleCenter;
  367. m_NoEnvironment1 = new Label(Style.k_DragAndDropEnvironment);
  368. m_NoEnvironment1.style.flexGrow = 1;
  369. m_NoEnvironment1.style.unityTextAlign = TextAnchor.MiddleCenter;
  370. m_NoEnvironment1.style.whiteSpace = WhiteSpace.Normal;
  371. m_NoEnvironment2 = new Label(Style.k_DragAndDropEnvironment);
  372. m_NoEnvironment2.style.flexGrow = 1;
  373. m_NoEnvironment2.style.unityTextAlign = TextAnchor.MiddleCenter;
  374. m_NoEnvironment2.style.whiteSpace = WhiteSpace.Normal;
  375. m_Views[(int)ViewIndex.First].Add(m_NoObject1);
  376. m_Views[(int)ViewIndex.First].Add(m_NoEnvironment1);
  377. m_Views[(int)ViewIndex.Second].Add(m_NoObject2);
  378. m_Views[(int)ViewIndex.Second].Add(m_NoEnvironment2);
  379. }
  380. void CreateDropAreas()
  381. {
  382. // GameObject or Prefab in view
  383. new DropArea(new[] { typeof(GameObject) }, m_Views[(int)ViewIndex.First], (obj, localPos) =>
  384. {
  385. if (viewLayout == Layout.CustomSplit)
  386. OnChangingObjectInViewInternal?.Invoke(obj as GameObject, ViewCompositionIndex.Composite, localPos);
  387. else
  388. OnChangingObjectInViewInternal?.Invoke(obj as GameObject, ViewCompositionIndex.First, localPos);
  389. m_NoObject1.style.visibility = obj == null || obj.Equals(null) ? Visibility.Visible : Visibility.Hidden;
  390. });
  391. new DropArea(new[] { typeof(GameObject) }, m_Views[(int)ViewIndex.Second], (obj, localPos) =>
  392. {
  393. OnChangingObjectInViewInternal?.Invoke(obj as GameObject, ViewCompositionIndex.Second, localPos);
  394. m_NoObject2.style.visibility = obj == null || obj.Equals(null) ? Visibility.Visible : Visibility.Hidden;
  395. });
  396. // Material in view
  397. //new DropArea(new[] { typeof(GameObject) }, m_Views[(int)ViewIndex.First], (obj, localPos) =>
  398. //{
  399. // if (layout == Layout.CustomSplit || layout == Layout.CustomCircular)
  400. // OnChangingMaterialInViewInternal?.Invoke(obj as Material, ViewCompositionIndex.Composite, localPos);
  401. // else
  402. // OnChangingMaterialInViewInternal?.Invoke(obj as Material, ViewCompositionIndex.First, localPos);
  403. //});
  404. //new DropArea(new[] { typeof(Material) }, m_Views[(int)ViewIndex.Second], (obj, localPos)
  405. // => OnChangingMaterialInViewInternal?.Invoke(obj as Material, ViewCompositionIndex.Second, localPos));
  406. // Environment in view
  407. new DropArea(new[] { typeof(Environment), typeof(Cubemap) }, m_Views[(int)ViewIndex.First], (obj, localPos) =>
  408. {
  409. if (viewLayout == Layout.CustomSplit)
  410. OnChangingEnvironmentInViewInternal?.Invoke(obj, ViewCompositionIndex.Composite, localPos);
  411. else
  412. OnChangingEnvironmentInViewInternal?.Invoke(obj, ViewCompositionIndex.First, localPos);
  413. m_NoEnvironment1.style.visibility = obj == null || obj.Equals(null) ? Visibility.Visible : Visibility.Hidden;
  414. });
  415. new DropArea(new[] { typeof(Environment), typeof(Cubemap) }, m_Views[(int)ViewIndex.Second], (obj, localPos) =>
  416. {
  417. OnChangingEnvironmentInViewInternal?.Invoke(obj, ViewCompositionIndex.Second, localPos);
  418. m_NoEnvironment2.style.visibility = obj == null || obj.Equals(null) ? Visibility.Visible : Visibility.Hidden;
  419. });
  420. // Environment in library
  421. //new DropArea(new[] { typeof(Environment), typeof(Cubemap) }, m_EnvironmentContainer, (obj, localPos) =>
  422. //{
  423. // //[TODO: check if this come from outside of library]
  424. // OnAddingEnvironmentInternal?.Invoke(obj);
  425. //});
  426. new DropArea(new[] { typeof(EnvironmentLibrary) }, m_EnvironmentContainer, (obj, localPos) =>
  427. {
  428. OnChangingEnvironmentLibraryInternal?.Invoke(obj as EnvironmentLibrary);
  429. RefreshLibraryDisplay();
  430. });
  431. }
  432. Rect IViewDisplayer.GetRect(ViewCompositionIndex index)
  433. {
  434. switch (index)
  435. {
  436. case ViewCompositionIndex.First:
  437. case ViewCompositionIndex.Composite: //display composition on first rect
  438. return m_Views[(int)ViewIndex.First].contentRect;
  439. case ViewCompositionIndex.Second:
  440. return m_Views[(int)ViewIndex.Second].contentRect;
  441. default:
  442. throw new ArgumentException("Unknown ViewCompositionIndex: " + index);
  443. }
  444. }
  445. Vector2 m_LastFirstViewSize = new Vector2();
  446. Vector2 m_LastSecondViewSize = new Vector2();
  447. void IViewDisplayer.SetTexture(ViewCompositionIndex index, Texture texture)
  448. {
  449. if (texture == null)
  450. return;
  451. bool updated = false;
  452. switch (index)
  453. {
  454. case ViewCompositionIndex.First:
  455. case ViewCompositionIndex.Composite: //display composition on first rect
  456. if (updated |= m_Views[(int)ViewIndex.First].image != texture)
  457. m_Views[(int)ViewIndex.First].image = texture;
  458. else if (updated |= (m_LastFirstViewSize.x != texture.width
  459. || m_LastFirstViewSize.y != texture.height))
  460. {
  461. m_Views[(int)ViewIndex.First].image = null; //force refresh else it will appear zoomed
  462. m_Views[(int)ViewIndex.First].image = texture;
  463. }
  464. if (updated)
  465. {
  466. m_LastFirstViewSize.x = texture?.width ?? 0;
  467. m_LastFirstViewSize.y = texture?.height ?? 0;
  468. }
  469. break;
  470. case ViewCompositionIndex.Second:
  471. if (m_Views[(int)ViewIndex.Second].image != texture)
  472. m_Views[(int)ViewIndex.Second].image = texture;
  473. else if (updated |= (m_LastSecondViewSize.x != texture.width
  474. || m_LastSecondViewSize.y != texture.height))
  475. {
  476. m_Views[(int)ViewIndex.Second].image = null; //force refresh else it will appear zoomed
  477. m_Views[(int)ViewIndex.Second].image = texture;
  478. }
  479. if (updated)
  480. {
  481. m_LastSecondViewSize.x = texture?.width ?? 0;
  482. m_LastSecondViewSize.y = texture?.height ?? 0;
  483. }
  484. break;
  485. default:
  486. throw new ArgumentException("Unknown ViewCompositionIndex: " + index);
  487. }
  488. }
  489. void IViewDisplayer.Repaint() => Repaint();
  490. void ApplyLayout(Layout value)
  491. {
  492. m_NoObject1.style.visibility = LookDev.currentContext.GetViewContent(ViewIndex.First).hasViewedObject ? Visibility.Hidden : Visibility.Visible;
  493. m_NoObject2.style.visibility = LookDev.currentContext.GetViewContent(ViewIndex.Second).hasViewedObject ? Visibility.Hidden : Visibility.Visible;
  494. m_NoEnvironment1.style.visibility = LookDev.currentContext.GetViewContent(ViewIndex.First).hasEnvironment ? Visibility.Hidden : Visibility.Visible;
  495. m_NoEnvironment2.style.visibility = LookDev.currentContext.GetViewContent(ViewIndex.Second).hasEnvironment ? Visibility.Hidden : Visibility.Visible;
  496. switch (value)
  497. {
  498. case Layout.HorizontalSplit:
  499. case Layout.VerticalSplit:
  500. if (!m_ViewContainer.ClassListContains(Style.k_FirstViewClass))
  501. m_ViewContainer.AddToClassList(Style.k_FirstViewClass);
  502. if (!m_ViewContainer.ClassListContains(Style.k_SecondViewsClass))
  503. m_ViewContainer.AddToClassList(Style.k_SecondViewsClass);
  504. if (value == Layout.VerticalSplit)
  505. {
  506. m_ViewContainer.AddToClassList(Style.k_VerticalViewsClass);
  507. if (!m_ViewContainer.ClassListContains(Style.k_VerticalViewsClass))
  508. m_ViewContainer.AddToClassList(Style.k_FirstViewClass);
  509. }
  510. for (int i = 0; i < 2; ++i)
  511. m_Views[i].style.display = DisplayStyle.Flex;
  512. break;
  513. case Layout.FullFirstView:
  514. case Layout.CustomSplit: //display composition on first rect
  515. if (!m_ViewContainer.ClassListContains(Style.k_FirstViewClass))
  516. m_ViewContainer.AddToClassList(Style.k_FirstViewClass);
  517. if (m_ViewContainer.ClassListContains(Style.k_SecondViewsClass))
  518. m_ViewContainer.RemoveFromClassList(Style.k_SecondViewsClass);
  519. m_Views[0].style.display = DisplayStyle.Flex;
  520. m_Views[1].style.display = DisplayStyle.None;
  521. break;
  522. case Layout.FullSecondView:
  523. if (m_ViewContainer.ClassListContains(Style.k_FirstViewClass))
  524. m_ViewContainer.RemoveFromClassList(Style.k_FirstViewClass);
  525. if (!m_ViewContainer.ClassListContains(Style.k_SecondViewsClass))
  526. m_ViewContainer.AddToClassList(Style.k_SecondViewsClass);
  527. m_Views[0].style.display = DisplayStyle.None;
  528. m_Views[1].style.display = DisplayStyle.Flex;
  529. break;
  530. default:
  531. throw new ArgumentException("Unknown Layout");
  532. }
  533. //Add flex direction here
  534. if (value == Layout.VerticalSplit)
  535. m_ViewContainer.AddToClassList(Style.k_VerticalViewsClass);
  536. else if (m_ViewContainer.ClassListContains(Style.k_VerticalViewsClass))
  537. m_ViewContainer.RemoveFromClassList(Style.k_VerticalViewsClass);
  538. }
  539. void ApplySidePanelChange(SidePanel sidePanel)
  540. {
  541. IStyle GetEnvironmentContenairDraggerStyle()
  542. => m_EnvironmentContainer.Q(className: "unity-base-slider--vertical").Q("unity-dragger").style;
  543. if (sidePanel == SidePanel.Environment)
  544. {
  545. if (!m_MainContainer.ClassListContains(Style.k_ShowEnvironmentPanelClass))
  546. m_MainContainer.AddToClassList(Style.k_ShowEnvironmentPanelClass);
  547. if (m_EnvironmentList.selectedIndex != -1)
  548. m_EnvironmentContainer.Q<EnvironmentElement>().style.visibility = Visibility.Visible;
  549. GetEnvironmentContenairDraggerStyle().display = DisplayStyle.Flex;
  550. m_EnvironmentContainer.style.display = DisplayStyle.Flex;
  551. }
  552. else
  553. {
  554. if (m_MainContainer.ClassListContains(Style.k_ShowEnvironmentPanelClass))
  555. m_MainContainer.RemoveFromClassList(Style.k_ShowEnvironmentPanelClass);
  556. m_EnvironmentContainer.Q<EnvironmentElement>().style.visibility = Visibility.Hidden;
  557. GetEnvironmentContenairDraggerStyle().display = DisplayStyle.None;
  558. m_EnvironmentContainer.style.display = DisplayStyle.None;
  559. }
  560. if (sidePanel == SidePanel.Debug)
  561. {
  562. if (!m_MainContainer.ClassListContains(Style.k_ShowDebugPanelClass))
  563. m_MainContainer.AddToClassList(Style.k_ShowDebugPanelClass);
  564. UpdateSideDebugPanelProperties();
  565. }
  566. else
  567. {
  568. if (m_MainContainer.ClassListContains(Style.k_ShowDebugPanelClass))
  569. m_MainContainer.RemoveFromClassList(Style.k_ShowDebugPanelClass);
  570. }
  571. }
  572. void Update()
  573. {
  574. if (LookDev.waitingConfigure)
  575. return;
  576. // [case 1245086] Guard in case the SRP asset is set to null (or to a not supported SRP) when the lookdev window is already open
  577. // Note: After an editor reload, we might get a null SRP for a couple of frames, hence the check.
  578. if (!LookDev.supported)
  579. {
  580. // Print an error and close the Lookdev window (to avoid spamming the console)
  581. if (RenderPipelineManager.currentPipeline != null)
  582. Debug.LogError("LookDev is not supported by this Scriptable Render Pipeline: " + RenderPipelineManager.currentPipeline.ToString());
  583. else if (GraphicsSettings.currentRenderPipeline != null)
  584. Debug.LogError("LookDev is not available until a camera render occurs.");
  585. else
  586. Debug.LogError("LookDev is not supported: No SRP detected.");
  587. LookDev.Close();
  588. }
  589. // All those states coming from the Contexts can become invalid after a domain reload so we need to update them.
  590. m_FirstOrCompositeManipulator.UpdateCameraState(LookDev.currentContext);
  591. m_SecondManipulator.UpdateCameraState(LookDev.currentContext, ViewIndex.Second);
  592. m_GizmoManipulator.UpdateGizmoState(LookDev.currentContext.layout.gizmoState);
  593. }
  594. void OnGUI()
  595. {
  596. if(EditorApplication.isUpdating)
  597. return;
  598. //deal with missing style on domain reload...
  599. ReloadStyleSheets();
  600. OnUpdateRequestedInternal?.Invoke();
  601. }
  602. }
  603. }