| marp | theme | class |
|---|---|---|
true |
default |
class MyProjectScript : EditorTool
{
public override void OnToolGUI()
{
// ... ?
}
}
class MyProjectScript : EditorTool
{
OverlayWindow m_Overlay;
void OnEnable()
[
m_Overlay = new OverlayWindow(
new GUIContent("My Overlay"),
OverlayGUI,
int.MaxValue,
null,
SceneViewOverlay.WindowDisplayOption.MultipleWindowsPerTarget);
}
public override void OnToolGUI()
{
SceneViewOverlay.ShowWindow(m_Overlay);
}
void OverlayGUI(Object target, SceneView sceneView)
{
GUILayout.Label("hello!");
}
}
- IMGUI only
- Anchored to bottom right of screen
- Not resizable
- Internal API
- No consistency for third party tools
- Class implementing
Overlay - Tagged with
OverlayAttribute
public abstract class Overlay
{
// Less interesting properties omitted
public UnityEditor.EditorWindow containerWindow { get; }
public bool displayed { get; set; }
public string displayName { get; set; }
public bool floating { get; }
public UnityEngine.Vector2 floatingPosition { get; set; }
public string id { get; }
public abstract VisualElement CreatePanelContent();
protected virtual void OnCollapsed();
public virtual void OnDestroy();
protected virtual void OnExpanded();
public virtual void OnInitialize();
public virtual void OnPopupWindowDestroy(EditorWindow window);
public virtual void OnPopupWindowInitialize(EditorWindow window);
public void Undock();
}public sealed class OverlayAttribute : System.Attribute
{
public string displayName { get; }
public System.Type editorWindowType { get; }
public string id { get; }
public OverlayAttribute(Type editorWindowType, string displayName, bool defaultLayout = False) {}
public OverlayAttribute(System.Type editorWindowType, string id, string displayName, bool defaultLayout = False) {}
public OverlayAttribute(System.Type editorWindowType, string id, string displayName, string ussName, bool defaultLayout = False) {}
}using UnityEditor;
using UnityEditor.Overlays;
using UnityEngine.UIElements;
[Overlay(typeof(SceneView), "Selection Count")]
[Icon("MyPackage/Icons/SelectionCount.png")]
public class SelectionCount : Overlay
{
Label m_Label;
public override void OnInitialize() => Selection.selectionChanged += UpdateLabel;
public override void OnDestroy() => Selection.selectionChanged -= UpdateLabel;
public override VisualElement CreatePanelContent()
{
return m_Label = new Label($"Selection Contains {Selection.count} objects(s)");
}
void UpdateLabel()
{
if (m_Label != null)
m_Label.text = $"Selection contains {Selection.count} objects(s)";
}
}[Overlay(typeof(SceneView), "Selection Count")]
[Icon("MyPackage/Icons/SelectionCount.png")] // <-Optional- Register Overlay as applicable to Scene View, with display name.
IconAttributeis not specific toOverlay. It is a simple way to define an icon for aMonoBehaviourthat respects the built-in naming conventions (ex, "d_" and "@2x")- Not required
- If no
Iconis found theOverlaywill create one from first two significant letters.
public class SelectionCount : Overlay- All Overlays inherit
Overlayclass.
Label m_Label;
public override void OnInitialize() => Selection.selectionChanged += UpdateLabel;
public override void OnDestroy() => Selection.selectionChanged -= UpdateLabel;- Use
OnInitializeandOnDestroyto manage lifecycle resources.
public override VisualElement CreatePanelContent()
{
return m_Label = new Label($"Selection Contains {Selection.count} objects(s)");
}CreatePanelContentexpects that a newVisualElementis returned each call.- This is a different pattern than appending to
rootVisualElementdirectly, as withEditorWindowfor example.
void UpdateLabel()
{
if (m_Label != null)
m_Label.text = $"Selection contains {Selection.count} objects(s)";
}
}- Manage your
UI Elementscontent as usual
- We've already refactored all existing overlays in trunk
IMGUIContainerworks out of the box- ...but preferably just spend a few moments to rewrite using UI Elements
- A reusable
VisualElementwithEditorToolbarElementattribute (ex)EditorToolbarToggleEditorToolbarDropdownEditorToolbarButton
- An
Overlayimplementing theToolbarOverlaytype- Specialized
Overlayto provide content for horizontal and vertical toolbars
- Specialized
[EditorToolbarElement("SceneView/Lighting", typeof(SceneView))]
sealed class SceneLightingElement : EditorToolbarToggle, IAccessContainerWindow
{
public object containerWindow { get; set; }
SceneView sceneView => context as SceneView;
public SceneLightingElement()
{
name = "SceneviewLighting";
RegisterValueChangedCallback(evt => sceneView.sceneLighting = evt.newValue);
}
}[Overlay(typeof(SceneView), k_Id,"SceneView Settings",true)]
class SceneViewToolBar : ToolbarOverlay
{
const string k_Id = "unity-scene-view-toolbar";
protected override void PopulateToolbar(EditorToolbar toolbar)
{
toolbar.AddElement("SceneView/Camera Mode");
toolbar.AddElement("SceneView/2D");
toolbar.AddElement("SceneView/Lighting");
// ...
}
} [EditorToolbarElement("SceneView/Lighting", typeof(SceneView))]EditorToolbarElementis the attribute used to identify pieces of a Toolbar.
sealed class SceneLightingElement : EditorToolbarToggle, IAccessContainerWindow- Just a
VisualElementthat is styled correctly for a toolbar - We provide out of the box a set of default elements (
EditorToolbar{Button, Toggle, Dropdown, ...}) - Can author custom
VisualElementas well IAccessContainerWindowprovides access to theOverlay.containerWindow
public SceneLightingElement()
{
name = "SceneviewLighting";
tooltip = L10n.Tr("When toggled on, the Scene lighting is used. When toggled off, a light attached to the Scene view camera is used.");
RegisterCallback<AttachToPanelEvent>(OnAttachedToPanel);
RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);
this.RegisterValueChangedCallback(evt => sceneView.sceneLighting = evt.newValue);
SceneViewToolbarElements.AddStyleSheets(this);
}
// ... implementation- Otherwise this is authored exactly like a typical
VisualElement
[Overlay(typeof(SceneView), k_Id,"SceneView toolbar",true)]OverlayAttributeis unchanged (optionalidanddefaultLayoutparams shown here)
protected override void PopulateToolbar(EditorToolbar toolbar)
{
toolbar.AddElement("SceneView/Camera Mode");
// ...
}- This is the only function a
ToolbarOverlayneeds to implement - Add existing
EditorToolbarElementitems identified by theEditorToolbarElement.idproperty






