Skip to content

Quicker Text Editing in Blender (Part 3): Keymaps

  • by

<Here be keys>

Context

I’ve been using Blender to make videos using its VSE, and I use text sequences for captions. But doing so involves a lot of repetitive setting of various things- colour, position, size, duration; so I’d like to speed up that process, rather than faff about setting them in the sidebar. My videos can have a lot of text sequences!

Last time we wrote some code to generate Operators (the Blender type) dynamically based on Enums- so we can have, say, an enum of colours:

class Colours(Enum):
    GREEN = (0, 1, 0, 1)
    PURPLE = (0.7, 0, 0.7, 1)
    BLUE = (0, 0, 1, 1)

and get a nice set of operators:

Quicker Access Using Hotkeys

Thanks to guidance from iceythe on BlenderArtists, we can create key bindings to run operators. We can even use the more generic SetTextColour operator by setting a property on the keybinding, which will work like an argument has been passed. In their words:

To answer your original question regarding hotkeys; when you create a hotkey, the object returned is what’s called an OperatorProperties instance. You can set predefined arguments on these just like you would when defining button operators in layouts.

part of a reply on blenderartists

Even better, they ‘gib teh codes‘ and provided examples of how to implement that. It is, as they note, a lot of boilerplate for setting them up, but we’ll use that to make hotkeys for our operators. For example, for the colour operators:

class SetTextColour(TextSequenceAction):
    """Set colour of text sequence[s]"""
    bl_idname = "sequencer.settextcolor"
    bl_label = "Set Text Colour"

    colour: bpy.props.FloatVectorProperty(
        name="textcolour",
        subtype='COLOR',
        description="Colour for text",
        size=4,
        min=0.0,
        max=1.0,
        default=(0.0, 0.0, 0.0, 1),  # black in RGBA
        )

    _colour = None

    _keymaps = []

    def __init__(self):
        if self._colour:
            self.colour = self._colour

    def execute(self, context):
        for strip in bpy.context.selected_editable_sequences:
            if strip.type == "TEXT":
                strip.color = self.colour

        return {'FINISHED'}

    @classmethod
    def register(cls):
        # Boilerplate
        wm = bpy.context.window_manager
        km = wm.keyconfigs.addon.keymaps.get("Sequencer")
        if km is None:
            km = wm.keyconfigs.addon.keymaps.new(
                "Sequencer", space_type='SEQUENCE_EDITOR')

        # 'ctrl + shift + g' -> SetTextColour(color=Colours.GREEN.value)
        kmi = km.keymap_items.new(cls.bl_idname,
                                  'G', 'PRESS', ctrl=True, shift=True)
        kmi.properties.colour = Colours.GREEN.value
        cls._keymaps.append((km, kmi))
        kmi = None

        # 'ctrl + shift + b' -> SetTextColour(color=Colours.BLUE.value)
        kmi = km.keymap_items.new(cls.bl_idname,
                                  'B', 'PRESS', ctrl=True, shift=True)
        kmi.properties.colour = Colours.BLUE.value
        cls._keymaps.append((km, kmi))
        print({'INFO'}, f"_keymaps: {cls._keymaps}")

        # 'ctrl + shift + p' -> SetTextColour(color=Colours.PURPLE.value)
        kmi = km.keymap_items.new(cls.bl_idname,
                                  'P', 'PRESS', ctrl=True, shift=True)
        kmi.properties.colour = Colours.PURPLE.value
        cls._keymaps.append((km, kmi))
        print({'INFO'}, f"_keymaps: {cls._keymaps}")

    @classmethod
    def unregister(cls):
        # Remove keymaps when operator is unregistered
        for km, kmi in cls._keymaps:
            km.keymap_items.remove(kmi)
        cls._keymaps.clear()

Gives us:

Wonderful! The keys are displayed using Screencast-Keys

So we have a decent way of quickly setting colour without our hands leaving the keyboard.

Next Steps

There’s a couple of next steps:

  1. for my own use, I can produce a version with the presets (colour/position/size/duration) hard-coded, as this would let me crack on making videos, which I put on hold to write this script/addon†
  2. for general use, I would want to give the user the ability to define and customise themselves- let them set presets and the hotkeys for them as they see fit

†: in the ‘proactive laziness’ sense- ie don’t do something slowly/inefficiently/cumbersomely if you’re about to do something to make it much easier!

Tell us what's on your mind