Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Stop MenuItem from consuming keyboard input event

Discussion in 'Immediate Mode GUI (IMGUI)' started by Johannski, Jan 7, 2017.

  1. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Hello there,

    I wanted to make a simple Application Pause Toggle as Unity already implemented it, but with an easier keyboard shortcut (Because sometimes you just really want to quickly pause the editor and maybe have only one finger left). Sadly the shortcut can't be changed in the preferences, so I went to do my own simple script:
    Code (CSharp):
    1. // --------------------------------------------------------------------------------------------------------------------
    2. // <copyright file="PauseApplicationToggle.cs" company="Supyrb">
    3. //   Copyright (c) 2017 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <author>
    6. //   Johannes Deml
    7. //   send@johannesdeml.com
    8. // </author>
    9. // --------------------------------------------------------------------------------------------------------------------
    10.  
    11. using UnityEditor;
    12.  
    13. namespace Supyrb
    14. {
    15.     using UnityEngine;
    16.     using System.Collections;
    17.    
    18.     public static class PauseApplicationToggle
    19.     {
    20.         [MenuItem("Supyrb/Misc/TogglePauseApplication _p", false, 10000)]
    21.         public static void TogglePauseApplication()
    22.         {
    23.             EditorApplication.isPaused = !EditorApplication.isPaused;
    24.         }
    25.  
    26.         [MenuItem("Supyrb/Misc/TogglePauseApplication _p", true)]
    27.         public static bool TogglePauseApplicationValidation()
    28.         {
    29.             return Application.isPlaying;
    30.         }
    31.     }
    32. }
    33.  
    34.  
    The script works quite well and I can easily toggle by just hitting the p key. One big problem for me however is, that the menu item consumes the keyboard input event, even if the validator function sends back a false. So, whenever I want to rename something and hit a p, the renaming is stopped, I just can't type the letter p anymore.

    Is there a workaround for this? I imagine I can add a custom script that listens to all events, and uses the p event, but does not consume it. This feels rather dirty, I hope there is some functionality I missed.
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    There are a few possible solutions for this, but in my opinion, a menu item shouldn't have a single key shortcut in the first place.. Think of other tools or apps you use, most use key combinations (CTRL + key) as shortcuts. I believe you can already achieve the same using ctrl-shift-p, you could simply train your fingers to hit that combination to pause...

    Other solutions are not to use menu items, but something else that will pause the game as you hit that key.
    Since you only want this to run when Application.isPlaying is true, a runtime script that processes this input sounds like a better fit to me (as opposed to the editor script that is executed even when you're not in play mode).
     
  3. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Thanks for the answer. Yep, the keyboard shortcut ctrl-shift-p does exactly what I want, but I sadly can't change the combination in the preferences.
    Hm, well when you are thinking about pressing W or E or R or F, there are quite a few shortcuts in unity that work without any modifiers.
    I also had the thought of creating a runtime script, but the problem there is, that it won't be able to resume the pause, because the application is paused. So that is also not the best solution out there... I'm just annoyed that I haven't found a way to control whether the event is consumed or not.
     
  4. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I actually tried the code you posted (using Unity 5.6 beta 3) and it didn't work - hitting "P" while in play mode didn't do anything. When i manually paused, and then hit "P", it unpaused the game.

    There may be other solutions to this issue, i'll try to have a look later :)
     
  5. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Oh, you're right. The validate function I added later did a nonsense check, here is the updated version:
    Code (CSharp):
    1. // --------------------------------------------------------------------------------------------------------------------
    2. // <copyright file="PauseApplicationToggle.cs" company="Supyrb">
    3. //   Copyright (c) 2017 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <author>
    6. //   Johannes Deml
    7. //   send@johannesdeml.com
    8. // </author>
    9. // --------------------------------------------------------------------------------------------------------------------
    10.  
    11. using UnityEditor;
    12.  
    13. namespace Supyrb
    14. {
    15.     using UnityEngine;
    16.     using System.Collections;
    17.    
    18.     public static class PauseApplicationToggle
    19.     {
    20.         [MenuItem("Supyrb/Misc/TogglePauseApplication _p", false, 10000)]
    21.         public static void TogglePauseApplication()
    22.         {
    23.             EditorApplication.isPaused = !EditorApplication.isPaused;
    24.         }
    25.  
    26.         [MenuItem("Supyrb/Misc/TogglePauseApplication _p", true)]
    27.         public static bool TogglePauseApplicationValidation()
    28.         {
    29.             return EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused;
    30.         }
    31.     }
    32. }
    33.  
    34.  
     
  6. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    I think you can avoid than MenuItem consumes your keyboard event.
    I use this shortcuts to avoid conflicts with Unity:
    F6 = Play
    F7 = Pause
    F8 = Next Step
    (F5 is used in Version Control window to refresh)

    Code (csharp):
    1.  
    2. [MenuItem("Shortcuts/Play _F6")]
    3. static void PlayGame()
    4. {
    5.  EditorApplication.ExecuteMenuItem("Edit/Play");
    6. }
    7.  
    8. [MenuItem("Shortcuts/Pause _F7")]
    9. static void PauseGame()
    10. {
    11.  EditorApplication.ExecuteMenuItem("Edit/Pause");
    12. }
    13.  
    14. [MenuItem("Shortcuts/Step _F8")]
    15. static void StepGame()
    16. {
    17.  EditorApplication.ExecuteMenuItem("Edit/Step");
    18. }
    19.  
    And to avoid errors when play/pause... I use existing unity menu item !
     
  7. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Interesting that you mention that, I just set the shortcut to the F keys just before you answered me as a quick fix. I think with this solution we are just shipping around the problem. The event is still consumed, but as long as no other event is interested in an F5 input it does not really matter. :)
     
  8. Aeroxima

    Aeroxima

    Joined:
    Jul 19, 2016
    Posts:
    15
    This is still a problem and I wish it wasn't. There's a bunch of hotkeys in Unity already, and I put in a simple one that I really like, but it consumes input while the built-in ones work fine (such as for the tools in the bar at the top left, and any entered in the preferences).

    Any other fix now a year later?
     
  9. pixlweaver

    pixlweaver

    Joined:
    Dec 21, 2012
    Posts:
    92
    Really wish there was a fix for this! I'd like to set up some custom hotkeys so some tasks are similar to working in Maya (would make workflow a bit easier for artists on my team) but this forces me to use some odd key combination that no one will remember. UGH!