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