100% found this document useful (1 vote)
167 views17 pages

(2019.1) UIElements Migration Guide

This document provides guidance on migrating to the final UIElements API released in Unity 2019.1. Key changes include namespace and method name changes, removal of obsolete APIs, and structural changes to built-in controls that now include labels. Styling classes are also different and the document provides details on the new class names for each control.

Uploaded by

Svinčnik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
167 views17 pages

(2019.1) UIElements Migration Guide

This document provides guidance on migrating to the final UIElements API released in Unity 2019.1. Key changes include namespace and method name changes, removal of obsolete APIs, and structural changes to built-in controls that now include labels. Styling classes are also different and the document provides details on the new class names for each control.

Uploaded by

Svinčnik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

UIElements migration guide

In 2019.1 UIElements is officially releasing and not experimental anymore.

This document aims at helping you in the process of migrating / validating the use of the API.
It is not exhaustive and focuses on the most likely breakage you might encounter.
You can always get in touch with us if you don’t know how to replace an old API call or for any
other migration issue.

C# API breaking changes


Note:​ All Obsolete symbols from the experimental API were removed. It might be worth fixing
​ pgrading to the final API.
those ​before u

Namespace changes

- ​UnityEditor.Experimental.UIElements​ became ​UnityEditor.UIElements


- ​UnityEngine.Experimental.UIElements​ became ​UnityEngine.UIElements
- ​UnityEngine.Experimental.UIElements.StyleEnums ​and
UnityEngine.Experimental.UIElements.StyleSheets​ are not needed anymore

VisualElement API changes

Accessor of inline style (​VisualElement.style​) have changed their underlying type


(​StyleValue<T>​ was removed)
Note that this goes along with a semantic change (see section below).

The ​OnStylesResolved()​ virtual function was removed and replaced with the
CustomStyleResolvedEvent​ event.

The ​persistenceKey​ property was renamed to ​viewDataKey​.


It is no more possible to implement custom persistency ; we are planning to re-design this part
of the API in a future release.
The ​layout​ property setter is not public anymore. ​style.position​, ​style.top​,
style.left​, ​style.width​ and ​style.height​ should be used instead.
AddStyleSheetPath()​ and related methods were removed. This is to decouple UIElements
from resources folders. Instead, use the ​styleSheets​ property and explicitly load style sheets
via the ​Resources​ class or ​AssetDatabase​ class.

The ​shadow​ property was renamed ​hierarchy.

VisualElement does not implement the IEnumerable interface anymore.


Use the ​Children()​ method or UQuery instead.

The ​clippingOptions​ property is now split between the ​cacheAsBitmap​ and


style.overflow ​properties​. ​Set c ​ acheAsBitmap​ to true to trigger bitmap caching, which
requires that the elements receives has the ​overflow​ property value set to
Overflow.Hidden​ (from C# or USS).

The ​dataWatch​ property was removed. This feature will not be available anymore. One can
use ​SerializedProperty​ bindings instead.

The​ DoRepaint()​ method cannot be overridden directly. Use the ​ImmediateModeElement


class to implement custom painting. New APIs will be introduced in a future release for
lower-level rendering primitives.

The ​focusIndex​ property was removed. It’s no longer necessary to specify an index for an
element to be focusable, setting ​element.focusable=true​ is sufficient. ​focusIndex​ was
renamed to ​tabIndex​.

Other API changes

Calls to​ EditorWindow.GetRootVisualContainer()​ must be replaced by accessing the


EditorWindow.rootVisualElement​ property.

The ​INotifyValueChanged​ interface does not contain method for registering callbacks
anymore. Those were moved to extension methods.
The ​OnValueChanged()​ method was renamed ​RegisterValueChangedCallback()​.
The ​RemoveValueChanged()​ method was renamed
UnregisterValueChangedCallback()​.

VisualTreeAsset.CloneTree()​ does not accept a dictionary anymore (reflecting the


removal of the slots feature).
It’s also now possible to call this method without any argument.
The ​DropdownMenu.MenuAction​ was renamed ​DropdownMenuAction ​and
DropdownMenuAction.StatusFlag​ was renamed ​DropdownMenuAction.Status.

Semantic API changes

Inline styles vs. resolved styles

The ​VisualElement.styles​ property was previously reflecting both inline styles added via
the C# and resolved styles coming from style sheets. The ​VisualElement.style​ object now
only reflects properties defined in C#. The ​resolvedStyles​ property must be used to query
actual values coming from both style sheets and C#.

Persistence changes

Elements in the physical hierarchy of another element will only persist their view data if their
physical root has ​viewDataKey​ defined.

Styling and structural changes on built-in controls

BaseField​ and derived classes

Most built-in controls were refactored in order to include a label when necessary in the
hierarchy. This means the hierarchy of a field is now comprising a container, a label (present or
not depending on the value of the ​label​ attribute) and the field itself (the inner input).

The following fields are affected by this change:

ColorField TextField
CurveField DoubleField
GradientField FloatField
ObjectField IntegerField
Toggle LongField

MinMaxSlider BoundsField
Slider BoundsIntField
SliderInt RectField
RectIntField
EnumField Vector2Field
MaskField Vector2IntField
PopupField Vector3Field
LayerMaskField Vector3IntField
LayerField Vector4Field
TagField

Currently, the way to register a callback on inner inputs is by using UQuery. Here is an example
of setting a ​KeyDownEvent​ callback on a textfield, using UQuery and the inner element class
name :

var nameTextField = new TextField();


nameTextField.Q("unity-text-input").RegisterCallback<KeyDownEvent>(OnKeyDown);

This mechanism can be extended to all other callbacks needing information directly from the
inner part of the field.

As for styling, the following class structure is now available to correctly style those fields :

Element Class Name

New Hierarchy Field / Container unity-base-field

Label unity-base-field__label

Inner Input unity-base-field__input

When the label is absent, the ​container​ also has unity-base-field--no-label

When the field label has a dragger, the ​label​ also has unity-base-field__label--with-dragger
(for ​DoubleField, FloatField, IntegerField,
LongField​)

In addition of the above uss class, the following elements can be styled using the following uss
class. The old style values are provided at the end of document in an annex to help figuring out
differences in style.

Field Type Specific Class Name


ColorField unity-color-field

CurveField unity-curve-field
unity-curve-field__content
unity-curve-field__border

GradientField unity-gradient-field
unity-gradient-field__border

ObjectField unity-object-field-display
unity-object-field-display__icon
unity-object-field-display__label
unity-object-field-display--accept-drop

Toggle unity-toggle
unity-toggle--no-text
unity-toggle__checkmark
unity-toggle__text

MinMaxSlider unity-min-max-slider
unity-min-max-slider__tracker
unity-min-max-slider__dragger
unity-min-max-slider__min-thumb
unity-min-max-slider__max-thumb

Slider For both:


SliderInt unity-base-slider
unity-base-slider--horizontal
unity-base-slider--vertical
unity-base-slider__tracker
unity-base-slider__dragger

For each specific slider:


unity-slider
unity-slider-int

EnumField unity-enum-field
unity-enum-field__text

MaskField For all the popup types field:


PopupField unity-base-popup-field
LayerField unity-base-popup-field__text
TagField
LayerMaskField For these two, with the popup base type:
unity-mask-field
unity-popup-field

This one also contains the mask field:


unity-layer-mask-field

These also contain the popup field:


unity-layer-field
unity-tag-field

TextField For all fields:


DoubleField unity-base-text-field
FloatField Inner Input:​ unity-text-input
IntegerField
LongField For specific:
unity-text-field
unity-double-field
unity-float-field
unity-integer-field
unity-long-field

BoundsField Originally, those were composed of 2 groups of a label + Vector3Field.


BoundsIntField Now, those are composed of 2 Vector3Fields or Vector3IntFields.
unity-bounds-field
unity-bounds-field__center-field
unity-bounds-field__extents-field

unity-bounds-int-field
unity-bounds-int-field__position-field
unity-bounds-int-field__size-field

RectField All those fields contains one or more of classes:


RectIntField unity-composite-field
Vector2Field unity-composite-field__field-spacer​: applied for space for fields
Vector2IntField with only 2 components by line: Vector2Field, Vector2IntField, RectField
Vector3Field and RectIntField
Vector3IntField unity-composite-field--multi-line​: applied for fields displayed
Vector4Field on multiple lines: RectField and RectIntField
unity-composite-field__field-group​: applied to each line of a
multi-line field.
unity-composite-field__field​ : applied to each sub field of the
composite field
unity-composite-field__field--first​ : applied to the first sub
field of the line

For each individual field:


unity-rect-field
unity-rect-int-field
unity-vector2-field
unity-vector2-int-field
unity-vector3-field
unity-vector3-int-field
unity-vector4-field

Other controls

For the following classes, the structure is identical but class lists can now be used to assign
styles to them. The default USS files from the editor use those selectors.

Label unity-text-element
unity-label

Button unity-text-element
unity-button

IMGUIContainer unity-imgui-container

USS properties changes


Properties were renamed when possible to be conform to CSS.
Custom properties now need to be prefixed with “--”.

Old property New property

-unity-word-wrap: true | false white-space: normal | nowrap

text-alignment -unity-text-align

position-type: relative | position : relative | absolute


absolute | manual (manual ​is not supported anymore​)

(CurveField class)
curve-color --unity-curve-color

(TextField class)
selection-color --unity-selection-color
cursor-color --unity-cursor-color

(Image class)
image --unity-image
image-size --unity-image-size

(ListView class)
item-height --unity-item-height

We now assign USS classes to all elements. Those classes follow the BEM methodology
(​http://getbem.com/​). We updated the selectors in the default USS files to use these class
names instead the element type name (Label, Button) or element name (#Checkmark). This
change may impact your styling, as the new default USS rules have different, generally higher,
specificity than the previous ones.

We are planning to release the full list of available classes names. Until then you can look at the
static string constants exposed by controls, for example ​DoubleField.ussClassName.

UXML changes
If you specify namespaces in your UXML files, you will need to update them to the use
non-experimental ones.

The UXML slots feature was disabled until further design review.

GraphView changes
The GraphView namespace has moved from
UnityEditor.Experimental.UIElements.GraphView​ to
UnityEditor.Experimental.GraphView​.

Since ​GraphElement​ inherits from ​VisualElement​, all the changes listed in the first section
apply.

GraphView custom style properties were prefixed according to the new rule.

Old property New property

edge-width --edge-width
selected-edge-color --selected-edge-color
ghost-edge-color --ghost-edge-color
segment-size --segment-size
segment-color --segment-color
delete-segment-color --delete-segment-color
layer --layer
spacing --spacing
thick-lines --thick-lines
line-color --line-color
thick-line-color --thick-line-color
grid-background-color --grid-background-color
distance --distance
port-color --port-color
disabled-port-color --disabled-port-color
separator-height --separator-height
separator-extent --separator-extent
animation-duration --animation-duration

Annex 1 - Old Style Values for Fields


The following table will help figuring out the default value for the different fields before the
change of style for UIElements. It should help to figure out how to restyle the different elements
used in the applications.

Field Type Old Style Values

ColorField ColorField {
min-height: 18;
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
}

CurveField CurveField {
min-height: 18;
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
background-color:
rgb(86,86,86);
curve-color: #00ff00;
}

CurveField > CurveFieldContent{


position:absolute;
left:1;
right:1;
bottom:1;
top:1;
overflow:hidden;
}

CurveField > #border


{
position:absolute;
left:0;
right:0;
bottom:0;
top:0;
-unity-slice-left: 3;
-unity-slice-top: 3;
-unity-slice-right: 3;
-unity-slice-bottom: 3;
}

GradientField GradientField {
min-height: 18;
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
}

GradientField > #border


{
position:absolute;
left:0;
right:0;
bottom:0;
top:0;
-unity-slice-left: 3;
-unity-slice-top: 3;
-unity-slice-right: 3;
-unity-slice-bottom: 3;
}

ObjectField ObjectField {
min-height: 16;
flex-direction: row;
margin-left: 4;
margin-top: 4;
margin-right: 4;
margin-bottom: 4;
}
ObjectField > ObjectFieldDisplay {
height: 16;
flex-direction: row;
flex: 1 0 0;
margin-left: 0;
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
-unity-slice-left: 4;
-unity-slice-top: 4;
-unity-slice-right: 4;
-unity-slice-bottom: 4;
}

ObjectField > ObjectFieldDisplay > Image {


margin-left: 2;
margin-top: 2;
margin-right: 0;
margin-bottom: 2;
max-width: 16;
max-height: 16;
}

ObjectField > ObjectFieldDisplay > Label {


flex: 1 0 0;
margin-top: 0;
margin-left: 0;
padding-left: 0;
}

ObjectField > ObjectFieldSelector {


width: 18;
height: 16;
}

Toggle Toggle {
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
padding-top: -1;
padding-bottom: 2;
padding-left: 3;
padding-right: 3;
flex-direction: row;
}
Toggle > #Checkmark {
padding-top: 0;
width:16;
height:15;
flex:0 0 auto;
align-self:Center;
-unity-slice-top: 15;
-unity-slice-left: 16;
}

Toggle > Label {


margin-left: 2;
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
padding-left: 0;
padding-top: 0;
padding-right: 0;
padding-bottom: 0;
}

MinMaxSlider MinMaxSlider {
height: 18;
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
}

MinMaxSlider > #TrackElement {


-unity-slice-left: 3;
-unity-slice-top: 0;
-unity-slice-right: 3;
-unity-slice-bottom: 0;
height: 5;
position:absolute;
right:1;
left:1;
top:7;
}

MinMaxSlider > #DragElement {


-unity-slice-left: 7;
-unity-slice-top: 0;
-unity-slice-right: 7;
-unity-slice-bottom: 0;
margin-top: 5;
width: 12;
height: 12;
position: absolute;
}

MinMaxSlider .thumbelement {
cursor: resize-horizontal;
position:absolute;
}

Slider /* Vertical slider */


SliderInt SliderInt.vertical, Slider.vertical {
width: 12;
}

SliderInt.vertical > #TrackElement,


Slider.vertical > #TrackElement {
border-top-width: 3;
border-bottom-width: 3;
top: 3;
bottom: 3;
left:4;
right:4;
position:absolute;
-unity-slice-top: 3;
-unity-slice-bottom: 3;
width: 5;
}

SliderInt.vertical > #DragElement,


Slider.vertical > #DragElement {
width: 12;
height: 12;
}

/* Horizontal slider */
SliderInt.horizontal, Slider.horizontal {
height: 18;
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
}

SliderInt.horizontal > #TrackElement,


Slider.horizontal > #TrackElement {
-unity-slice-left: 3;
-unity-slice-top: 0;
-unity-slice-right: 3;
-unity-slice-bottom: 0;
height: 5;
position:absolute;
right:1;
left:1;
top:7;
}

SliderInt.horizontal > #DragElement,


Slider.horizontal > #DragElement {
margin-top: 5;
width: 12;
height: 12;
}

EnumField EnumField {
-unity-text-align: middle-left;
height: 16;
font-size: 9;
margin-left: 4;
margin-top: 3;
margin-right: 8;
margin-bottom: 3;
padding-left: 6;
padding-top: 0;
padding-right: 6;
padding-bottom: 3;
-unity-slice-left: 6;
-unity-slice-top: 4;
-unity-slice-right: 14;
-unity-slice-bottom: 4;
}

MaskField .popupField {
PopupField -unity-text-align: middle-left;
LayerField height: 16;
TagField font-size: 9;
LayerMaskField margin-left: 4;
margin-top: 3;
margin-right: 8;
margin-bottom: 3;
padding-left: 6;
padding-top: 0;
padding-right: 6;
padding-bottom: 3;
-unity-slice-left: 6;
-unity-slice-top: 4;
-unity-slice-right: 14;
-unity-slice-bottom: 4;
}

.popupField > .textElement {


overflow: hidden;
}

TextField InputField, FloatField, DoubleField,


DoubleField IntegerField, LongField, TextField {
FloatField min-height: 15;
IntegerField margin-left: 4;
LongField margin-top: 2;
margin-right: 4;
margin-bottom: 2;
padding-left: 3;
padding-top: 1;
padding-right: 3;
padding-bottom: 2;
-unity-slice-left: 3;
-unity-slice-top: 3;
-unity-slice-right: 3;
-unity-slice-bottom: 3;
selection-color: rgba(61,128,223,166);
cursor: text;
overflow: hidden;
}

BoundsField BoundsField > .group {


BoundsIntField flex-direction: row
}

BoundsField > .group > Label {


min-width: 45;
}

BoundsField > .group > Vector3Field {


flex: 1 0 0;
}

RectField .compositeField {
RectIntField flex-direction: row;
Vector2Field flex-wrap: Wrap;
Vector2IntField }
Vector3Field
Vector3IntField .compositeField > .field {
Vector4Field flex-direction: row;
height: 20;
flex: 1 1 140;
}

.compositeField > .field > Label {


min-height: 20;
}

.compositeField > .field > FloatField {


flex: 1 0 0;
}

.compositeField > .field > IntegerField {


flex: 1;
}

Label Label {
margin-left: 4;
margin-top: 2;
margin-right: 4;
margin-bottom: 2;
padding-left: 2;
padding-top: 1;
padding-right: 2;
padding-bottom: 2;
overflow: hidden;
}

Button Button {
-unity-text-align: middle-center;
border-left-width: 6;
border-top-width: 4;
border-right-width: 6;
border-bottom-width: 4;
margin-left: 4;
margin-top: 3;
margin-right: 4;
margin-bottom: 3;
padding-left: 6;
padding-top: 2;
padding-right: 6;
padding-bottom: 3;
-unity-slice-left: 6;
-unity-slice-top: 4;
-unity-slice-right: 6;
-unity-slice-bottom: 4;
}

You might also like