﻿<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=Dev%3AIT%2F2.5%2FPy%2FScripts%2FCookbook%2FCode_snippets%2FBlender_add-ons</id>
	<title>Dev:IT/2.5/Py/Scripts/Cookbook/Code snippets/Blender add-ons - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=Dev%3AIT%2F2.5%2FPy%2FScripts%2FCookbook%2FCode_snippets%2FBlender_add-ons"/>
	<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons&amp;action=history"/>
	<updated>2026-11-03T20:09:16Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons&amp;diff=105265&amp;oldid=prev</id>
		<title>Yamyam: 1版 をインポートしました</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons&amp;diff=105265&amp;oldid=prev"/>
		<updated>2018-06-28T19:43:41Z</updated>

		<summary type="html">&lt;p&gt;1版 をインポートしました&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ja&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← 古い版&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;2018年6月28日 (木) 19:43時点における版&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;ja&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(相違点なし)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Yamyam</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons&amp;diff=105264&amp;oldid=prev</id>
		<title>wiki&gt;ValterVB: /* Un semplice importer BVH */</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons&amp;diff=105264&amp;oldid=prev"/>
		<updated>2011-06-26T17:56:47Z</updated>

		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Un semplice importer BVH&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Page/Header|2.5x|Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Interface|Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Multi-File_packages|100}}&lt;br /&gt;
&lt;br /&gt;
=Blender add-ons=&lt;br /&gt;
Finora abbiamo preso in considerazione solo script indipendenti, eseguiti all&amp;#039;interno del {{Format/Literal|Text Editor}}. un utente finale è più conveniente se lo script è un Blender add-ons che può essere abilitato dalle {{Format/Literal|User Preferences}}. E&amp;#039; anche possibile caricare automaticamente uno script ogni volta che Blender viene avviato.&lt;br /&gt;
&lt;br /&gt;
Per trasformare uno script in un add-ons, devi scriverlo in un modo speciale. Ci deve essere una struttura &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt;all&amp;#039;inizio del file e le funzioni &amp;lt;code&amp;gt;register&amp;lt;/code&amp;gt; e &amp;lt;code&amp;gt;unregister&amp;lt;/code&amp;gt; devono essere definite alla fine. Inoltre lo script deve essere salvato nelle directory dove Blender normalmente cerca gli add-ons all&amp;#039;avvio. Queste includono le directory &amp;lt;code&amp;gt;addons&amp;lt;/code&amp;gt; e &amp;lt;code&amp;gt;addons-contrib&amp;lt;/code&amp;gt; che puoi trovare sotto la directory &amp;lt;code&amp;gt;2.57/scripts&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shapekey pinning==&lt;br /&gt;
Lo script può essere eseguito dal {{Format/Literal|Text Editor}} window as usual. come al solito, comunque può aanche essere letto come add-ons. Le informazioni sull&amp;#039;add-on sono specificate nel dizionario &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; all&amp;#039;inizio del file.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
bl_info = {&lt;br /&gt;
    &amp;#039;name&amp;#039;: &amp;#039;Shapekey pinning&amp;#039;,&lt;br /&gt;
    &amp;#039;author&amp;#039;: &amp;#039;Thomas Larsson&amp;#039;,&lt;br /&gt;
    &amp;#039;version&amp;#039;: (0, 1, 2),&lt;br /&gt;
    &amp;#039;blender&amp;#039;: (2, 5, 7),&lt;br /&gt;
    &amp;#039;api&amp;#039;: 35774,&lt;br /&gt;
    &amp;quot;location&amp;quot;: &amp;quot;View3D &amp;gt; UI panel &amp;gt; Shapekey pinning&amp;quot;,&lt;br /&gt;
    &amp;#039;description&amp;#039;: &amp;#039;Pin and key the shapekeys of a mesh&amp;#039;,&lt;br /&gt;
    &amp;#039;warning&amp;#039;: &amp;#039;&amp;#039;,&lt;br /&gt;
    &amp;#039;wiki_url&amp;#039;: &amp;#039;http://blenderartists.org/forum/showthread.php?193908&amp;#039;,&lt;br /&gt;
    &amp;#039;tracker_url&amp;#039;: &amp;#039;&amp;#039;,&lt;br /&gt;
    &amp;quot;support&amp;quot;: &amp;#039;COMMUNITY&amp;#039;,&lt;br /&gt;
    &amp;quot;category&amp;quot;: &amp;quot;3D View&amp;quot;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il significato di molte voci in questo dizionario sono evidenti&lt;br /&gt;
* &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: Nome dell&amp;#039;add-on.&lt;br /&gt;
* &amp;lt;code&amp;gt;author&amp;lt;/code&amp;gt;: Nome dell&amp;#039;autore.&lt;br /&gt;
* &amp;lt;code&amp;gt;versione&amp;lt;/code&amp;gt;: Versione dello script.&lt;br /&gt;
* &amp;lt;code&amp;gt;blender&amp;lt;/code&amp;gt;: Versione di Blender.&lt;br /&gt;
* &amp;lt;code&amp;gt;api&amp;lt;/code&amp;gt;: Revisione con cui lo script lavora.&lt;br /&gt;
* &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;: Dove trovare il pulsante.&lt;br /&gt;
* &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;: Una descrizione mostrata come tooltip e nella documentazione.&lt;br /&gt;
* &amp;lt;code&amp;gt;warning&amp;lt;/code&amp;gt;: Un avviso. Se non è lasciato vuoto, una piccola icona sarà mostrata nelle preference utente.&lt;br /&gt;
* &amp;lt;code&amp;gt; wiki_url&amp;lt;/code&amp;gt;: Link alla pagina dello script presente nella wiki. In realtà dovrebbe puntare al sito di Blender, ma qui puntiamo a un thread su blenderaertist.org.&lt;br /&gt;
* &amp;lt;code&amp;gt;tracker_url&amp;lt;/code&amp;gt;: Link al bug tracker dello script.&lt;br /&gt;
* &amp;lt;code&amp;gt;support&amp;lt;/code&amp;gt;: Ufficiale o comunità&lt;br /&gt;
* &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;: Categoria dello script, per es. {{Format/Literal|3D View}}, {{Format/Literal|Import-Export}}, {{Format/Literal|Add Mesh}}, o {{Format/Literal|Rigging}}. Corrisponde alle categorie nelle {{Format/Literal|User Preferences}}.&lt;br /&gt;
&lt;br /&gt;
Molte di queste voci possono essere semplicemente omesse, come vedremo negli esempi seguenti.&lt;br /&gt;
&lt;br /&gt;
La seconda richiesta di un add-ons è che devono essere definite le funzioni &amp;lt;code&amp;gt;register()&amp;lt;/code&amp;gt; e &amp;lt;code&amp;gt;unregister()&amp;lt;/code&amp;gt;che normalmente sono messe alla fine del file. &amp;lt;code&amp;gt;register()&amp;lt;/code&amp;gt; normalmente fa una chiamata a &amp;lt;code&amp;gt;bpy.utils.register_module(__name__)&amp;lt;/code&amp;gt;, che registra tutte le classi definite nel file. Può anche conternere inizializzazioni personalizzate. Questo script dichiara anche una proprietà RNA personalizzata. Come abbiamo visto nella sottosezione [[Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Properties#RNA_properties_versus_ID_properties|Proprietà RNA vs proprietà ID]], la dichiarazione è necessaria , perché la proprietà bool, se no, viene vista come intera.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def register():&lt;br /&gt;
    initialize()&lt;br /&gt;
    bpy.utils.register_module(__name__)&lt;br /&gt;
&lt;br /&gt;
def unregister():&lt;br /&gt;
    bpy.utils.unregister_module(__name__)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    register()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Annullare la registrazione è simile alla registrazione.  L&amp;#039;ultima linea permette di eseguire lo script in maniera indipendente all&amp;#039;interno del {{Format/Literal|Text Editor}}. Anche se l&amp;#039;utente finale non eseguirà mai lo script nell&amp;#039;editor, è utile avere questa possibilità mentre si fa il debugging.&lt;br /&gt;
&lt;br /&gt;
Copia il file nella directory dove Blender cerca gli add-ons. Riavvia Blender, apri le {{Format/Literal|User Preferences}} dal menù {{Menu|File|User Preferences}}e clicca sulla linguetta Add-ons. Il nostro script può essere trovato in fondo alla sezione 3D View.&lt;br /&gt;
[[File:Code_Snippets_UserPref.png|640px]]&lt;br /&gt;
Si riconosce i campi in &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; nel dizionario. Abilita lo script premendo il checkbox nell&amp;#039;angolo superiore destro. Se vuoi caricare automaticamente lo script, ogni volta che avvii Blender, premi {{Button|Save As Default}} nella parte inferiore sinistra della finestra.&lt;br /&gt;
&lt;br /&gt;
Dopo che l&amp;#039;Add-on è stato abilitato, appare nel panello dell&amp;#039;interfaccia.&lt;br /&gt;
[[File:Code_Snippets_Addon-enabled.png|640px]]&lt;br /&gt;
Lo script stesso  mostra le shapekeys dell&amp;#039;oggetto attivo nell&amp;#039;interfaccia. Il cubo di default non ha nessun shapekeys. Invece importiamo un personaggio MakeHuman che ha un sacco di espressioni facciali che sono implementate come shapekeys. [http://www.makehuman.org MakeHuman] è un&amp;#039;applicazione che permette di creare facilmente un personaggio. Un personaggio completamente texturizzato e riggato, che può essere esportato in Blender usando il formato MHX (MakeHuman eXchange). I files MHX possono essere importati in Blender con l&amp;#039;importer MHX, che è un add-on distribuito assieme a Blender.&lt;br /&gt;
&lt;br /&gt;
Quello che è importante per questo esempio, è che la mesh di MakeHuman ha un sacco di shapekeys. Se premi il pulsante Pin a destra del valore dello shapekey, la shapekey è &amp;#039;&amp;#039;pinned&amp;#039;&amp;#039;, per es. il suo valore è impostato a uno, mentre i valori di tutti gli altri shapekeys sono impostati a zero. Se il pulsante &amp;#039;&amp;#039;Autokey&amp;#039;&amp;#039; nella {{Format/Literal|timeline}}  è attivo, un  key  è impostato per il valore della shapekey. Inoltre se {{Format/Literal|Key all}} è selezionato sono impostate delle key per ogni shapekey nella mesh.&lt;br /&gt;
[[File:Code_Snippets_Shapepin.png|640px]]&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File shapekey_pin.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
bl_info = {&lt;br /&gt;
    &amp;#039;name&amp;#039;: &amp;#039;Shapekey pinning&amp;#039;,&lt;br /&gt;
    &amp;#039;author&amp;#039;: &amp;#039;Thomas Larsson&amp;#039;,&lt;br /&gt;
    &amp;#039;version&amp;#039;: &amp;#039;(0, 1, 2)&amp;#039;,&lt;br /&gt;
    &amp;#039;blender&amp;#039;: (2, 5, 7),&lt;br /&gt;
    &amp;quot;location&amp;quot;: &amp;quot;View3D &amp;gt; UI panel &amp;gt; Shapekey pinning&amp;quot;,&lt;br /&gt;
    &amp;#039;description&amp;#039;: &amp;#039;Pin and key the shapekeys of a mesh&amp;#039;,&lt;br /&gt;
    &amp;#039;warning&amp;#039;: &amp;#039;&amp;#039;,&lt;br /&gt;
    &amp;#039;wiki_url&amp;#039;: &amp;#039;http://blenderartists.org/forum/showthread.php?193908&amp;#039;,&lt;br /&gt;
    &amp;#039;tracker_url&amp;#039;: &amp;#039;&amp;#039;,&lt;br /&gt;
    &amp;quot;support&amp;quot;: &amp;#039;COMMUNITY&amp;#039;,&lt;br /&gt;
     &amp;quot;category&amp;quot;: &amp;quot;3D View&amp;quot;}&lt;br /&gt;
&lt;br /&gt;
import bpy&lt;br /&gt;
from bpy.props import *&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class VIEW3D_OT_ResetExpressionsButton(bpy.types.Operator):&lt;br /&gt;
#&lt;br /&gt;
class VIEW3D_OT_ResetExpressionsButton(bpy.types.Operator):&lt;br /&gt;
    bl_idname = &amp;quot;shapepin.reset_expressions&amp;quot;&lt;br /&gt;
    bl_label = &amp;quot;Reset expressions&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        keys = context.object.data.shape_keys&lt;br /&gt;
        if keys:&lt;br /&gt;
            for shape in keys.keys:&lt;br /&gt;
                shape.value = 0.0&lt;br /&gt;
        return{&amp;#039;FINISHED&amp;#039;}    &lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class VIEW3D_OT_PinExpressionButton(bpy.types.Operator):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class VIEW3D_OT_PinExpressionButton(bpy.types.Operator):&lt;br /&gt;
    bl_idname = &amp;quot;shapepin.pin_expression&amp;quot;&lt;br /&gt;
    bl_label = &amp;quot;Pin&amp;quot;&lt;br /&gt;
    expression = bpy.props.StringProperty()&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        skeys = context.object.data.shape_keys&lt;br /&gt;
        if skeys:&lt;br /&gt;
            frame = context.scene.frame_current&lt;br /&gt;
            for block in skeys.key_blocks:            &lt;br /&gt;
                oldvalue = block.value&lt;br /&gt;
                block.value = 1.0 if block.name == self.expression else 0.0&lt;br /&gt;
                if (context.tool_settings.use_keyframe_insert_auto and &lt;br /&gt;
                    (context.scene.key_all or &lt;br /&gt;
                    (block.value &amp;gt; 0.01) or &lt;br /&gt;
                    (abs(block.value-oldvalue) &amp;gt; 0.01))):&lt;br /&gt;
                    block.keyframe_insert(&amp;quot;value&amp;quot;, index=-1, frame=frame)&lt;br /&gt;
        return{&amp;#039;FINISHED&amp;#039;}    &lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class ExpressionsPanel(bpy.types.Panel):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class ExpressionsPanel(bpy.types.Panel):&lt;br /&gt;
    bl_label = &amp;quot;Pin shapekeys&amp;quot;&lt;br /&gt;
    bl_space_type = &amp;quot;VIEW_3D&amp;quot;&lt;br /&gt;
    bl_region_type = &amp;quot;UI&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    @classmethod&lt;br /&gt;
    def poll(cls, context):&lt;br /&gt;
        return context.object and (context.object.type == &amp;#039;MESH&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    def draw(self, context):&lt;br /&gt;
        layout = self.layout&lt;br /&gt;
        layout.operator(&amp;quot;shapepin.reset_expressions&amp;quot;)&lt;br /&gt;
        layout.prop(context.scene, &amp;quot;key_all&amp;quot;)&lt;br /&gt;
        skeys = context.object.data.shape_keys&lt;br /&gt;
        if skeys:&lt;br /&gt;
            for block in skeys.key_blocks:            &lt;br /&gt;
                row = layout.split(0.75)&lt;br /&gt;
                row.prop(block, &amp;#039;value&amp;#039;, text=block.name)&lt;br /&gt;
                row.operator(&amp;quot;shapepin.pin_expression&amp;quot;, &lt;br /&gt;
                    text=&amp;quot;Pin&amp;quot;).expression = block.name&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    initialize and register&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def initialize():&lt;br /&gt;
    bpy.types.Scene.key_all = BoolProperty(&lt;br /&gt;
        name=&amp;quot;Key all&amp;quot;,&lt;br /&gt;
        description=&amp;quot;Set keys for all shapes&amp;quot;,&lt;br /&gt;
        default=False)&lt;br /&gt;
&lt;br /&gt;
def register():&lt;br /&gt;
    initialize()&lt;br /&gt;
    bpy.utils.register_module(__name__)&lt;br /&gt;
&lt;br /&gt;
def unregister():&lt;br /&gt;
    bpy.utils.unregister_module(__name__)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    register()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Un semplice importer BVH==&lt;br /&gt;
Il formato BVH è comunemente usato per trasferire le animazioni dei personaggi, per es. i dati di mocap. Questo programma è un semplice importer BVHThis program is a simple BVH importer, che costruisce uno skeleton con le azioni descritte nel file BVH. E&amp;#039; implementato come add-on con un dizionario &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; all&amp;#039;inizio del file e il codice per la registrazione alla fine.&lt;br /&gt;
&lt;br /&gt;
Una volta che il sottostante script è stato eseguito, o attivato come add-on, il semplice BVH importer può essere richiamato dal pannello dell&amp;#039;interfaccia utente ({{Shortcut|Ctrl|N}}). Ci sono 2 opzioni: una scelta booleana per ruotare la mesh di 90 gradi (per far puntare l&amp;#039;asse Z in alto) a un fattore di scala.&lt;br /&gt;
&lt;br /&gt;
Questo programma illustra anche come richiamare il file selector premendo un pulsante nel pannello. La classe del pulsante Load BVH eredita sia dalla classe base &amp;lt;code&amp;gt;bpy.types.Operator&amp;lt;/code&amp;gt; che da &amp;lt;code&amp;gt;ImportHelper&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class OBJECT_OT_LoadBvhButton(bpy.types.Operator, ImportHelper):&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La classe &amp;lt;code&amp;gt;ImportHelper&amp;lt;/code&amp;gt; (probabilmente non documentata) definisce alcuni attributi che sono usati per filtrare i file visibili nel file selector.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
filename_ext = &amp;quot;.bvh&amp;quot;&lt;br /&gt;
filter_glob = bpy.props.StringProperty(default=&amp;quot;*.bvh&amp;quot;, options={&amp;#039;HIDDEN&amp;#039;})&lt;br /&gt;
filepath = bpy.props.StringProperty(name=&amp;quot;File Path&amp;quot;,&lt;br /&gt;
    maxlen=1024, default=&amp;quot;&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
C&amp;#039;è un&amp;#039;analoga classe &amp;lt;code&amp;gt;ExportHelper&amp;lt;/code&amp;gt; che limita le scelte disponibili in un export file selector.&lt;br /&gt;
[[File:Code_Snippets_Bvh-load.png|640px]]&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File simple_bvh_import.py&lt;br /&gt;
# Simple bvh importer&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
bl_info = {&lt;br /&gt;
    &amp;#039;name&amp;#039;: &amp;#039;Simple BVH importer (.bvh)&amp;#039;,&lt;br /&gt;
    &amp;#039;author&amp;#039;: &amp;#039;Thomas Larsson&amp;#039;,&lt;br /&gt;
    &amp;#039;version&amp;#039;: (1, 0, 0),&lt;br /&gt;
    &amp;#039;blender&amp;#039;: (2, 5, 7),&lt;br /&gt;
    &amp;#039;api&amp;#039;: 34786,&lt;br /&gt;
    &amp;#039;location&amp;#039;: &amp;quot;File &amp;gt; Import&amp;quot;,&lt;br /&gt;
    &amp;#039;description&amp;#039;: &amp;#039;Simple import of Biovision bvh&amp;#039;,&lt;br /&gt;
    &amp;#039;category&amp;#039;: &amp;#039;Import-Export&amp;#039;}&lt;br /&gt;
&lt;br /&gt;
import bpy, os, math, mathutils, time&lt;br /&gt;
from mathutils import Vector, Matrix&lt;br /&gt;
from bpy_extras.io_utils import ImportHelper&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class CNode:&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class CNode:&lt;br /&gt;
    def __init__(self, words, parent):&lt;br /&gt;
        name = words[1]&lt;br /&gt;
        for word in words[2:]:&lt;br /&gt;
            name += &amp;#039; &amp;#039;+word&lt;br /&gt;
        &lt;br /&gt;
        self.name = name&lt;br /&gt;
        self.parent = parent&lt;br /&gt;
        self.children = []&lt;br /&gt;
        self.head = Vector((0,0,0))&lt;br /&gt;
        self.offset = Vector((0,0,0))&lt;br /&gt;
        if parent:&lt;br /&gt;
            parent.children.append(self)&lt;br /&gt;
        self.channels = []&lt;br /&gt;
        self.matrix = None&lt;br /&gt;
        self.inverse = None&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    def __repr__(self):&lt;br /&gt;
        return &amp;quot;CNode %s&amp;quot; % (self.name)&lt;br /&gt;
&lt;br /&gt;
    def display(self, pad):&lt;br /&gt;
        vec = self.offset&lt;br /&gt;
        if vec.length &amp;lt; Epsilon:&lt;br /&gt;
            c = &amp;#039;*&amp;#039;&lt;br /&gt;
        else:&lt;br /&gt;
            c = &amp;#039; &amp;#039;&lt;br /&gt;
        print(&amp;quot;%s%s%10s (%8.3f %8.3f %8.3f)&amp;quot; % &lt;br /&gt;
            (c, pad, self.name, vec[0], vec[1], vec[2]))&lt;br /&gt;
        for child in self.children:&lt;br /&gt;
            child.display(pad+&amp;quot;  &amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    def build(self, amt, orig, parent):&lt;br /&gt;
        self.head = orig + self.offset&lt;br /&gt;
        if not self.children:&lt;br /&gt;
            return self.head&lt;br /&gt;
        &lt;br /&gt;
        zero = (self.offset.length &amp;lt; Epsilon)&lt;br /&gt;
        eb = amt.edit_bones.new(self.name)        &lt;br /&gt;
        if parent:&lt;br /&gt;
            eb.parent = parent&lt;br /&gt;
        eb.head = self.head&lt;br /&gt;
        tails = Vector((0,0,0))&lt;br /&gt;
        for child in self.children:&lt;br /&gt;
            tails += child.build(amt, self.head, eb)&lt;br /&gt;
        n = len(self.children)&lt;br /&gt;
        eb.tail = tails/n&lt;br /&gt;
        (trans,quat,scale) = eb.matrix.decompose()&lt;br /&gt;
        self.matrix = quat.to_matrix()&lt;br /&gt;
        self.inverse = self.matrix.copy()&lt;br /&gt;
        self.inverse.invert()&lt;br /&gt;
        if zero:&lt;br /&gt;
            return eb.tail&lt;br /&gt;
        else:        &lt;br /&gt;
            return eb.head&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    readBvhFile(context, filepath, rot90, scale):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
Location = 1&lt;br /&gt;
Rotation = 2&lt;br /&gt;
Hierarchy = 1&lt;br /&gt;
Motion = 2&lt;br /&gt;
Frames = 3&lt;br /&gt;
&lt;br /&gt;
Deg2Rad = math.pi/180&lt;br /&gt;
Epsilon = 1e-5&lt;br /&gt;
&lt;br /&gt;
def readBvhFile(context, filepath, rot90, scale):&lt;br /&gt;
    fileName = os.path.realpath(os.path.expanduser(filepath))&lt;br /&gt;
    (shortName, ext) = os.path.splitext(fileName)&lt;br /&gt;
    if ext.lower() != &amp;quot;.bvh&amp;quot;:&lt;br /&gt;
        raise NameError(&amp;quot;Not a bvh file: &amp;quot; + fileName)&lt;br /&gt;
    print( &amp;quot;Loading BVH file &amp;quot;+ fileName )&lt;br /&gt;
&lt;br /&gt;
    time1 = time.clock()&lt;br /&gt;
    level = 0&lt;br /&gt;
    nErrors = 0&lt;br /&gt;
    scn = context.scene&lt;br /&gt;
            &lt;br /&gt;
    fp = open(fileName, &amp;quot;rU&amp;quot;)&lt;br /&gt;
    print( &amp;quot;Reading skeleton&amp;quot; )&lt;br /&gt;
    lineNo = 0&lt;br /&gt;
    for line in fp: &lt;br /&gt;
        words= line.split()&lt;br /&gt;
        lineNo += 1&lt;br /&gt;
        if len(words) == 0:&lt;br /&gt;
            continue&lt;br /&gt;
        key = words[0].upper()&lt;br /&gt;
        if key == &amp;#039;HIERARCHY&amp;#039;:&lt;br /&gt;
            status = Hierarchy&lt;br /&gt;
        elif key == &amp;#039;MOTION&amp;#039;:&lt;br /&gt;
            if level != 0:&lt;br /&gt;
                raise NameError(&amp;quot;Tokenizer out of kilter %d&amp;quot; % level)    &lt;br /&gt;
            amt = bpy.data.armatures.new(&amp;quot;BvhAmt&amp;quot;)&lt;br /&gt;
            rig = bpy.data.objects.new(&amp;quot;BvhRig&amp;quot;, amt)&lt;br /&gt;
            scn.objects.link(rig)&lt;br /&gt;
            scn.objects.active = rig&lt;br /&gt;
            bpy.ops.object.mode_set(mode=&amp;#039;EDIT&amp;#039;)&lt;br /&gt;
            root.build(amt, Vector((0,0,0)), None)&lt;br /&gt;
            #root.display(&amp;#039;&amp;#039;)&lt;br /&gt;
            bpy.ops.object.mode_set(mode=&amp;#039;OBJECT&amp;#039;)&lt;br /&gt;
            status = Motion&lt;br /&gt;
        elif status == Hierarchy:&lt;br /&gt;
            if key == &amp;#039;ROOT&amp;#039;:    &lt;br /&gt;
                node = CNode(words, None)&lt;br /&gt;
                root = node&lt;br /&gt;
                nodes = [root]&lt;br /&gt;
            elif key == &amp;#039;JOINT&amp;#039;:&lt;br /&gt;
                node = CNode(words, node)&lt;br /&gt;
                nodes.append(node)&lt;br /&gt;
            elif key == &amp;#039;OFFSET&amp;#039;:&lt;br /&gt;
                (x,y,z) = (float(words[1]), float(words[2]), float(words[3]))&lt;br /&gt;
                if rot90:                    &lt;br /&gt;
                    node.offset = scale*Vector((x,-z,y))&lt;br /&gt;
                else:&lt;br /&gt;
                    node.offset = scale*Vector((x,y,z))&lt;br /&gt;
            elif key == &amp;#039;END&amp;#039;:&lt;br /&gt;
                node = CNode(words, node)&lt;br /&gt;
            elif key == &amp;#039;CHANNELS&amp;#039;:&lt;br /&gt;
                oldmode = None&lt;br /&gt;
                for word in words[2:]:&lt;br /&gt;
                    if rot90:&lt;br /&gt;
                        (index, mode, sign) = channelZup(word)&lt;br /&gt;
                    else:&lt;br /&gt;
                        (index, mode, sign) = channelYup(word)&lt;br /&gt;
                    if mode != oldmode:&lt;br /&gt;
                        indices = []&lt;br /&gt;
                        node.channels.append((mode, indices))&lt;br /&gt;
                        oldmode = mode&lt;br /&gt;
                    indices.append((index, sign))&lt;br /&gt;
            elif key == &amp;#039;{&amp;#039;:&lt;br /&gt;
                level += 1&lt;br /&gt;
            elif key == &amp;#039;}&amp;#039;:&lt;br /&gt;
                level -= 1&lt;br /&gt;
                node = node.parent&lt;br /&gt;
            else:&lt;br /&gt;
                raise NameError(&amp;quot;Did not expect %s&amp;quot; % words[0])&lt;br /&gt;
        elif status == Motion:&lt;br /&gt;
            if key == &amp;#039;FRAMES:&amp;#039;:&lt;br /&gt;
                nFrames = int(words[1])&lt;br /&gt;
            elif key == &amp;#039;FRAME&amp;#039; and words[1].upper() == &amp;#039;TIME:&amp;#039;:&lt;br /&gt;
                frameTime = float(words[2])&lt;br /&gt;
                frameTime = 1&lt;br /&gt;
                status = Frames&lt;br /&gt;
                frame = 0&lt;br /&gt;
                t = 0&lt;br /&gt;
                bpy.ops.object.mode_set(mode=&amp;#039;POSE&amp;#039;)&lt;br /&gt;
                pbones = rig.pose.bones&lt;br /&gt;
                for pb in pbones:&lt;br /&gt;
                    pb.rotation_mode = &amp;#039;QUATERNION&amp;#039;&lt;br /&gt;
        elif status == Frames:&lt;br /&gt;
            addFrame(words, frame, nodes, pbones, scale)&lt;br /&gt;
            t += frameTime&lt;br /&gt;
            frame += 1&lt;br /&gt;
&lt;br /&gt;
    fp.close()&lt;br /&gt;
    time2 = time.clock()&lt;br /&gt;
    print(&amp;quot;Bvh file loaded in %.3f s&amp;quot; % (time2-time1))&lt;br /&gt;
    return rig&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    channelYup(word):&lt;br /&gt;
#    channelZup(word):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def channelYup(word):&lt;br /&gt;
    if word == &amp;#039;Xrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;X&amp;#039;, Rotation, +1)&lt;br /&gt;
    elif word == &amp;#039;Yrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;Y&amp;#039;, Rotation, +1)&lt;br /&gt;
    elif word == &amp;#039;Zrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;Z&amp;#039;, Rotation, +1)&lt;br /&gt;
    elif word == &amp;#039;Xposition&amp;#039;:&lt;br /&gt;
        return (0, Location, +1)&lt;br /&gt;
    elif word == &amp;#039;Yposition&amp;#039;:&lt;br /&gt;
        return (1, Location, +1)&lt;br /&gt;
    elif word == &amp;#039;Zposition&amp;#039;:&lt;br /&gt;
        return (2, Location, +1)&lt;br /&gt;
&lt;br /&gt;
def channelZup(word):&lt;br /&gt;
    if word == &amp;#039;Xrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;X&amp;#039;, Rotation, +1)&lt;br /&gt;
    elif word == &amp;#039;Yrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;Z&amp;#039;, Rotation, +1)&lt;br /&gt;
    elif word == &amp;#039;Zrotation&amp;#039;:&lt;br /&gt;
        return (&amp;#039;Y&amp;#039;, Rotation, -1)&lt;br /&gt;
    elif word == &amp;#039;Xposition&amp;#039;:&lt;br /&gt;
        return (0, Location, +1)&lt;br /&gt;
    elif word == &amp;#039;Yposition&amp;#039;:&lt;br /&gt;
        return (2, Location, +1)&lt;br /&gt;
    elif word == &amp;#039;Zposition&amp;#039;:&lt;br /&gt;
        return (1, Location, -1)&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    addFrame(words, frame, nodes, pbones, scale):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def addFrame(words, frame, nodes, pbones, scale):&lt;br /&gt;
    m = 0&lt;br /&gt;
    for node in nodes:&lt;br /&gt;
        name = node.name&lt;br /&gt;
        try:&lt;br /&gt;
            pb = pbones[name]&lt;br /&gt;
        except:&lt;br /&gt;
            pb = None&lt;br /&gt;
        if pb:&lt;br /&gt;
            for (mode, indices) in node.channels:&lt;br /&gt;
                if mode == Location:&lt;br /&gt;
                    vec = Vector((0,0,0))&lt;br /&gt;
                    for (index, sign) in indices:&lt;br /&gt;
                        vec[index] = sign*float(words[m])&lt;br /&gt;
                        m += 1&lt;br /&gt;
                    pb.location = (scale * vec  - node.head) * node.inverse&lt;br /&gt;
                    for n in range(3):&lt;br /&gt;
                        pb.keyframe_insert(&amp;#039;location&amp;#039;, index=n, frame=frame, group=name)&lt;br /&gt;
                elif mode == Rotation:&lt;br /&gt;
                    mats = []&lt;br /&gt;
                    for (axis, sign) in indices:&lt;br /&gt;
                        angle = sign*float(words[m])*Deg2Rad&lt;br /&gt;
                        mats.append(Matrix.Rotation(angle, 3, axis))&lt;br /&gt;
                        m += 1&lt;br /&gt;
                    mat = node.inverse * mats[0] * mats[1] * mats[2] * node.matrix&lt;br /&gt;
                    pb.rotation_quaternion = mat.to_quaternion()&lt;br /&gt;
                    for n in range(4):&lt;br /&gt;
                        pb.keyframe_insert(&amp;#039;rotation_quaternion&amp;#039;,&lt;br /&gt;
                                           index=n, frame=frame, group=name)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    initSceneProperties(scn):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def initSceneProperties(scn):&lt;br /&gt;
    bpy.types.Scene.MyBvhRot90 = bpy.props.BoolProperty(&lt;br /&gt;
        name=&amp;quot;Rotate 90 degrees&amp;quot;, &lt;br /&gt;
        description=&amp;quot;Rotate the armature to make Z point up&amp;quot;)&lt;br /&gt;
    scn[&amp;#039;MyBvhRot90&amp;#039;] = True&lt;br /&gt;
&lt;br /&gt;
    bpy.types.Scene.MyBvhScale = bpy.props.FloatProperty(&lt;br /&gt;
        name=&amp;quot;Scale&amp;quot;, &lt;br /&gt;
        default = 1.0,&lt;br /&gt;
        min = 0.01,&lt;br /&gt;
        max = 100)&lt;br /&gt;
    scn[&amp;#039;MyBvhScale&amp;#039;] = 1.0&lt;br /&gt;
&lt;br /&gt;
initSceneProperties(bpy.context.scene)&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class BvhImportPanel(bpy.types.Panel):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class BvhImportPanel(bpy.types.Panel):&lt;br /&gt;
    bl_label = &amp;quot;BVH import&amp;quot;&lt;br /&gt;
    bl_space_type = &amp;quot;VIEW_3D&amp;quot;&lt;br /&gt;
    bl_region_type = &amp;quot;UI&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def draw(self, context):&lt;br /&gt;
        self.layout.prop(context.scene, &amp;quot;MyBvhRot90&amp;quot;)&lt;br /&gt;
        self.layout.prop(context.scene, &amp;quot;MyBvhScale&amp;quot;)&lt;br /&gt;
        self.layout.operator(&amp;quot;simple_bvh.load&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    class OBJECT_OT_LoadBvhButton(bpy.types.Operator, ImportHelper):&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class OBJECT_OT_LoadBvhButton(bpy.types.Operator, ImportHelper):&lt;br /&gt;
    bl_idname = &amp;quot;simple_bvh.load&amp;quot;&lt;br /&gt;
    bl_label = &amp;quot;Load BVH file (.bvh)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # From ImportHelper. Filter filenames.&lt;br /&gt;
    filename_ext = &amp;quot;.bvh&amp;quot;&lt;br /&gt;
    filter_glob = bpy.props.StringProperty(default=&amp;quot;*.bvh&amp;quot;, options={&amp;#039;HIDDEN&amp;#039;})&lt;br /&gt;
&lt;br /&gt;
    filepath = bpy.props.StringProperty(name=&amp;quot;File Path&amp;quot;, &lt;br /&gt;
        maxlen=1024, default=&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        import bpy, os&lt;br /&gt;
        readBvhFile(context, self.properties.filepath, &lt;br /&gt;
            context.scene.MyBvhRot90, context.scene.MyBvhScale)&lt;br /&gt;
        return{&amp;#039;FINISHED&amp;#039;}    &lt;br /&gt;
&lt;br /&gt;
    def invoke(self, context, event):&lt;br /&gt;
        context.window_manager.fileselect_add(self)&lt;br /&gt;
        return {&amp;#039;RUNNING_MODAL&amp;#039;}    &lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    Registration&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def menu_func(self, context):&lt;br /&gt;
    self.layout.operator(&amp;quot;simple_bvh.load&amp;quot;, text=&amp;quot;Simple BVH (.bvh)...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def register():&lt;br /&gt;
    bpy.utils.register_module(__name__)&lt;br /&gt;
    bpy.types.INFO_MT_file_import.append(menu_func)&lt;br /&gt;
&lt;br /&gt;
def unregister():&lt;br /&gt;
    bpy.utils.unregister_module(__name__)&lt;br /&gt;
    bpy.types.INFO_MT_file_import.remove(menu_func)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    try:&lt;br /&gt;
        unregister()&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
    register()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Page/Footer|Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Interface|Dev:IT/2.5/Py/Scripts/Cookbook/Code_snippets/Multi-File_packages}}&lt;/div&gt;</summary>
		<author><name>wiki&gt;ValterVB</name></author>
		
	</entry>
</feed>