1
import bpy

from bpy.props import (StringProperty,
                       PointerProperty,
                       )

from bpy.types import (Panel,
                       Operator,
                       PropertyGroup,
                       )

class MySettings(PropertyGroup):

    my_objs: StringProperty(
        name="Object Name",
        description="Helper property to store an object name",
        )


class SimpleOperator(Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Viewports and Renders"

    @classmethod
    def poll(cls, context):
        return len(context.selected_objects)


    def execute(self, context):
        for objs in bpy.context.selected_objects:
            objs.hide_render = False

        return {'FINISHED'}


class OBJECT_PT_CustomPanel(Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "My_test"
    bl_context = "objectmode"   

    @classmethod
    def poll(cls, context):
        return len(context.selected_objects)

    def draw(self, context):
        layout = self.layout
        row = layout.row(align=True)
        row.prop(context.object, "hide_render", text='')

classes = (
    MySettings,
    SimpleOperator,
    OBJECT_PT_CustomPanel,
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Scene.my_tool


if __name__ == "__main__":
    register()

I'm trying to run the script in Blender 2.93.5 for selected objects, but it is only working for the active object.

UPDATED:

If I change as suggested the property for a operator, the script works as it should. The thing is that I would like to keep the property because the icon change it's "looks" when clicked as you see in the current UI, but if I change it for an operator the button is not the same.

Some extra details in the question, what if half of the objects are hidden?, since the default function is to set all selected objects hidden from render, the script should check which ones are hidden already and hide the ones that are not hidden, when clicking the button again, all selected should become visible then.

pekkuskär
  • 307
  • 2
  • 11
  • 2
    You are displaying the property of the context.object instead add an operator button to layout row.operator("object.simple_operator") to invoke the operator. \ – batFINGER Oct 29 '21 at 10:46
  • Thanks, but the problem with it is that is not toggling the hide_render of course I can add this
                if objs.hide_render == False:
                    objs.hide_render = True
                else:
                    objs.hide_render = False
    

    in the operator, but then the icon toggle property is missing.

    – pekkuskär Oct 29 '21 at 10:54
  • so what do you want now? a button which just does all selected object to "not hide in render"? or a toggle button? In your old code you just set hide_render to false - there was no toggle functionality at all – Chris Oct 29 '21 at 11:00
  • or with exclusive or ob ^= True – batFINGER Oct 29 '21 at 11:02
  • @Chris, so that's where my problem resides then, I'm going after having the current behavior toggle button but acting on all selected objects and not only on the active one. So there is some code missing which I don't know. – pekkuskär Oct 29 '21 at 11:08
  • @batFINGER thanks for the hint. – pekkuskär Oct 29 '21 at 11:08
  • Could loop thru all objects in draw and layout their hide render props. And also add an operator button(s) that sets all to True / False or toggles based on an operator property. Not unlike a select operator. – batFINGER Oct 29 '21 at 11:10
  • Ok, now that got more complicate than what I anticipated :/. I had no idea you could loop inside the panel (if I understood right). one thing I noticed from my current code is that if I hold Alt then all selected objects gets hidden, maybe a easier way is to mimic the Alt key pressed? But then a prop won't work with index, so it has to be an operator? – pekkuskär Oct 29 '21 at 11:20
  • Loop in panel to display all properties (will get ugly if too many selected) Alt "prop click" will set all selected (with that prop) to value of active. (this works everywhere) No idea where you are going re index? Index of what? To me the original question related to only having context object's property in panel. To set also add the active to layout and using ALT will make setting selected to value of active easy. If a toggle is required see answer below. Somewhat related https://blender.stackexchange.com/questions/23998/python-ctrlclick-for-buttons-capture-invocation-event – batFINGER Oct 29 '21 at 11:35

1 Answers1

1

so if i understood you right, you want this:

enter image description here

which you can get by this:

import bpy

from bpy.props import (StringProperty, PointerProperty, )

from bpy.types import (Panel, Operator, PropertyGroup, )

class MySettings(PropertyGroup):

my_objs: StringProperty(
    name="Object Name",
    description="Helper property to store an object name",
    )


class SimpleOperator(Operator): """Tooltip""" bl_idname = "object.simple_operator" bl_label = "Toggle Render"

@classmethod
def poll(cls, context):
    return len(context.selected_objects)


def execute(self, context):
    print("in execute")
    for objs in bpy.context.selected_objects:
        print(objs)
        objs.hide_render = not objs.hide_render

objs.hide_render = False

    return {'FINISHED'}


class OBJECT_PT_CustomPanel(Panel): bl_label = "My Panel" bl_idname = "OBJECT_PT_custom_panel" bl_space_type = "VIEW_3D"
bl_region_type = "UI" bl_category = "My_test" bl_context = "objectmode"

@classmethod
def poll(cls, context):
    print("in poll")
    return len(context.selected_objects)

def draw(self, context):
    print("in draw")
    layout = self.layout
    row = layout.row(align=True)
    row.operator("object.simple_operator")

row.prop(context.object, "hide_render", text='')

classes = ( MySettings, SimpleOperator, OBJECT_PT_CustomPanel, )

def register(): from bpy.utils import register_class for cls in classes: register_class(cls)

bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) del bpy.types.Scene.my_tool

if name == "main": print("in main") register()

Chris
  • 59,454
  • 6
  • 30
  • 84
  • Thank you for the example it could solve some other things. I may have explained myself not clear enough, what I'm going after is to be bale to change the toggle icon depending if the selected objects are hidden or not from render. I'm trying to disect the code to use it on a UIList so I can use the icon changing (toggling) per list index. I hope I explained myself more clear now. – pekkuskär Oct 29 '21 at 11:29
  • 3
    Yeah recommend edit question with all extra details. ... what if half selected are hidden? – batFINGER Oct 29 '21 at 11:40
  • Question has been updated with further details. – pekkuskär Nov 01 '21 at 06:13