2
$\begingroup$

Bug in addon to change header color dynamically

I made an add-on that changes the theme color of the header if the automatic keyframe feature is enabled.

The color change function works fine.

However, the following bug occurs in the object gizmo transform gizmo.

  • Mouse hovers no longer highlight
  • Drag operation is delayed a little

    Why do bugs occur in Gizmo by changing the theme color? I have no idea.

enter image description here

python

import bpy

bl_info = {
    "name" : "header_color_change",
    "author" : "Bookyakuno",
    "version" : (1, 0, 0),
    "blender" : (2, 80, 0),
    "location" : "hoge",
    "description" : "hoge",
    "category" : "UI"
}


def TEST_HT_header_color_change(self, context):
    layout = self.layout
    layout.label(text="")


    if bpy.context.scene.tool_settings.use_keyframe_insert_auto == True:
        bpy.context.preferences.themes[0].topbar.space.header = (0.4, 0.000000, 0.000000, 1.000000)

    else:
        bpy.context.preferences.themes[0].topbar.space.header = (0.137255, 0.137255, 0.137255, 1.000000)

    return {'FINISHED'}


def register():
    bpy.types.TOPBAR_HT_upper_bar.append(TEST_HT_header_color_change)

def unregister():
    bpy.types.TOPBAR_HT_upper_bar.remove(TEST_HT_header_color_change)

if __name__ == "__main__":
    register()

'''

$\endgroup$

2 Answers 2

1
$\begingroup$

In a draw callback

As an alternative to using onload and update handlers, could make it a draw callback on the 3d view space.

The added bonus here is can write some text to screen, in addition to or instead of colouring header.

EDIT minor adjustment to keep themes bg color. Only tested running from console.

import blf
import bpy

bl_info = {
    "name": "New Object",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > New Object",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "wiki_url": "",
    "category": "Add Mesh",
}

highlight_color = (0.4, 0, 0, 1)

class DrawingClass:
    def __init__(self, prop):
        print("INT DC")
        from bpy import context
        self.prop = prop
        self.col = context.preferences.themes[0].topbar.space.header[:] 
        self.handle = bpy.types.SpaceView3D.draw_handler_add(
            self.draw_text_callback, (), 'WINDOW', 'POST_PIXEL')

    def draw_text_callback(self):
        from bpy import context
        font_id = 0  # XXX, need to find out how best to get this.
        if not hasattr(context, "scene"):
            return None
        scene = context.scene
        if scene.tool_settings.use_keyframe_insert_auto:
            context.preferences.themes[0].topbar.space.header = highlight_color
            # draw some text
            blf.position(font_id, 15, 50, 0)
            blf.size(font_id, 20, 72)
            blf.draw(font_id, "%s %s" % (context.scene.name, self.prop))

        else:
            context.preferences.themes[0].topbar.space.header = self.col

    def remove_handle(self):
        from bpy import context
        context.preferences.themes[0].topbar.space.header = self.col
        bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')


dc = None


def register():
    global dc
    dc = DrawingClass("Draw This On Screen")

def unregister():
    global dc
    if dc:
        dc.remove_handle()
        dc = None

if __name__ == "__main__":
    register()
$\endgroup$
3
$\begingroup$

I think that the issue comes from changing preference data during a UI draw, that is, you are accessing data that should not be altered while drawing the UI.

An alternative approach that seems to work is using handlers to alter the theme settings. In 2.80 the scene_update_* handlers have been renamed to depsgraph_update_*.

def TEST_prefset(scene):
    prefs = bpy.context.preferences

    if scene.tool_settings.use_keyframe_insert_auto == True:
        prefs.themes[0].topbar.space.header = (0.4, 0.000000, 0.000000, 1.000000)

    else:
        prefs.themes[0].topbar.space.header = (0.137255, 0.137255, 0.137255, 1.000000)


def register():
    bpy.app.handlers.depsgraph_update_post.append(TEST_prefset)

def unregister():
    bpy.app.handlers.depsgraph_update_post.remove(TEST_prefset)
$\endgroup$
1
  • $\begingroup$ I found that my method was not appropriate. The code attached to the reference fixed the Gizmo bug, but it didn't load at Blender startup and it didn't work (it will work if you reload the add-on itself every time). Therefore, I improved it to read by "load_post" using "persistent", This method is loaded at boot time. Thank you for teaching me the handler. header_color_change.py - github $\endgroup$
    – Bookyakuno
    Jun 7, 2019 at 14:26

You must log in to answer this question.

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