0
$\begingroup$

I'm trying to write a sequencer add-on. I need it to add a bgl UI on top of the sequencer timeline, without a real interactive part, so I'm trying to make it a kind of "static handler" (I'm no coder, I don't know the specific term for it) instead of a modal operator with timer.
So far, I have this working, but I can't find a way to unregister it correctly when deactivating the add-on...
Here's example code with "hello world":

bl_info = {  
 "name": "modaltest",  
 "author": "tonton",  
 "version": (0, 1),  
 "blender": (2, 7, 9),  
 "location": "Sequencer",  
 "description": "",  
  "wiki_url": "",  
 "tracker_url": "",  
 "category": "Sequencer"}

import bpy
import bgl
import blf


def draw_callback_px():

    font_id = 0  # XXX, need to find out how best to get this.

    # draw some text
    blf.position(font_id, 15, 30, 0)
    blf.size(font_id, 20, 72)
    blf.draw(font_id, "Hello Word ")


def register():
    bpy.types.SpaceSequenceEditor.draw_handler_add(draw_callback_px, (), 'WINDOW', 'POST_PIXEL')

def unregister():
    bpy.types.SpaceSequenceEditor.draw_handler_remove(draw_callback_px)

I tried a bunch of ways to unregister the handler, nothing so far has worked. Do you know what I am doing wrong? Thank you very much in advance! :D

$\endgroup$
5
  • 1
    $\begingroup$ 2d example: How to draw shapes in the node editor with python bgl? Just replace the Space to SpaceSequenceEditor and Area.type $\endgroup$
    – brockmann
    Commented Jan 17, 2018 at 11:34
  • $\begingroup$ thanks for the answer, but i don't have problem with the drawing itself, but i don't want it to be a modal. In my code you can see i register the handler, not a modal. This way, the drawing is here anytime (loaded at opening) when the script is installed as an addon, but i can't find the way to unregister it... $\endgroup$
    – tonton
    Commented Jan 17, 2018 at 11:59
  • $\begingroup$ Similarly there is this method that doesn't require a modal handler. $\endgroup$
    – batFINGER
    Commented Jan 17, 2018 at 14:15
  • $\begingroup$ thanks @batFINGER, this method seems to work also, but i don't have a clue to unregister this properly neither... (sorry if that's a dumb question!) $\endgroup$
    – tonton
    Commented Jan 17, 2018 at 14:48
  • $\begingroup$ NP. Suggest make a global list or dic eg widgets = {} defined globally. Add to in register widgets["Foo"] = DisplayClass() and in unregister for key, dc in widgets.items(): dc.remove_handle() Note might be an issue passing context as argument from register method, could instead use bpy.context in draw callback. It's late here, will get back to it if need be. $\endgroup$
    – batFINGER
    Commented Jan 17, 2018 at 14:52

1 Answer 1

1
$\begingroup$

Define a "drawing class".

Similarly to method used in this answer When registered the widgets are drawn on all VSE spaces. When unregistered the drawing handles are removed. Simple message and location passed to class. In script below two "widgets" are created drawing "Bob" and "Jack" at different locations on VSE.

enter image description here

bl_info = {  
 "name": "VSE blf test",  
 "author": "",  
 "version": (0, 1),  
 "blender": (2, 7, 9),  
 "location": "Sequencer",  
 "description": "",  
  "wiki_url": "",  
 "tracker_url": "",  
 "category": "Sequencer"}

import bpy
import blf

class DrawingClass:
    def __init__(self, msg, loc):
        self.msg = msg
        self.loc = loc
        self.handle = bpy.types.SpaceSequenceEditor.draw_handler_add(
                   self.draw_text_callback,(loc,),
                   'WINDOW', 'POST_PIXEL')

    def draw_text_callback(self, loc):
        font_id = 0  # XXX, need to find out how best to get this.

        # draw some text
        x, y = self.loc
        blf.position(font_id, x, y, 0)
        blf.size(font_id, 66, 72)
        blf.draw(font_id, "%s" % (self.msg))

    def remove_handle(self):
         bpy.types.SpaceSequenceEditor.draw_handler_remove(self.handle, 'WINDOW')

widgets = {}
def register():
    widgets["Bob"] = DrawingClass("Bob", (0, 0))
    widgets["Jack"] = DrawingClass("Jack", (140, 140))    

def unregister():
    for key, dc in widgets.items():
        dc.remove_handle()

if __name__ == "__main__":
    register()

Might find this handy for 2D coordinates in VSE.

PS. Initially forgot to change SpaceView3D type in handle_remove, and found another sure fire way to crash blender. Suggest actually passing the space type to class as well as demonstrated in BGLWidget class

$\endgroup$
1
  • $\begingroup$ thanks a lot for this very complete answer ! works like a charm ! you, sir, just made my day ! :) $\endgroup$
    – tonton
    Commented Jan 17, 2018 at 17:50

You must log in to answer this question.

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