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.
IconAttribute
is not specific toOverlay
. It is a simple way to define an icon for aMonoBehaviour
that respects the built-in naming conventions (ex, "d_" and "@2x")- Not required
- If no
Icon
is found theOverlay
will create one from first two significant letters.
public class SelectionCount : Overlay
- All Overlays inherit
Overlay
class.
Label m_Label;
public override void OnInitialize() => Selection.selectionChanged += UpdateLabel;
public override void OnDestroy() => Selection.selectionChanged -= UpdateLabel;
- Use
OnInitialize
andOnDestroy
to manage lifecycle resources.
public override VisualElement CreatePanelContent()
{
return m_Label = new Label($"Selection Contains {Selection.count} objects(s)");
}
CreatePanelContent
expects that a newVisualElement
is returned each call.- This is a different pattern than appending to
rootVisualElement
directly, as withEditorWindow
for example.
void UpdateLabel()
{
if (m_Label != null)
m_Label.text = $"Selection contains {Selection.count} objects(s)";
}
}
- Manage your
UI Elements
content as usual
- We've already refactored all existing overlays in trunk
IMGUIContainer
works out of the box- ...but preferably just spend a few moments to rewrite using UI Elements
- A reusable
VisualElement
withEditorToolbarElement
attribute (ex)EditorToolbarToggle
EditorToolbarDropdown
EditorToolbarButton
- An
Overlay
implementing theToolbarOverlay
type- Specialized
Overlay
to 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))]
EditorToolbarElement
is the attribute used to identify pieces of a Toolbar.
sealed class SceneLightingElement : EditorToolbarToggle, IAccessContainerWindow
- Just a
VisualElement
that is styled correctly for a toolbar - We provide out of the box a set of default elements (
EditorToolbar{Button, Toggle, Dropdown, ...}
) - Can author custom
VisualElement
as well IAccessContainerWindow
provides 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)]
OverlayAttribute
is unchanged (optionalid
anddefaultLayout
params shown here)
protected override void PopulateToolbar(EditorToolbar toolbar)
{
toolbar.AddElement("SceneView/Camera Mode");
// ...
}
- This is the only function a
ToolbarOverlay
needs to implement - Add existing
EditorToolbarElement
items identified by theEditorToolbarElement.id
property