2
$\begingroup$

I have a Boolean property in my custom panel that I would like to either use a driver or can I use python to do make my option true/false Based on the shading type. I have searched up what I want, but the answers don't help and I am asking again because those were based on older blender versions.

For example, When I go into solid shading mode, Visibility of a object is set to hidden and vice versa for other shading types.

$\endgroup$
13
  • $\begingroup$ I'm a bit confused. Do you want to use this Boolean in a driver, or do you want a driver that sets its value? $\endgroup$ Jan 27, 2022 at 4:03
  • $\begingroup$ @MartyFouts sorry i will edit that to make sense $\endgroup$ Jan 27, 2022 at 4:22
  • 1
    $\begingroup$ Yes, I can. What you want can be done, I think. I'll try to put together an answer as soon as I have some time. $\endgroup$ Jan 27, 2022 at 14:50
  • 1
    $\begingroup$ Does this answer your question? Automatically run a script when an object is transformed or a condition is met Checking the property before/after each frame is rendered is probably the easiest solution. Msgbus typically is the hardest solution - I wonder if someone investigated performance gains of msgbus way... $\endgroup$ Jan 28, 2022 at 1:04
  • 1
    $\begingroup$ As for a driver solution, it's enough to right-click on the "viewport display" icon in the outliner, "Copy as new driver", then right-click on the driven property "paste driver" - except the driver won't update immediately when you click on an icon to disable viewport visibility, it will only update if you e.g. keyframe the viewport visibility and play the animation. $\endgroup$ Jan 28, 2022 at 1:11

1 Answer 1

4
$\begingroup$

As in comments under the question, I think it's a duplicate of:

Automatically run a script when an object is transformed or a condition is met

Which points to a Space3DView draw callback solution:

Use a driver to programmatically set the positions of many vertices

Since we had a conversation in the comments about it, I decided to write an answer here. The principle is the same as under the link (the 2nd part, "If you don't want it for an animation") - on every draw, try to figure out if you don't have to do anything as soon as possible, and in such case just quit the function. That's the purpose of 'last_shading' variable - if you keep track of the last value, you now know if the value changed - if it didn't, you don't have to do anything and you can just quit. The sooner you realize the function has no work to do and can quit, the less CPU cycles you will waste. But, as I show in the benchmark you don't have to worry about it too much...

import bpy
from bpy import context as C, data as D
from bpy.types import SpaceView3D

visibility_data = {
    'Cube': {'SOLID', 'MATERIAL', 'RENDERED'},
    'Sphere': {'MATERIAL'},
    'Suzanne': {'SOLID', 'MATERIAL'}
}

last_shading = None


def test():
    global last_shading
    if C.area.type != 'VIEW_3D':
        return
    shading_type = C.space_data.shading.type
    if shading_type == last_shading:
        return
    print(last_shading)  # The lesson from edits... Use a print to inspect if the function isn't executed too often
    for ob_name, shadings in visibility_data.items():
        ob = D.objects[ob_name]
        ob.hide_viewport = shading_type not in shadings
    last_shading = shading_type


try:
    SpaceView3D.draw_handler_remove(SpaceView3D.my_handler, 'WINDOW')
except (AttributeError, ValueError):
    pass

SpaceView3D.my_handler = SpaceView3D.draw_handler_add(test, (), 'WINDOW', 'PRE_VIEW')

If you run the script with a project that has a cube, sphere and 🐵, all with default names, you should be able to see that they hide automatically based on the visibility_data dictionary:

Not sure if changing the rendering mode updates depsgraph, but for almost anything, consider replacing the view 3D callback with the application handler, as used here by Martynas Žiemys: Operator that runs when a value input is changed

$\endgroup$
13
  • $\begingroup$ Thank you for giving an example as well, it helped me understand how to do this. This works. $\endgroup$ Jan 29, 2022 at 5:13
  • $\begingroup$ There is a tiny issue tho, This seems to run every second which heavily impacts the scene I am working on. is there something like Run once in python? $\endgroup$ Jan 29, 2022 at 7:21
  • $\begingroup$ @YunethAlwis This runs much more often than once per second, but it doesn't affect the scene in my tests. If you can reproduce the issue in a .blend file you can share, I'll be willing to look into it. Running first 5 lines of the test function shouldn't be heavy on CPU even if it's run 100 times per frame. But perhaps there's an error there that causes more work to be done? Could you also tell me what's your hardware you're working on? $\endgroup$ Jan 29, 2022 at 11:02
  • $\begingroup$ My Hardware is i7 9750H, GTX 1650m. $\endgroup$ Jan 29, 2022 at 13:12
  • 1
    $\begingroup$ @YunethAlwis see the edit - that's the crucial part :) $\endgroup$ Jan 29, 2022 at 13:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .