3D View Context Menu Experiments

The Context Menu that pops up when you right-click in the 3D Viewport is not a context menu.

It certainly looks like one, but is not. You can right-click on things and a menu will pop up that contains specialized items. But the included items only depend on what objects were already selected and active before the menu was invoked. It will be the same regardless of where you click, so the entire menu could just as well be hanging from the header instead.

Technically, my experiments with this involve the following: adding an “ob_cursor” member to the View3D struct, giving “WM_OT_call_menu” an invoke that sets the ob_cursor pointer based on ED_view3d_give_object_under_cursor(), and then extending ed_screen_context() so that I can get to this new “bpy.context.cursor_object” from python. It’s enough to play with. I have no idea where ob_cursor is better stored, and I’d imagine making a specific “WM_OT_call_3dv_contextmenu” operator if I wasn’t so lazy.

What can be done with this that you can’t do otherwise? Well this means you could act on any object, not just the active one that had already been made active before you even clicked.

So you could have one mesh object selected, but then right-click on another and “add to selection”. Right-click on any of them to “make active”. You could then right-click on one of your cameras to make it the active one, without having to select it first. You could put an object into edit mode, then right-click another to “edit as well”.

Right now imagine selecting multiple mesh objects. You can right-click and select “parent” but it doesn’t matter where you clicked, the parent will be the “active” object, probably the last you selected. With this change you could have three mesh objects selected, then right-click on an entirely different unselected object and “make parent”. It would be so much more intuitive.

So I am wondering if this is interesting at all to anyone? Is this a direction we were already planning on going? I have a feeling I am just jumping the gun on a known “to do”, but also don’t want to miss this by not pointing out the current shortcomings. Or it is also possible that I am thinking about this in entirely the wrong way. Regardless, I’m not the right person to actually implement this properly as I’m a blender source newbie and am terrible with python as well. LOL

11 Likes

I tend to agree here. Context means “Depends where you click”. If it’s on a light, it’s different, if it’s on an empty space, different, if it’s on the veritice, different. It should not have to be Lclick then Rclick to change the context.

The same should be true in other editors. Right click without selecting a keyframe should bring up it’s context menu, on the timeline different, on the panels different, in the properties different, etc.

It should be consistent throughout the UI, so I agree with you. I’m curious about how you would code it, as I had no idea you could detect where the mouse click was other than in the 3D viewport or UI elements.

In fact, the Rclick context menu’s are so… odd, that when you drag the timeline in Lclick select maps you can’t even get to that menu! You drag the timeline instead.

In the Bforartists 2.8 fork, they removed the context menus entirely mainly due to being header menu double entries and not really contextual at all. They would love to have a true contextual system, maybe even a contextual pie menu on one click - but till then… not sure how to do it.

1 Like

Right now the context menus are launched in a very simple way. The keymap calls an operator called WM_OT_call_menu that launches a menu in python with a name supplied to that operator. So if you are in object mode it calls “VIEW3D_MT_object_context_menu”, but if you are in edit mode and the active object is a mesh it calls “VIEW3D_MT_edit_mesh_context_menu”, etc.

How I think it should work is that only ONE python menu should be called regardless of mode or what is selected or active and it should know what thing was under your mouse at the time. That way it can do a lot more branching for different conditions. Like right-clicking on a mesh object that is not being edited while in edit mode so that you can edit that one as well.

My experiments with it involve adding a new member to the View3D struct to hold the “cursor object”. Then changes to the ed_screen_context() function so that python scripts can see that object as “bpy.context.cursor_object”.

Then I made a new operator in view3d_ops that finds the object under the mouse, using ED_view3d_give_object_under_cursor(), adds that object to the current View3D before calling a python menu. So it then knows what object you clicked on, if any.

That is actually enough for this to work. Python scripts already know what mode you are in, what is selected, what is active, etc. This just adds this one new object. I’m am just not that used to Python, so I would not be the best person to flesh the idea out.

My current struggle is how to also allow context menus on the navigation widgets (top-right icons for ortho/persp, etc). I would love to see options on them. It would be worth it just for “auto perspective”.

2 Likes

Hi! While this proposal makes total sense for left click selection, I’m wondering how this should be managed for right click selection instead.
At the moment the “context menu” is called with W, and I think it would be really strange to have a key shortcut performing different things depending on the mouse position, while any other one is selection based.

Another thing that comes to my mind is that something like this would probably need to be paired with some sort of “selection prediction” on mouse over (I don’t know if this term is correct), otherwise I think it would be quite difficult to use it in complex scenes with a lot of objects.

Selection pre-highlight is still years behind in Blender and… for another topic of debate, but yes, it would be necessary to make it work nicely (though I’ve used this workflow in many software without it). Rclick select does make a contextual menu typical of most Lclick select workflows in mostly all software somewhat odd if it was all in Rclick select, maybe as a double click?.. but that is Blender. Indeed rightclick contextual menu is indeed mainly for Lclick select workflows.

Of course!. With your message I now realize why this is working as it is: Devs working with right-click select and that keymap not having any free mouse key bindings. So doing this “properly”, as I see it, would not be a consideration at all.

I can’t see how these things can coexist well. The best we could get is having context menus that differ radically between right- and left- click and I doubt that would be acceptable. Although the current state seems pretty dim in that it the “W” just brings up menus that are pretty-much identical to the menus on the header.

Yes that would be nice. Although that does seem unlikely to get. I have not played with anything too complex yet though, although surprised that cameras and lamps are easy to select this way.

Currently looking at object iterators. Most operators operate on “selected_editable_objects” and so this requires something a bit different. Basically we want to operate on only the mouse object if is not selected, but all selected objects if it is.

Lots of fun to play with though…

1 Like

Changing the contents depending on where you click vs what you have selected is a different way to do it, but be aware that it can cause some problematic issues in common cases:

  • When you want a context menu to act on multiple selections
  • Some elements might be hard to reliably hit, like vertices or simply small objects, or objects that are hidden behind others
2 Likes

To be fair, doing it this way is the correct, and only, way to do it for “Context Menus.” I can’t think of any other programs doing it any other way. The current are just dropdown menus that happen to appear near the mouse - they may as well be on the header (and they are already there too).

Imagine having two lamps and two cubes, with the cubes selected (one active naturally).

Right-clicking on a lamp would just act on that one lamp. Right-click on a cube though and the menu could act on both (since the mouse object was selected) for most operations. But you could still include active-specific options. So “make active” on the non-active selected object for example. But we could also include “make active” on a non-selected object by just having that action add to selection and also make active.

For sure, but no harder than they are to select initially. But yes, there are lots of weeds there. It is very possible that doing this properly is just not practical without pre-selection highlighting.

For overlapping objects we might be able to do something like that menu you can get with alt-left click when there are overlapping objects.

But in edit mode it could act much the same as it is now. Still operate on the selected and active vertices, edges, and faces. The only difference being that when you right-click to initiate the context menu you must do so somewhere within the bounds of the object. But not a tough thing to do.

But imagine being in edit mode on one object, then just right-click on some other object to “edit as well”. I think we can only do this currently by shift-clicking on the (other object’s) mesh icon in the Outliner. So a nicer way of dealing with this.

4 Likes

Looks like the weeds with this experiment are the sheer number of operators that will work on only the active object, not an arbitrary object. The ones that work on multiple objects wouldn’t be too bad, but it is all the active-only ones that would be tough. So far I can’t find any easy way of getting around that…

You would have to run a cycle to apply the same operator to the selection, as the default IMO.
The “Active Only” workflow is so slow in Blender… that might be a worth project before going on context menu’s, make most of the UI default on “Apply to Selected” instead of only Active. Would there be a way to check the context if it’s with a selection then pretend to “ALT” change the system, like apply to all selected?

#1 it seems obvious blender should have the python hooks to mke experiments like this POSSIBLE, regardlesss of what we do with the right-click/W menu right now. Otherwise, how can we even experiment?

#2 i think highlighting the context object after the right-click/W but before the context menu is drawn is sufficient. We don’t need constant pre-selection highlighting

#3 an experimental context menu could be a hybrid of the current menu (which is not context sensitive) and a few “context object actions” at the top… in this way it doesn’t break any behavior, it just gives us a way to experiment with adding a few context actions

I personally think this is a great direction to explore to make blender more accessible to users of other programs, and to fight shortcut bloat.

For example, a parenting workflow, where one selects some objects and then right clicks (or presses W) on the desired parent (whether it is selected or not) and sees it (temporarily) highlighted as context, with “context object” > “make parent” action at the top of the menu. Seems great, and doesn’t change any existing blenderisms.

And if we can make a good enough set of context sensitive actions, perhaps someday the current non-context menu items be pushed into a right-click submenu.

1 Like

this is a nice thread, deepening and investigating you can do great order, polish and focusing on prediction and contextualization features here

That is a good point I think. I didn’t think that it might be useful on its own to know the 3dview object (if there is one) under the mouse in python at the time the menu is invoked. I can’t see it doing any harm to having that information. Except maybe the disappointment of not being able to do much with that object.

It might need a bit of a think. It is only the object in the current 3dview that was under the mouse at the moment you invoked the menu, and doesn’t remain pointing at other objects as you move your mouse later. So I need to think about the naming of the thing.

  • click object context
  • click over context
  • invoke object context
  • menu invoke object context

@Harleya, my man, I would love you if you got something like this committed into master. Especially for use cases like this:

  • …You could put an object into edit mode, then right-click another to “edit as well”.
  • …then right-click on an entirely different unselected object and “make parent”.
  • …You could then right-click on one of your cameras to make it the active one, without having to select it first.
  • …you could act on any object, not just the active one that had already been made active before you even clicked.

Sir, this is absolutely the right way to be thinking of how a context menu should function. It should be contextual to the thing under the cursor.

I think jeske’s point #1 is reason enough to at least expose this in the API, even if it isn’t immediately used by Blender’s native context menus.

As I spend more time working with Blender’s python API I realize that there is a lot of information that is not exposed to Python that would make my life much easier if it was. This is a perfect example. It would give add-on devs a more powerful set of tools to work with. Add-ons are, in some ways, the laboratories for Blender’s future direction. If an add-on is wildly successful Blender may adopt its conventions internally. If not, it doesn’t harm Blender if an add-on never gained traction. But without good hooks the add-on devs are sometimes hobbled in what they can do.

And generally speaking “Please expose [such and such data] to the API.” is not going to garner a lot of votes as a Right Click Select proposal because most of the people on RCS won’t understand the meritorious value of a technical request for under-the-hood API features.

jeske’s point #3 importantly reinforces that exposing this hook can be a great way to allow exploration with possible future directions without breaking current things. Even Blender itself could try a hybrid of one or two contextual menu entries without the workload of needing to redo the entire context menu system. If it’s well-received it could even allow for a slow shift over time from fixed actions that only work on active/selection (what we have now, which is just the header menus but next to the cursor) to a dynamic one that is truly contextual.

I think this can actually move forward without needing any sort of pre-highlight at all, even the ‘momentary’ one suggested in his point #2. (Although that would certainly be useful. Say, a third outline color different from the Active color or Selected color, like a light blue; only visible while the context menu is present on a non-selected object; disappears if the menu is cancelled.)

This is somewhat adjacent to general-purpose contextier context menus, but I’ve played around a bit with adding right click pie menus to custom gizmos, and I’ve found them to be incredibly useful for changing things like transform orientations and snapping modes.

They would be for tablet users, which I would assess are around the majority, at least among professionals ? Right-clicking with a stylus means hovering above the tablet surface, moving the index finger to reach the right-click button that sits about two centimeters above the middle button (which is how it is usually set up for convenience, since the middle button is arguably more frequently used, notably for navigation), and targeting the object. I know I make it sound like a complex choreography, but it’s actually quite annoying : the difficulty lies in keeping the stylus still, while hovering, and clicking (either by tapping the tablet surface, or not).

I actually believe the fault lies more on how the tablet and stylus are designed, but currently they are all made like this. I am not saying this to discourage anyone, but to help keep it in mind. Surely having menus react to what’s under the pointer can be useful, and I’ll probably just rebind it to W or some easy-access hotkey.

I’m pretty sure context means “depends on context.” :wink:

the context is determent by where you click and what is selected and what is the active object. So technically both of you are correct