if / else to switch operator with icons

Hi together!
I have a question: how to create a correct if/else switch for operator with icons

This example works with defined assigment toolsettings.use_snap:


snap_tool = toolsettings.use_snap            

if snap_tool == False:
        row.operator("wm.context_toggle", text="", icon="CHECKBOX_DEHLT").data_path = "tool_settings.use_snap"
else:
        row.operator("wm.context_toggle", text="", icon="CHECKBOX_HLT").data_path = "tool_settings.use_snap"

But if i tried to transfer it to a operator from an external script, it will not work.


view_tool = ?

if view_tool == False:
        row.operator("view3d.display_modifiers_viewport_off", text=",icon = ''RESTRICT_VIEW_OFF').data_path = ?
else:   
        row.operator("view3d.display_modifiers_viewport_on", text=",icon = 'RESTRICT_VIEW_ON').data_path = ?

(as eg. the operator from the display tools for modifier)

How i have to define the path?
Must i create a separate operator execusion for it?

I can’t see your problem.

Only some style recommendations:

if snap_tool == False:

That’s really not needed, you should do:

if snap_tool:
    row.operator("wm.context_toggle", text="", icon="CHECKBOX_HLT").data_path = "tool_settings.use_snap"
else:
    row.operator("wm.context_toggle", text="", icon="CHECKBOX_DEHLT").data_path = "tool_settings.use_snap"

Or even better:

icon = "CHECKBOX_HLT" if snap_tool else "CHECKBOX_DEHLT"

row.operator("wm.context_toggle", text="", icon=icon).data_path = "tool_settings.use_snap"

I try to do this with an simple operator:


            if view_tool:
                row.operator("view3d.display_modifiers_viewport_off", text="",icon = 'RESTRICT_VIEW_OFF')
            else:
                row.operator("view3d.display_modifiers_viewport_on", text="",icon = 'RESTRICT_VIEW_ON')

And this is the error:

Traceback (most recent call last):
obj = context.active_object
NameError: name ‘view_tool’ is not defined

location: <unknown location>:-1

Well, you’ll have to define it.

and how? :o
i know to define it when the operator are a default function in blender,
but not in the script…

this is example how i want to use it, to save space in a panel etc.:



import bpy
#register_tool = ???

class VIEW3D_Register_Panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Register"

    def draw(self, context):        
        layout = self.layout

        col = layout.column(align=True)
        row = col.row(align=False)
        row.operator("ui.register_operator")
        row.operator("ui.deregister_operator")        
        
        row = col.row(align=False)

        #### how to make it changeable

        row.label(text="??????")
        if register_tool:
            row.operator("ui.register_operator", icon ="DISCLOSURE_TRI_RIGHT")
        else:
            row.operator("ui.deregister_operator", icon ="DISCLOSURE_TRI_DOWN")



class VIEW3D_Circle_Panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Circle"

    def draw(self, context):        
        layout = self.layout

        col = layout.column(align=True)
        row = col.row(align=True)
        row.operator("mesh.primitive_circle_add")


class DeRegister_Operator(bpy.types.Operator):
    bl_idname = "ui.deregister_operator"
    bl_label = "DeRegister"

    def execute(self, context):
        print(self)
        self.report({'INFO'}, "DeRegister Panel") 

        bpy.utils.unregister_class(VIEW3D_Circle_Panel)
        return{'FINISHED'}


class Register_Operator(bpy.types.Operator):
    bl_idname = "ui.register_operator"
    bl_label = "Register"

    def execute(self, context):
        print(self)
        self.report({'INFO'}, "Register Panel") 

        bpy.utils.register_class(VIEW3D_Circle_Panel)
        return{'FINISHED'}


def register():
    bpy.utils.register_class(Register_Operator)
    bpy.utils.register_class(DeRegister_Operator)
    bpy.utils.register_class(VIEW3D_Circle_Panel)
    bpy.utils.register_class(VIEW3D_Register_Panel)


def unregister():
    bpy.utils.unregister_class(Register_Operator)
    bpy.utils.unregister_class(DeRegister_Operator)
    bpy.utils.unregister_class(VIEW3D_Circle_Panel)
    bpy.utils.unregister_class(VIEW3D_Register_Panel)


if __name__ == "__main__":
    register()


If there any site with simple explanation for such things,
it would be also helpful…

Depends on what it’s supposed to do. It can be based on an existing property, or a custom boolproperty etc.
What do those operators do?

There are two buttons to register and deregister a panel with further operator
Each with own icon:
row.operator(“ui.register_operator”, text=“Button 1”, icon =“DISCLOSURE_TRI_RIGHT”)
row.operator(“ui.deregister_operator”, text=“Button 2”, icon =“DISCLOSURE_TRI_DOWN”)

Now i have two Buttons. But i want only 1 Button visible when it needed > if/else
Like the Snap Button in the header line > on/off

You need a condition to check the existence of the operator then. Something like:

hasattr(bpy.types, “UI_OT_register_operator”)

Thanks you!
I don´t how to use hastr(object, “Name”) !!!
I never was so deep in blender phyton!

It was my intention to clean up the space for my panels and pie menus.
because there are to many buttons for a simple on and off.
I had not thought that this can be so complicated.
…seems to be a next level!!!

This one is an example that i know for on/off. It use an BoolProperty.
But this changed only the color behind the icon and not the icon by itself.


import bpy

bpy.types.Scene.osc_circle = bpy.props.BoolProperty(default=False)

class SubLoc_CIRCLE():
    """De-/Register for Circle Panel"""
    bl_region_type = 'UI'
    bl_space_type = 'VIEW_3D' 

    @classmethod
    def poll(cls, context):
        return context.scene.osc_circle
    
class VIEW3D_Circle_Panel(SubLoc_CIRCLE, bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Circle"

    def draw(self, context):        
        layout = self.layout

        row = layout.row()
        row.operator("mesh.primitive_circle_add")

    
class VIEW3D_Register_Panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Register"

    def draw(self, context):        
        layout = self.layout

        row = layout.row() 
        #changed the color behind the icons  
        row.prop(bpy.context.scene, "osc_circle", text="Circle Panel", icon="MESH_CIRCLE")

def register():

    bpy.utils.register_class(VIEW3D_Circle_Panel)
    bpy.utils.register_class(VIEW3D_Register_Panel)
    
def unregister():

    bpy.utils.unregister_class(VIEW3D_Circle_Panel)
    bpy.utils.unregister_class(VIEW3D_Register_Panel)


if __name__ == "__main__":
    register()

…maybe I still check it later :slight_smile:

Well, you got a special case there. It’s usually a bit simpler:


import bpy


class RENDER_PT_custom_panel(bpy.types.Panel):
    bl_label = "Custom Panel"
    bl_idname = "RENDER_PT_custom_panel"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"


    def draw(self, context):
        layout = self.layout
        ob = context.object
        
        if ob.type == "EMPTY":
            # an Empty object has no .data attribute we could get an icon for
            layout.prop(ob, "name", icon="EMPTY_DATA")
        else:
            # use data type specific icon, or preview if available
            layout.prop(ob, "name", icon_value=layout.icon(ob.data))




def register():
    bpy.utils.register_module(__name__)




def unregister():
    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()