10
$\begingroup$

For quite long time, I was looking for a faster way to toggle (or toggle off) visible / selectable and renderable for many objects, as illustrated below:

enter image description here enter image description here enter image description here

I know we can do the relatively quick select by dragging in the Outliner, but it is not so fast though; Also, we can try H and AltH, as well as Ristrict Render, but the objects must be selectable first.

So, how can I do this in a faster way? Script would be acceptable, if necessary.


Edit:

To simplify my question in another way: Is there a way to make all hilighted items listed in Outliner to have either of these properties unified? For example, I want to have all objects selectable, what should I do instead of having to toggling them one by one? Intuitively, I tried to press A twice in Outliner, then hit S, I thought it would work similar to what A works everywhere, I mean a kind of "unified" toggle, to toggle all of them on or off, regardless their initial slectibility. But appearently it cannot be done in this way. So I'm looking for a better way to do this.

The only way I can think is to group them all first, then switch the outliner display type to Groups, now I can toggle them all by a single click. However, four problems here:

  1. Again, It doesn't work with the unselectable or invisible ones, which cannot be grouped since I cannot even select them.
  2. it means I have to give up the current selection first, which is sometimes unwanted.
  3. Even if all objects are initially selectable and I don't care to give up the current selection, creating a temporary group then delete it afterwards seems not as fast as expected.
  4. I'm particularly talking about a complicated scene with a large number of objects, which makes Outliner the important place to organize them.
$\endgroup$
  • $\begingroup$ This is a bit of an odd question, having to select objects first is a common requirement before operating on them. - how is this slowing you down? $\endgroup$ – ideasman42 Feb 5 '14 at 14:29
  • $\begingroup$ Hi, I see your point. However, even for now, these toggle behaviors can be done in Outliner without having to select objects, I mean, just simply hilight them in Outliner, then hit V S or R. However, afaik, the selectibility have to be treaked within Outliner (or script), so I have to turn to Outliner again. But that's not my point here. I've updated my question. Thank you. $\endgroup$ – Leon Cheung Feb 5 '14 at 15:46
  • $\begingroup$ Btw, my friend was trying to do this with Python, but he said he was not able to achieve this because of the lacking API support for Outliner. I'm not sure if this is true. or I just misunderstood him? $\endgroup$ – Leon Cheung Feb 5 '14 at 16:31
  • $\begingroup$ Maybe I've never done this with as many objects as you are working with, but I haven't noticed any delay if you create a group for these items: you can click just the visibility or selectability for the group and all objects in the group get adjusted accordingly. $\endgroup$ – tobinjim Feb 7 '14 at 3:54
  • $\begingroup$ @tobinjim Thanks for your advice. However, I've mentioned clearly about the disadvantages of using group for this kinda control. $\endgroup$ – Leon Cheung Feb 7 '14 at 4:38
3
$\begingroup$

Uploaded a script here.

I did not find the menu used by right-click. Put the operator into a menu named Toggle. You might have to scroll the header.

However, you can assign hotkeys to bpy.ops.outliner.custom_toggle(type) where type is from the set {"TOGVIS", "TOGSEL", "TOGREN"}.

Did not test it yet for large scenes.

$\endgroup$
  • $\begingroup$ The right-click menu is hardcoded in outliner_tools.c, based on EnumPropertyItem prop_object_op_types[]. $\endgroup$ – CoDEmanX Feb 9 '14 at 21:40
  • $\begingroup$ @pink vertex, I have to say that your script was as great as CoDEmanX's solution. It can be really nice if they can be put into the right-click menu. I decided to choose your answer here. CoDEmanX makes it improved by hardcode, I think more people will benefit it too, so I'll leave the bounty for him, hope you don't mind. :) (Grr, SE really should improve the bounty mechanism to allow for awarding multiple answers :S) $\endgroup$ – Leon Cheung Feb 12 '14 at 2:15
  • $\begingroup$ -- I dont mind. $\endgroup$ – pink vertex Feb 12 '14 at 12:01
  • $\begingroup$ I installed it but cannot understand how it works, could you explain? Thanks $\endgroup$ – MicroMachine Aug 31 '17 at 16:30
6
+200
$\begingroup$

The outliner is written in C, and not much is exposed to Python.

The operator that toggles the (render-)visibility or selectability is:

bpy.ops.outliner.object_operation()

Possible arguments for the type parameter are:

('SELECT', 'DESELECT', 'SELECT_HIERARCHY', 'DELETE', 'TOGVIS', 'TOGSEL', 'TOGREN', 'RENAME')

As you see, there are only toggles. Someone had to add some to only turn on or only turn off all pre-selected items (would unify the settings). Seems like a simple C task, but not sure how to do the interaction with the user...

Wouldn't make much sense to clutter the right-click menu with

Toggle Visible
Make Visible
Make Invisible
Toggle Selectable
Make Selectable
Make Unselectable
Toggle Renderable
Make Renderable
Make Unrenderable

Hotkeys should work well however, Shift + R/S/V to turn all on, Alt + R/S/V to turn all off. Ctrl + ... wouldn't work, 'cause CtrlS is globally for save .blend.


Update:

I duplicated the toggle code and changed it to set visibility/selectability/renderability. This means you can switch each of them on, just like you would toggle them. If you want to turn them all off, turn them all on, then toggle to invert. Benefit: 3 operators / entries in the right-click menu less.

It might make sense to refactor the code and have only one operator each (so 3 in total) + an enum to turn on, off or toggle. I would still add turn on and toggle to RMB menu only.

Diff: http://www.pasteall.org/49381/diff

Windows 64bit build: http://graphicall.org/1101

$\endgroup$
  • $\begingroup$ I have to admit that this is exactly what I want. However, as you mentioned, it may be a bit difficult to do for that reason. thank you for the understanding. $\endgroup$ – Leon Cheung Feb 6 '14 at 6:55
  • $\begingroup$ @LeonCheung: Updated my post, there's a link to a Windows build with 3 new operators available to turn all pre-selected items on. $\endgroup$ – CoDEmanX Feb 9 '14 at 22:44
  • $\begingroup$ Wow, you've touched the hardcode? Also, it works great to me. I have no excuse to not award the bounty to you. :P Thanks for the hard work! $\endgroup$ – Leon Cheung Feb 12 '14 at 1:59
4
$\begingroup$

As a start you could begin with

for sel in bpy.context.selected_objects:
    sel.hide = True

for sel in bpy.context.selected_objects:
    sel.hide = False

To switch between the two states, one could check if all objects are visible. If so, unhide them. Else hide them. Then bind the script to a shortcut. I'm pretty new to python but implemented such a function in 3dsmax a while ago.

Edit: This is for Restricted rendering:

for sel in bpy.context.selected_objects:
    sel.hide_render = True

for sel in bpy.context.selected_objects:
    sel.hide_render = False

Cheers, Michael

$\endgroup$
  • $\begingroup$ Hi, this may work. Thanks. But it seems that I have to have objects selected first. I just wonder what if they are not selectable. $\endgroup$ – Leon Cheung Feb 5 '14 at 16:26
4
$\begingroup$

RMB> Copy To Selected works here.

The objects must be selectable and selected for this to work, but I'm not sure there is any way to do this without those requirements without using python.

Here is a quick hack you can do using python:

import bpy

unselectable_objs = []
for obj in bpy.data.objects:
    if obj.hide_select == True:
        unselectable_objs.append(obj)
        obj.hide_select = False

print(unselectable_objs)

This will print an array of all the objects that are unselectable to the terminal, as well as enabling selectable for all objects.

Select the objects you want to change the visibility of and use Copy To Selected to set the visibility settings.

Now run this, setting unselectable_objs to the array which was printed in the terminal before to make your objects unselectable again:

import bpy

unselectable_objs = #array goes here
for obj in unselectable_objs:
    obj.hide_select = True
$\endgroup$
  • $\begingroup$ Hi gandalf3, I've tried that. It may work, too. It satisifies my question partically. Thanks. $\endgroup$ – Leon Cheung Feb 6 '14 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.