Here's an adjustment of the answer to this q Getting area (region.view2d) pixel coordinates of 2D views (VSE, NLA)
Run the script, use the spacebar to search out the "Simple Modal Sequencer Operator" and the current frame will change with the mouse.
The key method is region.view2d.region_to_view
which returns, in this case, the frame in x and the strip channel in y, from the regions pixel coords.
import bpy
import bgl
import blf
def draw_callback_px(self, context):
print("mouse points", len(self.mouse_path))
region = context.region
strip = context.scene.sequence_editor.active_strip
if strip is None:
return
x = strip.frame_final_start
y = strip.channel
x, y = region.view2d.view_to_region(x, y)
font_id = 0 # XXX, need to find out how best to get this.
# draw some text
blf.position(font_id, x, y, 0)
blf.size(font_id, 20, 72)
# region_to_view gives the region coords. x is frame, y is channel.
x, y = region.view2d.region_to_view(*self.mouse_path[-1] )
blf.draw(font_id, "Hello Word %d %d" % (x, y))
# move the frame to the mouse
context.scene.frame_set(x)
class ModalDrawOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
bl_idname = "sequencer.modal_operator"
bl_label = "Simple Modal Sequencer Operator"
def modal(self, context, event):
context.area.tag_redraw()
region = context.region
if event.type == 'MOUSEMOVE':
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'LEFTMOUSE':
bpy.types.SpaceSequenceEditor.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceSequenceEditor.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'SEQUENCE_EDITOR':
# the arguments we pass the the callback
args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = bpy.types.SpaceSequenceEditor.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
self.mouse_path = []
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "SequenceEditor not found, cannot run operator")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(ModalDrawOperator)
if __name__ == "__main__":
register()
PS I slapped this together pretty quickly and put code in the draw hander rather than the event loop of the operator. Will fix later...