1
$\begingroup$

My goal is to simplify and create my own version of screencast key addon and this is my baby-stepping. What I'm doing here is to display a key on the screen that user pressed. However, the module msvcrt causes Blender crashing.

Some people uses bge or keyboard modules for detecting pressed keys but somewhat reason I have no modules in my Python 3. So I decided using msvcrt instead which is already exists on the module list.

I searched my problem on Google but sadly couldn't get an accepted solutions.

Any ideas?

This is the code:

bl_info = {
    "name" : "KeyPad",
    "author" : "anon",
    "description" : "",
    "blender" : (2, 80, 0),
    "version" : (0, 0, 1),
    "location" : "",
    "warning" : "",
    "category" : "Generic"
}

import bpy, blf, msvcrt

class Ksys:
    defaults = {
        "id": 0,
        "handler": None,
        "count": 3,
        "color": [255, 255, 255],
        "size": [50, 72],
        "position": {
            "left": [2, 80, 0],
            "center": [],
            "right": []
        }
    }
    def __init__(self):
        while True:
            if msvcrt.kbhit():
                key = msvcrt.getch()
                print("Key Pressing detected!:", key)
             
                Ksys.defaults["handler"] = bpy.types.SpaceView3D.draw_handler_add(self.draw(key), (None, None), 'WINDOW', 'POST_PIXEL')
                print("Key Assigning detected!")
                
                print("Waiting for 3 seconds then remove the handler on the window")
                bpy.app.timers.register(self.remove(Ksys.defaults["handler"]), Ksys.defaults["count"])

    def draw(key):
        blf.size(Ksys.defaults["id"], Ksys.defaults["size"][0], Ksys.defaults["size"][1])
        blf.color(Ksys.defaults["id"], Ksys.defaults["color"][0], Ksys.defaults["color"][1], Ksys.defaults["color"][2])
        blf.draw(Ksys.defaults["id"], key)

    def remove(key):
        bpy.types.SpaceView3D.draw_handler_remove(key, 'WINDOW')

# test run before register
o = Ksys()

def register():
    pass  

def unregister():
    pass
$\endgroup$
8
  • $\begingroup$ are u using windows? $\endgroup$
    – Chris
    Nov 11, 2021 at 8:51
  • $\begingroup$ @Chris Yes. I'm using Windows. Windows 10. $\endgroup$ Nov 11, 2021 at 8:54
  • $\begingroup$ @Christ I have Mac also but msvcrt is the module that only avaliable on Windows (at least not one of default modules of Python I guess). So I'm currently using Windows. $\endgroup$ Nov 11, 2021 at 9:00
  • $\begingroup$ that's why i asked...i am using mac too and there is no such module ;) $\endgroup$
    – Chris
    Nov 11, 2021 at 9:03
  • 1
    $\begingroup$ msvcrt is part of the Microsoft C++ runtime library and it's very much not recommended to use it raw, mostly because the code is not portable. bge is a Blender module for the game engine, which was removed when the game engine was. This answer talks about doing kbd input with a modal operator. There are threads on how to do it with a separate blender thread but that's pretty hard to get right as Gorgious pointed out. $\endgroup$ Nov 11, 2021 at 15:26

1 Answer 1

2
$\begingroup$

There are two ways to go about this in Blender. The recommended portable way is to create a modal operator. Modal Operators is a good free tutorial and this answer gives a minimal implementation that I quote here.

class VIEW3D_OT_process_input(bpy.types.Operator):
    """Process input while Control key is pressed."""
    bl_idname = 'view3d.process_input'
    bl_label = 'Process Input'
    bl_options = {'REGISTER'}

def modal(self, context, event):
    if event.type == 'ESC':
        return {'FINISHED'}
    elif event.ctrl:
        pass # Input processing code.

    return {'PASS_THROUGH'}

def invoke(self, context, event):
    context.window_manager.modal_handler_add(self)
    return {'RUNNING_MODAL'}

There are two obvious limitations of using the keypress event

  1. Being modal means that everything else has to wait while the modal operator is running. Sometimes this is a good thing, often it is not.
  2. You only get to receive the key press events that the blender interface is willing to expose and the list is far from complete.

The second approach has the disadvantage of being much harder to implement properly and much harder to debug. It also requires writing a version to interface with each OS that the script will run on. See Threading Gotchas for some examples of problems using separate threads. It also doesn't resolve the second problem.

Unless you have a compelling need to dive into one of the harder parts of OS interface, I would strongly advise using the modal approach.

$\endgroup$
2
  • $\begingroup$ Sorry for late response and thank you for details. $\endgroup$ Nov 14, 2021 at 0:26
  • $\begingroup$ No problem on the late response. I'm just glad the answer helped you. $\endgroup$ Nov 14, 2021 at 0:39

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.