[PYTHON] [Blender] Comment gérer les événements de souris et de clavier dans les scripts Blender

Si vous créez un plug-in Blender, vous souhaiterez gérer les événements à partir de la souris ou du clavier et fournir des fonctionnalités plus interactives. La fonction permettant de changer la taille d'un objet simplement en déplaçant la souris lorsque vous appuyez sur la touche S en mode Objet est juste un exemple de gestion d'un événement à partir de la souris, et la sensation de fonctionnement est bonne.

Donc cette fois, je vais vous montrer comment gérer les événements de souris et de clavier avec des scripts Blender, avec des exemples.

échantillon

Encore une fois, l'échantillon est montré en premier. Cet échantillon peut agrandir / réduire l'objet en fonction de la position de la souris. Nous avons traité les événements suivants afin que vous puissiez comprendre le modèle des événements d'entrée dans Blender.

Code source

mouse_keyboard_event_test.py


import bpy

bl_info = {
    "name" : "Mouse/Keyboard event test",
    "author" : "Nutti",
    "version" : (0,1),
    "blender" : (2, 7, 0),
    "location" : "UV > Mouse/Keyboard event test",
    "description" : "Mouse/Keyboard event test.",
    "warning" : "",
    "wiki_url" : "",
    "tracker_url" : "",
    "category" : "UV"
}

running = False     #Vrai si l'événement est en cours d'acquisition

class MouseKeyboardEventTest(bpy.types.Operator):
    """Mouse/Keyboard event test."""
    
    bl_idname = "uv.mouse_keyboard_event_test"
    bl_label = "Mouse/Keyboard event test"
    bl_description = "Mouse/Keyboard event test"
    bl_options = {'REGISTER', 'UNDO'}
    
    obj_scale = 1.0     #Grossissement de l'objet
    orig_x = 0.0        #Coordonnée X lorsque le bouton est enfoncé
    orig_scale = []     #Agrandissement de l'objet lorsque le bouton est enfoncé

    def modal(self, context, event):
        global running
    
        #Quitter si ne fonctionne pas
        if running is False:
            return {'PASS_THROUGH'}
        
        #Appliquer un agrandissement aux objets
        active_obj = bpy.context.active_object
        active_obj.scale[0] = self.orig_scale[0] * self.obj_scale
        active_obj.scale[1] = self.orig_scale[1] * self.obj_scale
        active_obj.scale[2] = self.orig_scale[2] * self.obj_scale
        
        #############################################
        #Souris/Traitement pour gérer les événements du clavier
        #############################################
        
        #Mouvement de la souris-Définissez le grossissement de l'objet en fonction de la coordonnée X de la souris
        if event.type == 'MOUSEMOVE':
            factor = 1.0 / 100.0
            self.obj_scale = 1.0 + (event.mouse_x - self.orig_x) * factor
            return {'RUNNING_MODAL'}
        #Lorsque vous appuyez sur la touche espace-Renvoie l'agrandissement lorsque le bouton est enfoncé
        elif event.type == 'SPACE':
            if event.value == 'PRESS':
                self.orig_x = event.mouse_x
                return {'RUNNING_MODAL'}
        #Lorsque vous appuyez sur le clic droit-Confirmez le taux d'agrandissement modifié et terminez l'opération
        if event.type == 'RIGHTMOUSE':
            if event.value == 'PRESS':
                running = False
                return {'FINISHED'}
        
        return {'RUNNING_MODAL'}
    
    def invoke(self, context, event):
        global running
        
        if context.area.type == 'VIEW_3D':
            #Acceptez chaque événement si le bouton est enfoncé alors qu'il n'est pas en cours d'exécution
            if running is False:
                running = True
                #Réglage de l'état initial
                self.obj_scale = 1.0
                self.orig_x = event.mouse_x
                active_obj = bpy.context.active_object
                self.orig_scale = [
                    active_obj.scale[0],
                    active_obj.scale[1],
                    active_obj.scale[2]
                ]
                #paramètres du gestionnaire modal
                context.window_manager.modal_handler_add(self)
                return {'RUNNING_MODAL'}
        return {'CANCELLED'}
        
# 'N'Placez un bouton dans le menu qui apparaît sur le côté droit de VIEW 3D lorsque vous appuyez sur une touche
class OBJECT_PT_MKET(bpy.types.Panel):
    bl_label = "Mouse/Keyboard Event Test"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    def draw(self, context):
        sc = context.scene
        layout = self.layout
        #Placement des boutons
        layout.operator(MouseKeyboardEventTest.bl_idname, text="Start", icon="PLAY")


def register():
    bpy.utils.register_module(__name__)


def unregister():
    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()

Comment utiliser

Suivez les étapes ci-dessous pour installer le script. Blender Wiki

Si vous cliquez sur le bouton «Démarrer» dans «Test d'événement souris / clavier» du menu affiché sur le côté droit lorsque vous appuyez sur la touche «N» dans View 3D, les opérations suivantes seront acceptées.

opération Comportement sur les objets
Mouvement de la souris Déplacez la souris vers la droite de l'écran à partir de l'endroit où vous avez cliqué sur le bouton pour agrandir l'objet sélectionné et déplacez-la vers la gauche de l'écran pour effectuer un zoom arrière.
Touche espace Restaure la taille de l'objet lorsque le bouton a été cliqué.
clic-droit Confirmez la taille de l'objet modifié et terminez l'opération.

Exemple d'explication

L'explication de base du script Blender est présentée dans l'article suivant, nous nous concentrerons donc ici sur l'explication des éléments nouvellement ajoutés. [\ Blender ] Comment créer un plug-in Blender

Enregistrement du bouton

Ajoutez un bouton au menu de droite qui apparaît lorsque vous appuyez sur la touche «N» dans View 3D. L'enregistrement des boutons dépasse le cadre de cet article, alors pensez-y comme ceci pour le moment.

# 'N'Placez un bouton dans le menu qui apparaît sur le côté droit de VIEW 3D lorsque vous appuyez sur une touche
class OBJECT_PT_MKET(bpy.types.Panel):
    bl_label = "Mouse/Keyboard Event Test"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    def draw(self, context):
        #Placement des boutons
        # ...

invoke méthode

** La méthode qui est appelée lorsque la classe est appelée **. Dans cet exemple, il est appelé lorsque l'utilisateur clique sur le bouton.

    def invoke(self, context, event):
        global running
        
        if context.area.type == 'VIEW_3D':
            #Acceptez chaque événement si le bouton est enfoncé alors qu'il n'est pas en cours d'exécution
            if running is False:
                running = True

                #Réglage de l'état initial
                # ....

                #paramètres du gestionnaire modal
                context.window_manager.modal_handler_add(self)
                return {'RUNNING_MODAL'}
        return {'CANCELLED'}

Un gestionnaire (un objet avec une méthode modale) est spécifié dans la fonction context.window_manager.modal_handler_add pour accepter les événements de souris après avoir cliqué sur le bouton. Ici, spécifiez self car la classe a à la fois les méthodes ʻinvoke et modal` en même temps. En outre, divers paramètres d'état initial sont également définis.

Si vous définissez un gestionnaire ici, la méthode modale continuera à être appelée après **, nous avons donc préparé une variable running pour éliminer les opérations sur l'objet même si un événement se produit à l'arrêt.

méthode modale

Si vous enregistrez un gestionnaire avec la fonction context.window_manager.modal_handler_add dans la méthode ʻinvoke`, il sera appelé ** lorsqu'un événement se produit à partir de la souris ou du clavier **.

    def modal(self, context, event):
        global running

        #Quitter si ne fonctionne pas
        if running is False:
            return {'PASS_THROUGH'}

        # ....
        
        #Mouvement de la souris-Définissez le grossissement de l'objet en fonction de la coordonnée X de la souris
        if event.type == 'MOUSEMOVE':
            factor = 1.0 / 100.0
            self.obj_scale = 1.0 + (event.mouse_x - self.orig_x) * factor
            return {'RUNNING_MODAL'}
        #Lorsque vous appuyez sur la touche espace-Renvoie l'agrandissement lorsque le bouton est enfoncé
        elif event.type == 'SPACE':
            if event.value == 'PRESS':
                self.orig_x = event.mouse_x
                return {'RUNNING_MODAL'}
        #Lorsque vous appuyez sur le clic droit-Confirmez le taux d'agrandissement modifié et terminez l'opération
        if event.type == 'RIGHTMOUSE':
            if event.value == 'PRESS':
                running = False
                return {'FINISHED'}
        
        return {'RUNNING_MODAL'}

La méthode modal gère chaque événement comme suit.

un événement En traitement
Mouvement de la souris Obtient la position actuelle et calcule la différence latérale entre la position actuelle et la position initiale pour définir l'agrandissement de l'objet.
ensuite,{'RUNNING_MODAL'}Est retourné et le traitement se poursuit.
clic-droit {'FINISHED'}Renvoie et termine le processus.
Touche espace Modifiez le taux d'agrandissement de l'objet à la valeur initiale.
ensuite,{'RUNNING_MODAL'}Est retourné et le traitement se poursuit.
Autre {'RUNNING_MODAL'}Est retourné et le traitement se poursuit.

À la fin

Je vous ai montré comment gérer les événements de la souris et du clavier dans les scripts Blender. En connaissant les événements du clavier et de la souris, je pense que ** plus de choses peuvent être réalisées avec les scripts **, alors pourquoi ne pas essayer de l'utiliser?

Informations de référence

Recommended Posts

[Blender] Comment gérer les événements de souris et de clavier dans les scripts Blender
Comment gérer une session dans SQLAlchemy
[Blender] Comment rendre les scripts Blender multilingues
Comment exécuter des commandes et des scripts shell externes en python
Comment gérer le japonais avec Python
Comment faire des événements envoyés par le serveur dans Django
Comment utiliser is et == en Python
Comment écrire le bon shebang dans les scripts Perl, Python et Ruby
Comment générer une séquence en Python et C ++
Nettoyage des données Comment gérer les valeurs manquantes et aberrantes
Comment gérer le type datetime dans sqlite3 de python
Comment tracer l'autocorrélation et l'autocorrélation partielle avec Python
Comment connaître le répertoire actuel en Python dans Blender
Comment définir Decorator et Decomaker avec une seule fonction
Comment faire un clic droit en utilisant la saisie au clavier dans RPA?
[Python] Comment trier un dict dans une liste et une instance dans une liste
Comment utiliser Decorator dans Django et comment le créer
Comment gérer JSON en Ruby, Python, JavaScript, PHP
Comment obtenir des histogrammes RVB et HSV avec OpenCV
[Python] Comment gérer inf et NaN à une moyenne numpy, écart type, maximum / minimum
Un script qui compte jusqu'à 5 secondes et s'arrête dans le Python de Blender
Les étrangers parlent: Comment nommer les classes et les méthodes en anglais
Comment utiliser pyenv et pyenv-virtualenv à votre manière
[Introduction à l'application Udemy Python3 +] 36. Utilisation de In et Not
Comment créer et utiliser des bibliothèques statiques / dynamiques en langage C
Comparaison de l'utilisation des fonctions d'ordre supérieur dans Python 2 et 3
Comment obtenir toutes les clés et valeurs du dictionnaire
[TF] Comment charger / enregistrer le modèle et le paramètre dans Keras
Comment développer en Python
Comment gérer les trames de données
Comment créer une trame de données et jouer avec des éléments avec des pandas
Comment se connecter à AtCoder avec Python et soumettre automatiquement
Comment copier et coller le contenu de la ligne de commande avec bash sous Linux ou Mac sans souris
Comment définir la résolution de sortie pour chaque image clé dans Blender
Comment mettre à jour automatiquement la description de l'App Store dans Google Spreadsheets et Fastlane
Comment installer OpenCV sur Cloud9 et l'exécuter en Python
Comment comparer des listes et récupérer des éléments communs dans une liste
Repeated @ app.callback dans Dash Comment écrire correctement l'entrée et l'état
Comment donner et signifier l'option des contraintes dans scipy.optimize.minimize
Comment utiliser les fonctions dans des fichiers séparés version Perl et version Python
<Pandas> Comment gérer les données de séries chronologiques dans le tableau croisé dynamique
[ROS2] Comment décrire le remappage et les paramètres au lancement au format python
Comment afficher les octets de la même manière en Java et Python
[Python] Comment faire PCA avec Python
Comment utiliser les classes dans Theano
Comment écrire sobrement avec des pandas
Comment collecter des images en Python
Comment mettre à jour Spyder dans Anaconda
Comment refléter CSS dans Django
Comment installer et configurer Blackbird
Comment utiliser .bash_profile et .bashrc
Comment tuer des processus en vrac
Comment installer et utiliser Graphviz
Comment utiliser Mysql avec python
Comment envelopper C en Python
Comment utiliser ChemSpider en Python
[Blender] Comment créer un plug-in Blender
Comment utiliser PubChem avec Python
Comment exécuter du code TensorFlow 1.0 en 2.0