Blender python How do I add buttons to the graph editor?

Here’s my code. How do I change it so that I can get a button on the graph editor? There seems to be. A normalize button in the way… How can I rewrite this code so it adds buttons after that normalize? I need to put three buttons on there. Thanks for any help.

def draw_graph_editor(self, context):
    manager = context.scene.super_solid_mode
    layout = self.layout
        
    if manager.to_timeline_ge:
        col = layout.column()
        col.operator("ssm.switch_to_timeline_ge", text="", icon="TIME")
        
    if manager.to_sequencer_ge:
        col = layout.column()
        col.operator("ssm.switch_to_sequencer_ge", text="", icon="SEQUENCER")
        
    if manager.to_shader_editor_ge:
        col = layout.column()
        col.operator("ssm.switch_to_shader_editor_ge", text="", icon="NODE_MATERIAL")

I would like the buttons to be on the header of the graph editor to the right of the normalize button. I would like to put a few buttons up there. If somebody could show me how to write the code to add just one… I could figure out the rest… I would appreciate it.

you can’t add an icon right after the normalize button because that would be in the middle of another layout. If you want to do that you’ll need to either edit or extend/hijack the built-in GRAPH_HT_header class, which I wouldn’t recommend unless you know what you’re doing.

As an alternative, you can prepend a button and it will show up on the far left like so:

If you use append instead of prepend, your button will be on the far right over by the proportional editing controls:

import bpy

@bpy.app.handlers.persistent
def graph_editor_button_draw(self, context):
    layout = self.layout
    layout.operator_context = 'EXEC_DEFAULT'
    layout.operator(
        operator='wm.url_open_preset',
        text='',
        icon='QUESTION'
    ).type = 'API'    

def register():
    bpy.types.GRAPH_HT_header.prepend(graph_editor_button_draw)

def unregister():
    bpy.types.GRAPH_HT_header.remove(graph_editor_button_draw)

if __name__ == '__main__':
    register()

Here is the relevant code maybe you could tell me why when I run this code inside my add on… I get 4 buttons where I would like them, right next to the scripting tab on TOPBAR (actually would like a little spacer Between the Scripting tab and where my buttons begin… if you could tell me how to do that too)

but I also get duplicated buttons, same 4 of, all the way to the right of the TOPBAR

Any help on this is appreciated!

# TOPBAR       
def draw_topbar(self, context):
    manager = context.scene.super_solid_mode
    layout = self.layout
        
    if manager.switch_object:
        col = layout.column()
        col.operator("ssm.switch_object", text="", icon="OBJECT_DATA")        
    if manager.switch_edit:
        col = layout.column()
        col.operator("ssm.switch_edit", text="", icon="EDITMODE_HLT")
        
    if manager.switch_pose:
        col = layout.column()
        col.operator("ssm.switch_pose", text="", icon="POSE_HLT")   
        
    if manager.switch_sculpt:
        col = layout.column()
        col.operator("ssm.switch_sculpt", text="", icon="SCULPTMODE_HLT")     


bpy.types.TOPBAR_HT_upper_bar.append(draw_topbar)
bpy.types.TOPBAR_HT_upper_bar.remove(draw_topbar)


I attached my INIT.PY below

init.py|attachment (15.5 KB)

It looks like your question is related to this other question you asked- probably better to just continue the conversation there than to start a brand new topic, yeah?

Related tangent- people are more likely to help you when you have a history of marking your questions as solved, or acknowledge the assistance that’s been given with a ‘hey thanks’ or something along those lines. if you treat the forum like a google search engine and just shoot questions into the void people are less likely to assist in the future. food for thought :slight_smile:

To answer your question- it’s hard to say since I don’t know what “super_solid_mode” is (your init references SSM_Properties, which is in an external module), but at a guess I would say that all four of your properties are True, and thus- you get four buttons. rather than having four ‘if’ statements, you could use ‘if’ followed by ‘elif’, etc.

Side note: most people aren’t going to download an attachment. if your code is too long to drop directly into your post, consider using pastebin.

I had a quick question I created this class and I created also a button on the top bar with the prepend function and the buttons working OK but when I try and run this class with it it’s not switching to wireframe mode, it just does nothing… can you give me an idea what’s going on real quick

the code runs OK in the text editor but I don’t know how to test it in in the text editor…as if I was on the top bar…so I could figure out exactly what the code needs

class SSM_OT_switch_wire(bpy.types.Operator):
    """Switch to Wire Shading"""
    bl_idname = "ssm.switch_wire"
    bl_label = "Switch to Wire shading"
    bl_options = {"REGISTER",}

    def execute(self, context):
        def set_shading_mode(mode="SOLID", screens=None):
            # """
            # Performs an action analogous to clicking on the display/shade button of
            # the 3D view. Mode is one of "RENDERED", "MATERIAL", "SOLID", "WIREFRAME".
            # The change is applied to the given collection of bpy.data.screens.
            # If none is given, the function is applied to bpy.context.screen (the
            # active screen) only. E.g. set all screens to rendered mode:
              # set_shading_mode("RENDERED", bpy.data.screens)
            # """
            screens = screens or [bpy.context.screen]
            for s in screens:
                for spc in s.areas:
                    if spc.type == "VIEW_3D":
                        spc.spaces[0].shading.type = mode
                        break # we expect at most 1 VIEW_3D spacef space is a 3D view
                        space.shading.type = 'WIREFRAME'
                        
        try:
            set_shading_mode()
        except Exception as error:
            catch_error(error)                

        return {'FINISHED'}

break terminates the function. Any line of code written after it will never run. You should put it in the last position of your if indented code block :

                        spc.spaces[0].shading.type = mode
                        space.shading.type = 'WIREFRAME'
                        break # we expect at most 1 VIEW_3D spacef space is a 3D view

Thank you for your answer… I think my issue was that 1 of my icons was named ‘SEQUENCER’ instead of ‘SEQUENCE’…so my code worked when I change it…but now I can use prepend…so that is awesome…its all updated now so if you want a free copy of my addon(Super-Solid-Mode) PM me

Thank you so much I’m getting better at coding and this will teach me to look for those things better…Blender has such a strong API it’s so easy to write strong stable code in it!

Hehe yeah python doesn’t have a lot of keywords but they all have their use. Note in this specific case if you have an IDE it should have somehow highlighted the statements directly after the break and told you this wouldn’t ever run. I know VS Code does that.

image

image

Note the faint transparency on the unreachable code.

Cheers

just started using VSCODE…much happier now!

Nice. There are other ones, some paid and some free, I suggest you try out other things and see for yourself what’s best for you. If you choose VS Code, don’t forget the blender extension by Jacques Lucke. I can only recommend this how-to for a smooth workflow in VS Code https://b3d.interplanety.org/en/using-microsoft-visual-studio-code-as-external-ide-for-writing-blender-scripts-add-ons/