Prevent clicking on a pre-existing button

Hey all. I want to prevent clicks on a pre-existing piece of UI I have no control on (specifically, on the Overrides dropdown that is in the Prefab’s inspector).

The Inspector is in IMGUI.

I have found a way to draw things in it (see blue box above). I also found the rect of the dropdown.

However, how do I ensure that when you click on the blue box (or whatever I draw there), the Overrides dropdown doesn’t open? I need to stop clicks from going through.

PS: I have no control over that UI, so I can’t use GUI.enabled = false;

Thanks.

I haven’t used IMGUI for ages and currently I can’t test it, but an idea, try it and ignore it if it doesn’t work. :slight_smile:
So what I would try is this:

  • in theory you should get OnGUI event when the user hit the icon: https://docs.unity3d.com/ScriptReference/Event.html Although it is possible that it is per MonoBehaviour, so it won’t happen when other inspectors run…
  • The Event.current should carry information about that click, find out how to identify it (if you get event about it)
  • Then call the Use() method on it, so it (in theory) doesn’t get used by other systems

Again, I have no idea if it is a working solution or not, just an idea to be tested because currently I can’t.

1 Like

I mean, if you’re on anything beyond, what was it, 2021 or 2022(?), then there is some UI Toolkit involved:

(Sorry for the large image)

I believe you can use reflection to get the internal Inspector EditorWindow, and then you could possibly prevent Event propagation through these means as well.

This is not very pretty but it’s working:

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

public static class PreventPrefabOverrideWindow
{
    [InitializeOnLoadMethod]
    public static void DrawFilterHeader()
    {
        Editor.finishedDefaultHeaderGUI -= DrawInspectorHeader;
        Editor.finishedDefaultHeaderGUI += DrawInspectorHeader;
    }

    private static Type s_prefabOverrideWindowType = Type.GetType("UnityEditor.PrefabOverridesWindow,UnityEditor");
    private static FieldInfo s_windowContentField = typeof(PopupWindow).GetField("m_WindowContent", BindingFlags.Instance | BindingFlags.NonPublic);
  
    private static void DrawInspectorHeader(Editor _obj)
    {
        Object[] popupWindows = Resources.FindObjectsOfTypeAll(typeof (PopupWindow));
        foreach(Object popupWindowAsObject in popupWindows)
        {
            PopupWindow popupWindow = popupWindowAsObject as PopupWindow;
            if (s_windowContentField.GetValue(popupWindow).GetType() == s_prefabOverrideWindowType)
                popupWindow.Close();
        }
    }
}

Add a headerGUI to catch when a PrefabOverridesWindow is opened and close it instantly.

2 Likes

GameObjectInspector is the one drawing the button, specifically in DoPrefabButtons. I can’t spot anything in there that’s cleverer or cleaner than what @OlivierUbi is suggesting. If you were able to temporarily set m_ButtonStates to not have the CanShowOverrides flag, you could prevent the button from showing up entirely, but even if you fall back to doing that for reflection, I don’t quite know what entry point you would use for that.

It could be, though I’m not sure, that if you draw your blue box on top of the dropdown you want to block, and eat input events (by having it be a button), you might prevent the click from propagating, so it’s at least worth trying. You might have to do the pixel offsets manually and then hope real hard that the button position doesn’t move :stuck_out_tongue:

If this was implemented in UITK instead of inside an IMGUIContainer, you could just Q for the dropdown and set it’s click handler in like three lines of code, without any need for reflection or digging through the source code. UITK is so good at allowing you to just hack stuff.

3 Likes

I’ve already try it and the event is used(eaten) by GameObjectInspector before you could execute any code.

UITK is a good idea but i’m not an expert.

1 Like

This worked like a charm!! Thanks!

I will offer in return my monstruosity of a code to replicate a button that is the same size and position as the Overrides dropdown, which I draw as disabled on top of the dropdown so it communicates to the user that is not clickable :smile:

9758061--1397394--Screenshot 2024-04-08 alle 23.32.18.png

With this code the button should resize correctly even if the Inspector is stretched. At least in Unity 2022.3.

// Draw the overlaid button
float currentView = EditorGUIUtility.currentViewWidth;
GUILayout.BeginArea(new Rect(66f, 87f, currentView - 66f - 4f, EditorGUIUtility.singleLineHeight));
GUILayout.BeginHorizontal();

GUI.enabled = false;
Color prevContentColor = GUI.contentColor;

// Draw the Overrides dropdown button, semi-transparent
GUI.contentColor = Color.clear;
GUILayout.Button("Overridesn");

// Draw the other two buttons but invisible
Color prevColor = GUI.color;
Color prevColorBg = GUI.backgroundColor;
GUI.color = Color.clear;
GUI.backgroundColor = Color.clear;

GUILayout.Button("",GUILayout.MaxWidth(27), GUILayout.MinWidth(4));
GUILayout.Button(EditorGUIUtility.TrTextContent("Select"), EditorStyles.miniButton);
GUILayout.Button(EditorGUIUtility.TrTextContent("Open"), EditorStyles.miniButton);
GUILayout.EndHorizontal();
GUILayout.EndArea();

GUI.enabled = true;
GUI.color = prevColor;
GUI.backgroundColor = prevColorBg;
GUI.contentColor = prevContentColor;

It can go right after the code to close the dropdown.

I know there is a cleaner way to create a semi-transparent element than just disabling the GUI, but I couldn’t be bothered :smile:

And yes, it’s not typo… “Overridesn” as text makes a button that is exactly the length of the Overrides Dropdown!

5 Likes

I bet you didn’t think this would be one of the hardest part when you sat down to write Black Box, did you?

1 Like

The amusing part of all this is that there was at least half a dozen ways to accomplish the task at hand.

Not sure what that says about Unity.

It’s a bit messy, but honestly… that is quite flexible? I’m not sure how many software have this deep level of being able to get your hands dirty and not just add new tools, but override such a fundamental piece as the Game object header. Maybe Blender? (I’m not sure how other game engines fare in this respect)

Hehe no. But also, when I started the plugin it was all about hiding and locking.

But it feels like the most powerful aspect of it is revealing “just a little”, which brings up the question of how to lock again what you have revealed. That, indeed, is damn hard!

1 Like