Screencast keys status tool


(paulo_gomes) #1

hi all, this is a wip. I’m trying to learn python scripting and this is my first project. What the script does, is show the keys you press in the lower left corner of the 3Dview. The idea is to have a visual aid of the shortcuts when doing screencasts with blender. I also want to thanks Crouch for his pacience with me.

Load the script in blender’s text editor, then run it. Go to 3dview press space and search for ‘Screencast Key Status Tool’ and execute it. Now the keys you press should appear in the lower left corner. To disable the script press F7.

here’s a short video showing the script in action:

and here’s the script:

you can now copy it to your addon directory and enable it in the user preferences addon menu, thanks Meta-Androcto


# Blender Add-Ons menu registration (in User Prefs)
"Screencast (View3D > Tools > Draw Screencast)"
import bpy
import bgl
import blf
import time

def draw_callback_px(self, context):

    # draw some text
    blf.size(20, 72)
    
    final = 0
    for i in range(len(self.key)):
        if time.time()-self.time[i] < 2:
            blf.position(15, 50+20*i, 0)
            blf.draw(self.key[i])
            final = i
        else:
            break
    self.key = self.key[:final+1]
    self.time = self.time[:final+1]
    

class ScreencastKeysStatus(bpy.types.Operator):
    '''Draw keys pressed in 3DView'''
    bl_idname = "view3d.screencast_keys"
    bl_label = "Screencast Key Status Tool"

    def modal(self, context, event):
        context.area.tag_redraw() 
        
  
        ignore_keys = ['LEFT_SHIFT', 'RIGHT_SHIFT', 'LEFT_ALT', 'RIGHT_ALT', 'LEFT_CTRL',
'RIGHT_CTRL', 'TIMER', 'MOUSEMOVE', 'MIDDLEMOUSE', 'LEFTMOUSE',
'RIGHTMOUSE', 'WHEELDOWNMOUSE', 'WHEELUPMOUSE']

        if event.value == 'PRESS':        
            
            sc_keys = []
            
            if event.shift:
                sc_keys.append('Shift ')
        
            if event.alt:
                sc_keys.append('Alt ')
        
            if event.ctrl:
                sc_keys.append('Ctrl ')

            if event.type not in ignore_keys:
                sc_keys.append(event.type)
            
                self.key.insert(0, "+ ".join(map(str, sc_keys)))
                self.time.insert(0, time.time())

        if event.type == ('F7'):
            context.region.callback_remove(self._handle)
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            context.manager.add_modal_handler(self)

            # Add the region OpenGL drawing callback
            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
            self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL')

            self.key = []
            self.time = []
      

            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}


def register():
    bpy.types.register(ScreencastKeysStatus)


def unregister():
    bpy.types.unregister(ScreencastKeysStatus)


if __name__ == "__main__":
    register()


(GottfriedHofmann) #2

Wow! This is very usefull and should be added to the default install imho. Thank you!
Actually I was thinking about implementing something similiar myself…


(Meta-Androcto) #3

hi, very good job.
hopefully this can lead the way with onscreen hotkeys for the pressed button & other cool educational tools.


(Sunjay03) #4

Its pretty cool…but this isn’t exactly BGE. This is more of something that would go into the Python & Plugins area.


(GottfriedHofmann) #5

It’s working in alpha2 but not on latests builds from Graphicall :frowning:


(Nichod) #6

Is there an error message?


(GottfriedHofmann) #7

No. In Add-Ons it now just displays as ‘key’. After enabling i can run it or add it to the tool shelf als ‘Screencast Key Status Tool’ but nothing happens anymore.

Tested on blender25_r28606_omp_64bit built by Fish


(Crouch) #8

The script was broken by changes in Blender’s api (in specific, the addition of fontid in the blf module). I’ve fixed it in the Blender Extensions project. It’s now working correctly again for current svn (tested on 28653).
Download link

Or copy/paste it from below:

# Original Script by: Paulo Gomes
# Contact: [email protected]
# 
# Contributor(s): Bart Crouch
#
# Tested with r28653
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####


import bpy
import bgl
import blf
import time


# information for the add-ons window
bl_addon_info = {
    'name': '3D View: Screencast Key Status Tool',
    'author': 'Paulo Gomes',
    'version': '0.3',
    'blender': (2, 5, 2),
    'location': 'View3D > Spacebar > Search for "Screencast Key Status Tool"',
    'description': 'Display keys pressed in the 3d-view, useful for screencasts.',
    'category': '3D View'}


def draw_callback_px(self, context):
    # draw text in the 3d-view
    blf.size(0, 20, 72)
    final = 0

    # only display key-presses of last 2 seconds
    for i in range(len(self.key)):
        if time.time()-self.time[i] < 2:
            blf.position(0, 15, 50+20*i, 0)
            blf.draw(0, self.key[i])
            final = i
        else:
            break

    # get rid of statuses that aren't displayed anymore
    self.key = self.key[:final+1]
    self.time = self.time[:final+1]
    

class ScreencastKeysStatus(bpy.types.Operator):
    '''Draw keys pressed in 3DView'''
    bl_idname = "view3d.screencast_keys"
    bl_label = "Screencast Key Status Tool"

    def modal(self, context, event):
        context.area.tag_redraw()

        # keys that shouldn't show up in the 3d-view
        ignore_keys = ['LEFT_SHIFT', 'RIGHT_SHIFT', 'LEFT_ALT',
        'RIGHT_ALT', 'LEFT_CTRL', 'RIGHT_CTRL', 'TIMER', 'MOUSEMOVE',
        'MIDDLEMOUSE','LEFTMOUSE', 'RIGHTMOUSE', 'WHEELDOWNMOUSE',
        'WHEELUPMOUSE']

        if event.value == 'PRESS':
            # add key-press to display-list
            sc_keys = []
            
            if event.shift:
                sc_keys.append('Shift ')
        
            if event.alt:
                sc_keys.append('Alt ')
        
            if event.ctrl:
                sc_keys.append('Ctrl ')

            if event.type not in ignore_keys:
                sc_keys.append(event.type)
            
                self.key.insert(0, "+ ".join(map(str, sc_keys)))
                self.time.insert(0, time.time())

        if event.type == ('F7'):
            # stop script
            context.region.callback_remove(self._handle)
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            # start script
            context.manager.add_modal_handler(self)

            self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL')
            self.key = []
            self.time = []
      
            return {'RUNNING_MODAL'}

        else:
            # operator not invoked from within the 3d-view
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}


def register():
    bpy.types.register(ScreencastKeysStatus)


def unregister():
    bpy.types.unregister(ScreencastKeysStatus)


if __name__ == "__main__":
    register()

(GottfriedHofmann) #9

That’s great, thank you!


(Sunjay03) #10

Here is the error message I got:

Traceback (most recent call last):
File “Text”, line 11, in draw_callback_px
TypeError: BLF.size() takes exactly 3 arguments (2 given)

Clearly just another API change.

-Sunjay03


(Crouch) #11

Sunjay03: It looks like you’re using the old version from post 1. Try the one I posted on May 8th.


(Sunjay03) #12

It blocks my mouse rotation.


(Crouch) #13

Strange, I’m not having that problem (just tested it on 29294). I’m on Windows XP 32bit.

User Preferences Input:
Emulate 3 Button Mouse: OFF
Continuous Grab: ON
Select with: RIGHT
Emulate Numpad: OFF
Orbit Style: TRACKBALL
Zoom Style: DOLLY, VERTICAL

I’m rotating by pressing the Middle Mouse Button and moving the mouse. Would you mind sharing your settings and describing what exactly gets blocked?


(pildanovak) #14

Hello there very interesting script. However, from the video I guess it could be even better when next to the pressed key would be the name of what was triggered - usually the name of the operator.
That would be awesome :slight_smile:


(Sunjay03) #15

It works with the middle mouse button…but not alt+left click.

-Sunjay03


(Crouch) #16

pildanovak: nice idea, but might be hard to implement properly. Only way I can see right now is to check the keymap for the corresponding function. This might be easier once we get access to notifiers and listeners.

Sunjay03: strange, no problem here with alt+left-click. Did you enable Emulate 3 Button Mouse in the user preferences? It’s necessary for alt+left-click to work. (I believe in 2.4x it was enabled by default, while in 2.5x it’s disabled by default)


(Octopus4) #17

great , is there a way to run this on 2.49 ?


(Sunjay03) #18

I realized that it was my fault entirely. I hadn’t even enabled Alt+Click in my user preferences yet!

Sorry about that! (Still a great script)

-Sunjay03


(Lepes) #19

a really good script.

The only bug I found (that I tried to fix and I couldn’t :o) is if you keep pressed NumPad_4 (for example) you get a really long scrolling texts on screen and it slowdown Blender just a bit.

Cheers.


(calli) #20

Great Script. I wrote a version for Blender 2.45 (used on my DVD http://blenderbuch.de/DVD.php) but it was (also caused by some Blender bugs) not nearly as perfect as yours. But since then I did not had time to port it to Blender 2.5x, so yours is very welcome.

Now we only need audio-recording and Blender is the first(?) application with a complete video tutorial creation suite :wink:

Carsten