I have coded a custom GizmoGroup to manipulate the effects strip in the VSE visually. It works in principle, but unfortunately I can't line up the gizmo with the picture, because the gizmo ignores any zooming and panning of the preview area. Putting 'SCALE' in the bl_options does nothing and '3D' makes my gizmo disappear. Is there any other way to make my gizmo respect zoom and pan?

I have the same problem in the node editor, so hopefully there is a general way to do this. This is my code, if it is interesting:

import bpy
from bpy.props import *
from mathutils import Matrix, Vector
from .. register import autoregister, autoreload
from itertools import chain
from math import degrees

class TransformEffectGroup(bpy.types.GizmoGroup):
    bl_idname = 'CS_GGT_transform_effect'
    bl_space_type = 'SEQUENCE_EDITOR'
    bl_region_type = 'PREVIEW'
    bl_label = 'Transform Effect Gizmo'
    bl_options = { 'PERSISTENT', 'SCALE' }

    def poll(cls, context):
        active_strip = context.scene.sequence_editor.active_strip
        return not active_strip is None and active_strip.type == 'TRANSFORM'

    def setup(self, context):
        active_strip = context.scene.sequence_editor.active_strip
        print(f"setup {active_strip}")
        gizmo = self.gizmos.new("GIZMO_GT_cage_2d")
        gizmo.target_set_handler("matrix", get=self.get_matrix, set=self.set_matrix)
        gizmo.dimensions = (100, 100)
        gizmo.use_draw_modal = True
        gizmo.transform = { 'SCALE_UNIFORM', 'TRANSLATE', 'ROTATE' }
        if not active_strip is None and active_strip.type == 'TRANSFORM':
            self.strip = active_strip

    def refresh(self, context):
        active_strip = context.scene.sequence_editor.active_strip
        print(f"refresh {active_strip}")
        gizmo = self.gizmos[0]
        if not active_strip is None and active_strip.type == 'TRANSFORM':
            self.strip = active_strip

    def get_matrix(self):
        m  = Matrix.Scale(self.strip.scale_start_x, 4, Vector((1, 0, 0))) \
           @ Matrix.Scale(self.strip.scale_start_y, 4, Vector((0, 1, 0))) \
           @ Matrix.Rotation(self.strip.rotation_start, 4, 'Z') \
           @ Matrix.Translation(Vector((self.strip.translate_start_x, self.strip.translate_start_y, 0)))
        return chain.from_iterable(m)

    def set_matrix(self, m):
        matrix = Matrix((m[0:16:4], m[1:16:4], m[2:16:4], m[3:16:4]))
        t, r, s = matrix.decompose()
        self.strip.translate_start_x = t[0]
        self.strip.translate_start_y = t[1]
        s = matrix.to_scale()
        self.strip.scale_start_x = s[0]
        self.strip.scale_start_y = s[1]
        self.strip.rotation_start = degrees(r.to_euler('ZYX')[-1])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.