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

Shortcut Manager Feature Preview

Discussion in 'Editor Workflows' started by smcclelland, Sep 11, 2018.

  1. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,229
    Actually, with a bit of trial (and a lot of error) the [Shortcut(..)] attribute on a static method worked fine with an editorwindow. It wasn't obvious at first that I could just set all the keycodes to none and let the end user of our tools configure them in the shortcut manager. I thought I'd need to create the custom categories myself in code.

    Some more detail, like an example in the doco might help others.
     
    MariaAngelovaPD and awesomedata like this.
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    I totally understand why some shortcuts needs to not be activated during play mode, but generally this is bad. This should be something that's selected on a shortcut-by-shortcut basis.

    I asked in one of the other threads, but never got a reply - what's meant by "This is to guarantee old behavior"? If some command should not run in some case, it's the job of that command to prevent that, it shouldn't be a situation of "well some command doesn't support this, so now we have to block it from everyone"

    We're not going to be able to use this feature for a large chunk of our commands because of this, so we're back to using non-rebindable [MenuItem] shortcuts.
     
  3. jonathans42

    jonathans42

    Unity Technologies

    Joined:
    Jan 25, 2018
    Posts:
    514
    I hear you. I think we should revisit that decision. I would suggestion that we have a specific shortcut profile when in play mode, that binds less shortcuts, but still allow the user to rebind any of the shortcuts. Then, when you exit playmode, we switch back to the editmode shortcut profile automatically.
     
    Last edited: Aug 7, 2019
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Ideally, it should just be an option on the Shortcut-attribute. Maybe another [Flags] enum that could specify when the attribute was active?

    I'm suggesting that because having shortcuts that are only available in play mode would be nice for editor-only developer features that you want to make super-sure is not a part of any build.


    While you're at it, could you document the "context" parameter? "Optional shortcut context type" isn't very much of an explanation. Can you give it the type of some editor window and have it only be active if in the context of that window type, or...?
     
  5. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,229
    As some general feedback, the new shortcut manager is a great feature, which as a editor tool developer, really helps improve the customer experience.

    Pros
    Keyboard layout with Unassigned, Assigned and Global keys
    Keyboard layout tooltips
    Categories that are auto-populated from the Shortcut attributes
    Conflict management
    Context sensitive

    Cons
    Functionality; None found so far :)
    No example code in API reference docs (what is obvious to Unity devs not so obvious to the rest of us)
     
  6. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
  7. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    An even better idea would be a "Bind in Playmode" attribute.


    Some tool developers would like to ensure some shortcuts work in PlayMode, while others (or even the same shortcuts) should not be available (or should operate differently) in PlayMode.

    I can see this being _very_ handy for tool developers (like me) to let users modify game data using shortcut tools while the game is running.


    Just so much useful there.
     
    Lars-Steenhoff likes this.
  8. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    I'm using the ShortcutManager a lot for our inhouse tools, but I keep being annoyed by the fact that I need to create a static method for each individual shortcut even though a lot of the functionality could be refactored into using one or two parameters. Here's an example:

    Code (CSharp):
    1. [Shortcut("GridMoveTool/RotateRight", typeof(SceneView), KeyCode.Period, ShortcutModifiers.Shift)]
    2. private static void RotateRight()
    3. {
    4.     RotateHelper(Vector3.forward, -90f);
    5. }
    6.  
    7. [Shortcut("GridMoveTool/RotateLeft", typeof(SceneView), KeyCode.Comma, ShortcutModifiers.Shift)]
    8. private static void RotateLeft()
    9. {
    10.     RotateHelper(Vector3.forward, 90f);
    11. }
    12.  
    13. [Shortcut("GridMoveTool/FlipVertical", typeof(SceneView), KeyCode.Y, ShortcutModifiers.Shift)]
    14. private static void FlipVertical()
    15. {
    16.     RotateHelper(Vector3.right, 180f);
    17. }
    18.  
    19. [Shortcut("GridMoveTool/FlipHorizontal", typeof(SceneView), KeyCode.X, ShortcutModifiers.Shift)]
    20. private static void FlipHorizontal()
    21. {
    22.     RotateHelper(Vector3.up, 180f);
    23. }
    24.  
    25. private static void RotateHelper(Vector3 axis, float angle)
    26. {
    27.     if (instance == null)
    28.         return;
    29.  
    30.     var go = instance.target as GameObject;
    31.  
    32.     if (go == null)
    33.         return;
    34.  
    35.     Renderer renderer = go.GetComponent<Renderer>();
    36.  
    37.     Vector3 position;
    38.  
    39.     if (renderer != null)
    40.         position = renderer.bounds.center;
    41.     else
    42.         position = go.transform.position;
    43.  
    44.     instance.RotateTarget(position, axis, angle);
    45. }
    46.  
    47.  
    48. private void RotateTarget(Vector3 pivot, Vector3 axis, float angle)
    49. {
    50.     GameObject go = target as GameObject;
    51.     Undo.RecordObject(go.transform, "Rotate Transform");
    52.     go.transform.RotateAround(pivot, axis, angle);
    53. }
    This works fine, but could be shortened and be more readable if the Shortcut attribute would allow users to pass an argument of type object and use multiple attributes on a single method. Or, even better, similar to NUnit and co define a data source, which would be an IEnumerable that returns arbitrary data. All in all I think that the Shortcut attribute could copy some ideas from testing frameworks.

    That's simply an idea, other than that I'm very happy about how the ShortcutManager system works! :)
     
    awesomedata and Lars-Steenhoff like this.
  9. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    So today I was hoping to rebind some of the Animation Clip Editor's hotkeys (specifically the "," and "." next/prev keyframe keys) to something easier to reach with my left hand ("z" and "x"). But I can't because "z" and "x" are setup as Global keys (along with Q/W/E/R/T/Y) because I guess everything in the top Toolbar is that way?

    It's never been clear to me as to why these are global and not part of the actual Scene view? They don't apply to most/any other windows like Game or Animator or Animation, yet they prevent several useful hotkeys from being used by other windows. Is there a plan to eventually make these part of the scene view? (or is there a better forum to ask this in?)
     
    awesomedata and Lars-Steenhoff like this.
  10. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
  11. ReptileDev

    ReptileDev

    Joined:
    Aug 6, 2018
    Posts:
    2
    Hello,

    I'm using the Shortcut Manager in combination with the EditorTool class, and found some issues when trying to detect if a modifier key is held:

    Code (CSharp):
    1. public class MyTool : EditorTool
    2. {
    3.     static KeyCombination shortcut; // Set when MyTool becomes the active tool
    4.  
    5.     public override void OnToolGUI( EditorWindow window )
    6.     {
    7.         // Check if we are holding the shortcut keys down
    8.         if( Event.current.modifiers == shortcut.modifiers ) //NOTE: this won't compile
    9.         {
    10.             // do stuff here
    11.         }
    12.     }
    13. }
    As you can see the check at line 8 can not be done, since Event.modifiers and KeyCombination.modifiers are two different enums.

    Unfortunately they can not be casted to int either since, since their order does not match:

    Code (CSharp):
    1. public enum EventModifiers
    2. {
    3.         None = 0,
    4.         Shift = 1,
    5.         Control = 2,
    6.         Alt = 4,
    7.         Command = 8,
    8.         Numeric = 16,
    9.         CapsLock = 32,
    10.         FunctionKey = 64
    11. }  
    12.  
    13. public enum ShortcutModifiers
    14. {
    15.         None = 0,
    16.         Alt = 1,
    17.         Action = 2,
    18.         Shift = 4
    19. }
    Am I approaching this wrong? If so what's the correct way?
     
  12. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,229
    If you want to check for modifier keys, you could just check the current event.

    Code (CSharp):
    1. bool isCtrlKey = currentEvent.control;
    2. bool isShiftKey = currentEvent.shift;
    3. bool isAltKey = currentEvent.alt;
     
  13. Aka_ToolBuddy

    Aka_ToolBuddy

    Joined:
    Feb 25, 2014
    Posts:
    536
    @smcclelland Hi. Is there any news about that awesome feedback?
     
  14. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    I'm just trying this tool for the first time and I find it quite counter intuitive to use in general: If I know there's a keybind behind some operation, I'd want to be able to just select the bind and alter it, instead of first navigating the on-screen keyboard to see the bind name and then trying to search for it on the bottom part so I can finally change it. This feels like unnecessarily complicated way of doing such a basic task. Instead you could just:

    - Add listen button somewhere, let users hit the keybind they know exist and highlight the command on the bottom view for it so they can alter the bind immediately
    - Allow doing the same from on-screen keyboard, let people highlight the command just by clicking the keybind on the on-screen keyboard
    - Additionally, let people rebind directly from the on-screen keyboards right click context menu in addition to reset/remove for the existing action.

    I do wonder though, am I missing something obvious? Like is there a way to do the things I asked here and I just don't see it?
     
    awesomedata and MrLucid72 like this.
  15. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    962
    I'm also wondering why I can't stack a few things together. Why not allow me to have a conflict and do BOTH?
     
    Lars-Steenhoff and awesomedata like this.
  16. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    Nope -- it's just unnecessarily convoluted because Unity hates its users... having a non-convoluted workflow.
     
    MrLucid72 likes this.
  17. XGT08

    XGT08

    Joined:
    Aug 1, 2013
    Posts:
    1,894
    Hello,

    @leo-carneiro
    @smcclelland
    @jonathans42

    This looks really great up until this point. However, please make IShortcutToolContext available. I can not see any valid reason why this should be made inaccessible. I am working on an editor extension where there are situations in which different shortcut keys should be allowed to collide based on context. I can't fit them all inside the SceneView context.

    There is a curious sense which you guys (Unity devs) make things that have amazing potential, but are half done or they lack exactly where it hurts the most :)

    IShortcutToolContext is important. Please make it available.

    EDIT:
    Let me give you an example. My plugin is a level design plugin. And it works in 3 modes (3 tools so to speak): object spawn, object selection, object erase. Each one of these should be a different context.

    More than that, in object selection mode for example, I would like to have further contexts. I have a bunch of keys such as W, E, R to switch between different gizmos, but when I press the S key, my plugin can grab the selected objects and snap them to a grid. In this context, I want to be able to reuse the R key to rotate the objects involved in the snap session.

    So in this case, I would need 3 contexts: ObjectSpawn, ObjectSelection, ObjectErase.
    And for the the Object Selection context, I need (for this example) another context: ObjectSelectionSnap.

    Of course, this is just one example. I have many shortcuts and IShortcutToolContext would be invaluable.
     
    Last edited: Jun 2, 2020
    Ziflin likes this.
  18. XGT08

    XGT08

    Joined:
    Aug 1, 2013
    Posts:
    1,894
    Hello guys,

    @leo-carneiro
    @smcclelland
    @jonathans42

    I would just like to know if IShortcutToolContext is ever going to be made public. I am working on a plugin and I have to decide whether to build my own Shortcut system that supports contexts or wait until the interface becomes available. So is there any chance it will be made available in the future?

    Thanks,
    Andrew
     
  19. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    3,521
    I need a way to make the unity window go fullscreen on play ( CMD+P ).
    The fullscreen that happens when you press the green button on the unity toolbar on Mac.

    Now I tried to be smart and bind this shortcut to the same one as play and thought I would be all set.
    turns out unity thinks I'm stupid and won't let me have two command on the same shortcut.

    Is there a way to override this ?

    If not please let us choose, we are smart enough.
     

    Attached Files:

  20. gabbehector

    gabbehector

    Joined:
    Sep 26, 2018
    Posts:
    1
    I need to share my custom setup of shortcuts with my colleague but I can't seem to locate the actual file that is outpout as a response to me changing the shortcuts. We have a shared project but the Shortcuts has not been shared so it seems it is part of the editor rather than the project.
    Does anyone know what file it is and where it is located?
     
  21. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    To find your file you can create a new shortcut profile in the shortcut manager and give it a very distinct name. Then search your computer for this file name with a decent search tool (windows search doesn't work for me, but other tools do). This way, I found that my file is stored at:
    C:\Users\myname\AppData\Roaming\Unity\Editor-5.x\Preferences\shortcuts\default
     
    Last edited: Sep 25, 2020
    gabbehector likes this.
  22. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    I've asked about this before, but received no answer either.

    I wonder if @willgoldstone or someone else might know? -- I've semi-recently suggested a better editor-tooling workflow regarding in-editor SceneView-like shortcuts in the Workflow Improvement thread. Not sure if anyone from Unity plans to do anything with my suggestion though. :(
     
  23. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
    The shortcut manager seems to not have progressed a lot unfortunately...
    In like 5 minutes of setting up super basic context-specific shortcuts I've already run into the restrictions in this thread:
    - no way to use the Global context unless via reflection (it's internal)
    - no (good) way to implement IShortcutToolContext
    - thus, no way to re-use shortcuts depending on context (or am I missing something?) - I'd just want to have some shortcuts do different things depending on which objects are selected. Seems I'd have to basically implement an entire shortcut manager with global events on top of Unity's shortcut manager to do this...

    I must be missing something obvious.
     
    Last edited: Oct 6, 2020
    AndrewKaninchen and awesomedata like this.
  24. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    Just as a small feature request, it would be nice if we could bind shortcuts to mouse buttons > 3 that aren't used normally. For instance, we have an "Inspector History" script that lets us hit a [MenuItem] hotkey to go backwards (or forward) to previously inspected objects. It would be nice if we could bind this to the back/foward buttons found on many mice.
     
    Walter_Hulsebos and fherbst like this.
  25. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    I was hoping the newly created Input System (with its wide range of device support) would be useful in the Unity Editor too. D:
     
  26. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    Is there any way I can get a default shortcut to show up next to the corresponding menu entry? I have code like this:

    Code (CSharp):
    1. public class SceneWizard : EditorWindow
    2. {
    3.     [MenuItem("MyGame/SceneWizard")]
    4.     [Shortcut("MyGame/SceneWizard", KeyCode.M, ShortcutModifiers.Action)]
    5.     public static void ShowWizard()
    6.     {
    7.         GetWindow<SceneWizard>(utility: true, "Scenes");
    8.     }
    9. }
    This makes the shortcut available by default, meaning I can press CTRL + M to open the wizard. However, the shortcut is not displayed next to the entry in the main menu.

    That is unless I edit the shortcut in the shortcut manager that got automatically created for the menu item:

    upload_2020-11-24_23-34-49.png

    This lets me (or other users in my desired case) define their own shortcut override, however, it will only ever display in the main menu if changed for the Main Menu command seen above.

    So, naturally, I thought I could simply change my identifier string to match the one from the main menu, but that just logs a warning and is ignored.
     
    Rowlan, mariandev, fherbst and 2 others like this.
  27. TheVirtualMunk

    TheVirtualMunk

    Joined:
    Sep 6, 2019
    Posts:
    150
    Is there no way to have multiple ShortcutModifiers in an atribute?
    Like so;
    Code (CSharp):
    1. [Shortcut("Toggle True Fullscreen", null, KeyCode.F, ShortcutModifiers.Action & ShortcutModifiers.Alt)]
    Does not seem to work for me.
     
    awesomedata likes this.