Issue with GUI repaint

Hello there,
I am working on a Unity tool and at the moment I am having some difficulties with the GUI repaint.

I want to create a custom GUI. 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. What could be a good solution for this? Thank you

Script:

    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;
    }

I think maybe you can get snappier updates from:

Hey, thanks! I tried using this but it didn’t really make much difference, unfortunately. I think I came up with a solution, although I need to get a mouse position outside on OnGUI. This is an issue as Event.current is null outside OnGUI. Is there a way to get mouse position outside OnGUI function?

The solution (probably not the best, but should work I think, if I can get mouse pos):

    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;
    }

Raw mouse position is always “live” on Input.mousePosition

I tried using Input.mousePosition, but it always return (0, 0, 0) :confused:

Pardon, I missed the part where you said you were working on an editor tool. My bad.

Try this instead:

https://answers.unity.com/questions/829071/get-mouse-position-in-editor-based-on-screen-coord.html

The point is that I need to get mouse position every frame outside the OnGUI, so I am unable to use Event.current. It returns null when I try to access it.
Is there a way to either get mouse on-screen position coordinated or maybe subscribe to some onMouseMoved that fires every time mouse position is changed, not just in this window, but in general?

You might have to pick it up in OnGUI and stick that position in a class instance variable for other parts of the code to use.

Yes, icky, but likely workee… :slight_smile:

Tried that as well, but still has the same delay issue as OnGUI is not called every frame and the position is not constantly updated :
I can’t believe it’s that difficult to get a mouse position… I’ll try to see if I can come up with something I suppose, I’ve been trying to do this an entire day today, this is ridiculous :smile: