-
Notifications
You must be signed in to change notification settings - Fork 310
Description
I wanted to have a button that would behave like a sprite button for the background: one sprite by default, a different sprite when it's highlighted, and another for when it's pressed, but also have the ability to set the text dynamically.
To get this behavior I need to set text position dynamically for when button is in different states. Since there are no public events for when button is highlighted, selected, returns to default state, I need to either inherit from the Button class or copy paste the code and make my own class. I decided to inherit from the Button class:
[AddComponentMenu("UI/My Button", 30)]
public class MyButton : Button {
HorizontalLayoutGroup HorizontalLayoutGroup;
int NormalTextTopPadding;
int NormalTextBottomPadding;
[SerializeField] int HighlightedTextBottomPadding;
[SerializeField] int PressedTextBottomPadding;
void Awake() {
HorizontalLayoutGroup = GetComponent<HorizontalLayoutGroup>();
NormalTextTopPadding = HorizontalLayoutGroup.padding.top;
NormalTextBottomPadding = HorizontalLayoutGroup.padding.bottom;
}
protected override void DoStateTransition(SelectionState state, bool instant) {
base.DoStateTransition(state, instant);
if(state == SelectionState.Normal || state == SelectionState.Selected) {
HorizontalLayoutGroup.padding.top = NormalTextTopPadding;
HorizontalLayoutGroup.padding.bottom = NormalTextBottomPadding;
}
if(state == SelectionState.Highlighted) {
HorizontalLayoutGroup.padding.top = NormalTextTopPadding + HighlightedTextBottomPadding;
HorizontalLayoutGroup.padding.bottom = NormalTextBottomPadding - HighlightedTextBottomPadding;
}
if(state == SelectionState.Pressed) {
HorizontalLayoutGroup.padding.top = NormalTextTopPadding + HighlightedTextBottomPadding + PressedTextBottomPadding;
HorizontalLayoutGroup.padding.bottom = NormalTextBottomPadding - HighlightedTextBottomPadding - PressedTextBottomPadding;
}
}
}
This is the class. The first problem that I get is that the editor doesn't draw the properties HighlightedTextBottomPadding
and PressedTextBottomPadding
. I don't understand why, since in the SelectableEditor class it should draw all the child properties:
private void ChildClassPropertiesGUI()
{
if (IsDerivedSelectableEditor())
return;
DrawPropertiesExcluding(serializedObject, m_PropertyPathToExcludeForChildClasses);
}
So what do I do? I write my own editor to draw my properties:
[CustomEditor(typeof(MyButton), true)]
public class MyButtonEditor : SelectableEditor {
SerializedProperty HighlightedTextBottomPadding;
SerializedProperty PressedTextBottomPadding;
protected virtual void OnEnable() {
base.OnEnable();
HighlightedTextBottomPadding = serializedObject.FindProperty("HighlightedTextBottomPadding");
PressedTextBottomPadding = serializedObject.FindProperty("PressedTextBottomPadding");
}
public override void OnInspectorGUI() {
base.OnInspectorGUI();
EditorGUILayout.PropertyField(HighlightedTextBottomPadding);
EditorGUILayout.PropertyField(PressedTextBottomPadding);
serializedObject.ApplyModifiedProperties();
}
}
This starts to draw the MyButton
properties but it stops drawing the original button OnClick
property. That's because I now have a custom editor and IsDerivedSelectableEditor()
returns false and ChildClassPropertiesGUI()
doesn't draw child class properties. A naive thing to try is to add SerializedProperty OnClick;
field to the editor and then find it on Enable: OnClick = serializedObject.FindProperty("m_onClick");
and then draw it: EditorGUILayout.PropertyField(OnClick);
. Again, for some reason it doesn't work(FindProperty
returns null), even considering the MyButton
object does have m_onClick
property: it inherits it from Button
class.
So, how do I fix that problem? I have to write my own ButtonEditor
class for Button
and then inherit from that instead in my own MyButtonEditor
:
[CustomEditor(typeof(Button), true)]
public class ButtonEditor : SelectableEditor {
SerializedProperty OnClick;
protected virtual void OnEnable() {
base.OnEnable();
OnClick = serializedObject.FindProperty("m_OnClick");
}
public override void OnInspectorGUI() {
base.OnInspectorGUI();
EditorGUILayout.PropertyField(OnClick);
serializedObject.ApplyModifiedProperties();
}
}
Now with all those changes I(finally) have my own button with the behavior I want. But it's too much code for something simple like that. It would be nice to just write MyButton
class and be done with that. Not sure why SelectableEditor
only iterates over Button
properties but not properties of my child class.