- Home /
Get KeyCode events in editor without object selected
I'm trying to write an editor extension that gets keyboard events. There's two ways I've found:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(Transform))]
public class MyScript : Editor
{
void OnSceneGUI()
{
if (Event.current.isKey && Event.current.type == EventType.keyDown)
{
if (Event.current.keyCode == KeyCode.Keypad1)
{
Debug.Log("1 pressed");
}
}
}
}
The code above works, but requires that a gameobject is selected in the scene. Otherwise it will not work.
The second option involves using keyboard shortcuts for menu items:
using UnityEngine;
using UnityEditor;
using System.Collections;
public class MyScript : MonoBehaviour
{
[MenuItem("CustomMenu/Button _1")]
static void Button()
{
Debug.Log("1 pressed");
}
}
The problem with that is that it's very limited in its capabilities. For example, I can't check that the number 1 in the example is from the numpad. I also can't check for certain key combinations such as Ctrl + Numpad 1 because %1
does not work for numpad input.
I need to check for the KeyCode
like in the first example, but not have to have an object selected in the scene. I found this answer but it does not expose an Event
for which I can check the KeyCode
.
How can I get KeyCode
events in the editor scene view without requiring an object to be selected?
Answer by Keavon · Mar 12, 2015 at 11:44 PM
Thanks to kruncher on the Unity IRC, here's a working solution!
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public static class YourCustomSceneView
{
static YourCustomSceneView()
{
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
private static void OnSceneGUI(SceneView sceneView)
{
// Do your general-purpose scene gui stuff here...
// Applies to all scene views regardless of selection!
// You'll need a control id to avoid messing with other tools!
int controlID = GUIUtility.GetControlID(FocusType.Passive);
if (Event.current.GetTypeForControl(controlID) == EventType.keyDown)
{
if (Event.current.keyCode == KeyCode.Keypad1)
{
Debug.Log("1 pressed!");
// Causes repaint & accepts event has been handled
Event.current.Use();
}
}
}
}
To disable it, you can use SceneView.onSceneGUIDelegate -= OnSceneGUI;
You can also check if a modifier key is down at the same time as checking the keycode. For example, with the Control modifier key, use Event.current.control
Answer by awesomedata · May 05, 2017 at 07:43 AM
Some thoughts on the above method since there isn't much documentation on this topic:
Firstly, when dealing with SceneView and OnSceneGUI, remember to, as with any event subscription, to attempt to unsubscribe first, just in case there are lingering subscriptions hanging around, especially if this was called in OnEnable(), which is the most common way of dealing with Editor scripts like this:
public void OnEnable() {
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
Secondly, keep in mind that this event only fires when there has most-recently been input to the scene window/tab, such as clicking in the Scene. On the other hand, if you played with controls in other GUI windows, for example, like the inspector or your own custom EditorWindow/Inspector, the OnSceneGUI event will simply not fire until you click back on the scene window/area to return focus to it. This means you will have to duplicate input for any window using OnGUI if you want the keyboard shortcut to be fired from anywhere.
Thank you for that explanation, it helped me understand the problem. I don't understand what you mean with duplicating input? I'd like to get the keyboard events to trigger while a custom editorwindow is active
I don't understand what you mean with duplicating input?
In other words, as mentioned above, if your SceneView currently has focus, your EditorWindow does not, and therefore, listening to keyboard events in the EditorWindow will not matter (and this goes for any window that is not your SceneView, so you'll have to listen for input in all the windows that have focus.) I'm not sure if the OnSceneGUI event still operates this way, but I am sure it does.
Either way, if you want to have keyboard events register while the EditorWindow is active, just be sure to either give it focus, or ensure that wherever the user's main input happens, that area stays focused until they're done (for as long as you want to keep listening for the keyboard events to affect your custom EditorWindow.) Ins$$anonymous$$d of duplicating input code, it, alternatively, is possible to force focus to another window as well (that checks for input and acts upon it, then returns focus back to the previous window that was selected.)
Hopefully this helps.
Thanks you very much! I'm not sure it is what you meant but I managed to have input go through to my editorwindow by calling sceneView.Focus()! I hope that it doesn't cause too many unintended side effects but I'm sure I can figure it out from here! Calling EditorWindow.Focus() does nothing though, even if I call it constantly
Your answer
Follow this Question
Related Questions
When in play mode, i press W and it exits play mode? 1 Answer
Values changed with Editor Script don't get saved 1 Answer
Undo.RecordObject is too slow on large arrays, alternatives? 1 Answer
How to change settings on editor using Enum with an array? 0 Answers
Detect Play mode about to be entered 3 Answers