I am working on a Unity tool and I want to create a custom GUI for it.
In this simple script, I am checking if the mouse has hovered over a button and if so I change a GUI color. This is just a really basic example, but the same principles apply to something that I want to make.
The problem is that the change is really delayed. I tried implementing isDirty state, where it only repaints when it needs to. Although it doesn't seem to work. Same delay issue... I could just repaint the window every frame, but that is really non-performant.
private bool isDirty = false;
Rect _hoveredRect;
Rect HoveredRect
{
get { return _hoveredRect; }
set
{
if (_hoveredRect != value)
{
isDirty = true;
}
_hoveredRect = value;
}
}
void Update()
{
if (isDirty)
{
Repaint();
isDirty = false;
}
}
void OnGUI()
{
Rect button = new Rect(25, 25, 100, 35);
DrawButton(button, "Label");
}
bool DrawButton(Rect rect, string label)
{
var e = Event.current;
bool hovered = rect.Contains(e.mousePosition);
if (hovered)
{
HoveredRect = rect;
}
if (!hovered && HoveredRect == rect)
{
HoveredRect = Rect.zero;
}
var defaultColor = GUI.color;
GUI.color = hovered ? Color.red : defaultColor;
bool pressed = GUI.Button(rect, label);
GUI.color = defaultColor;
return pressed;
}
Then I came up with another solution, which should work, but I need to get mouse position and I can't use Event.current outside of OnGUI function.
Dictionary<Rect, bool> hoverableRects = new Dictionary<Rect, bool>();
private void OnEnable()
{
EditorApplication.update += UpdateMe;
}
private void OnDisable()
{
EditorApplication.update -= UpdateMe;
}
void UpdateMe()
{
var mousePos = ??; List<Rect> rects = new List<Rect>(hoverableRects.Keys);
foreach (var rect in rects)
{
hoverableRects[rect] = rect.Contains(mousePos);
}
}
void OnGUI()
{
Rect button = new Rect(25, 25, 100, 35);
DrawButton(button, "Label");
}
bool DrawButton(Rect rect, string label)
{
if (!hoverableRects.ContainsKey(rect))
{ hoverableRects.Add(rect, false); }
var defaultColor = GUI.color;
GUI.color = hoverableRects[rect] ? Color.red : defaultColor;
bool pressed = GUI.Button(rect, label);
GUI.color = defaultColor;
return pressed;
}
Is there a way to get mouse position every frame outside the OnGUI method?