You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Workspace Tools变更时运行bpy回调并添加预绘制钩子?

解决Workspace Tools变更的预绘制钩子延迟问题

核心思路:用消息订阅替代绘制时轮询

放弃在SpaceView3D.draw_handler_add里每次绘制都检查工具变更的方式,改用Blender内置的bpy.msgbus机制直接监听工具切换事件,能在工具变更的第一时间触发回调,彻底解决帧延迟和依赖用户重绘的问题。

具体实现步骤

1. 定义监听的属性路径

Workspace当前激活工具的存储路径是bpy.context.workspace.tools.active,我们直接监听这个属性的变更:

import bpy
from bpy.types import Context

# 设定要监听的属性
subscribe_target = (bpy.types.WorkSpaceTools, "active")

2. 编写工具变更回调函数

回调里可以直接处理工具切换后的逻辑,包括添加自定义绘制处理器,因为是实时触发,不会有延迟:

def tool_switch_callback(context: Context):
    # 先清理之前的绘制处理器,避免重复添加
    if hasattr(bpy.types.SpaceView3D, "_custom_draw_handler"):
        bpy.types.SpaceView3D.draw_handler_remove(
            bpy.types.SpaceView3D._custom_draw_handler,
            'WINDOW'
        )
    
    active_tool = context.workspace.tools.active
    # 这里可以添加你的业务逻辑,比如根据当前工具加载对应的绘制逻辑
    print(f"已切换工具: {active_tool.name}")
    
    # 定义自定义绘制逻辑
    def custom_draw():
        # 示例:在视口左上角绘制当前工具名称
        bpy.ops.view3d.text(
            text=f"当前工具: {active_tool.name}",
            location=(10, 30),
            size=12
        )
    
    # 添加新的绘制处理器
    bpy.types.SpaceView3D._custom_draw_handler = bpy.types.SpaceView3D.draw_handler_add(
        custom_draw,
        (),
        'WINDOW',
        'POST_PIXEL'
    )
    
    # 主动标记视口重绘,确保绘制内容立即显示
    for area in bpy.context.screen.areas:
        if area.type == 'VIEW_3D':
            area.tag_redraw()

3. 注册与取消消息订阅

在插件注册(或脚本运行)时绑定订阅,退出时清理:

def register():
    # 注册消息订阅,绑定回调
    bpy.msgbus.subscribe_rna(
        key=subscribe_target,
        owner=bpy.types.WorkSpaceTools,
        args=(bpy.context,),
        notify=tool_switch_callback,
    )

def unregister():
    # 取消订阅
    bpy.msgbus.clear_by_owner(bpy.types.WorkSpaceTools)
    # 清理遗留的绘制处理器
    if hasattr(bpy.types.SpaceView3D, "_custom_draw_handler"):
        bpy.types.SpaceView3D.draw_handler_remove(
            bpy.types.SpaceView3D._custom_draw_handler,
            'WINDOW'
        )

if __name__ == "__main__":
    register()

关键优势

  • 无延迟触发:工具切换瞬间就调用回调,不需要等待下一帧绘制
  • 性能更优:避免了每次绘制都执行检查逻辑的额外开销
  • 主动重绘:回调末尾手动触发视口重绘,确保自定义内容立即显示

内容的提问来源于stack exchange,提问作者ThorSummoner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:50:21