ThorSummoner
ThorSummoner

Reputation: 18159

how to run bpy callback on workspace tools change

How to add a pre-draw hook to current context workspace.tools change?

I attempted to get there using bpy.types.SpaceView3D.draw_handler_add(...) which as it runs on every draw, checks if workspace.tools changed, and if it changed, run my callback, but my callback wants to add its own SpaceView3D.draw_handler_add and doing it this way adds it a frame-too-late, leaving the view port undrawn until a user event repaints the screen.

Upvotes: 0

Views: 313

Answers (1)

ThorSummoner
ThorSummoner

Reputation: 18159

I found this post online https://devtalk.blender.org/t/update-property-when-active-tool-changes/11467/12

summary: maybe there is a mainline callback new https://developer.blender.org/D10635

AFWS Jan '20

@kaio

This seem like a better solution. It’s kind of a mystery code, cause I couldn’t figure out where you got that code info ,but then started looking at the space_toolsystem_common.py file. kaio AFWS Jan '20

Just realized there might be a cleaner way of getting callbacks for active tools using the msgbus. Since workspace tools aren’t rna properties themselves, figured it’s possible to monitor the bpy_prop_collection which changes with the tool.

The handle is the workspace itself, so shouldn’t have to worry about keeping a reference. The subscription lasts until a new file is loaded, so add a load_post callback which reapplies it.

Note this doesn’t proactively subscribe to workspaces added afterwards. Might need a separate callback for that :joy:

import bpy

def rna_callback(workspace):
    idname = workspace.tools[-1].idname
    print(idname)

def subscribe(workspace):
    bpy.msgbus.subscribe_rna(
        key=ws.path_resolve("tools", False),
        owner=workspace,
        args=(workspace,),
        notify=rna_callback)

if __name__ == "__main__":
    ws = bpy.context.workspace
    subscribe(bpy.context.workspace)

# Subscribe to all workspaces: if 0:
    for ws in bpy.data.workspaces:
        subscribe(bpy.context.workspace)

# Clear all workspace subscriptions if 0:
    for ws in bpy.data.workspaces:
        bpy.msgbus.clear_by_owner(ws)

Upvotes: 1

Related Questions