﻿<?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-06-03T00:23:15Z</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'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' 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'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'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'add-on sono specificate nel dizionario &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; all'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;
    'name': 'Shapekey pinning',&lt;br /&gt;
    'author': 'Thomas Larsson',&lt;br /&gt;
    'version': (0, 1, 2),&lt;br /&gt;
    'blender': (2, 5, 7),&lt;br /&gt;
    'api': 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;
    'description': 'Pin and key the shapekeys of a mesh',&lt;br /&gt;
    'warning': '',&lt;br /&gt;
    'wiki_url': 'http://blenderartists.org/forum/showthread.php?193908',&lt;br /&gt;
    'tracker_url': '',&lt;br /&gt;
    &amp;quot;support&amp;quot;: 'COMMUNITY',&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'add-on.&lt;br /&gt;
* &amp;lt;code&amp;gt;author&amp;lt;/code&amp;gt;: Nome dell'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'ultima linea permette di eseguire lo script in maniera indipendente all'interno del {{Format/Literal|Text Editor}}. Anche se l'utente finale non eseguirà mai lo script nell'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'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'Add-on è stato abilitato, appare nel panello dell'interfaccia.&lt;br /&gt;
[[File:Code_Snippets_Addon-enabled.png|640px]]&lt;br /&gt;
Lo script stesso  mostra le shapekeys dell'oggetto attivo nell'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'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'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 è ''pinned'', per es. il suo valore è impostato a uno, mentre i valori di tutti gli altri shapekeys sono impostati a zero. Se il pulsante ''Autokey'' 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;
    'name': 'Shapekey pinning',&lt;br /&gt;
    'author': 'Thomas Larsson',&lt;br /&gt;
    'version': '(0, 1, 2)',&lt;br /&gt;
    'blender': (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;
    'description': 'Pin and key the shapekeys of a mesh',&lt;br /&gt;
    'warning': '',&lt;br /&gt;
    'wiki_url': 'http://blenderartists.org/forum/showthread.php?193908',&lt;br /&gt;
    'tracker_url': '',&lt;br /&gt;
    &amp;quot;support&amp;quot;: 'COMMUNITY',&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{'FINISHED'}    &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{'FINISHED'}    &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 == 'MESH')&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, 'value', 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' implementato come add-on con un dizionario &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; all'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'interfaccia utente ({{Shortcut|Ctrl|N}}). Ci sono 2 opzioni: una scelta booleana per ruotare la mesh di 90 gradi (per far puntare l'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={'HIDDEN'})&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'è un'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;
    'name': 'Simple BVH importer (.bvh)',&lt;br /&gt;
    'author': 'Thomas Larsson',&lt;br /&gt;
    'version': (1, 0, 0),&lt;br /&gt;
    'blender': (2, 5, 7),&lt;br /&gt;
    'api': 34786,&lt;br /&gt;
    'location': &amp;quot;File &amp;gt; Import&amp;quot;,&lt;br /&gt;
    'description': 'Simple import of Biovision bvh',&lt;br /&gt;
    'category': 'Import-Export'}&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 += ' '+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 = '*'&lt;br /&gt;
        else:&lt;br /&gt;
            c = ' '&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 == 'HIERARCHY':&lt;br /&gt;
            status = Hierarchy&lt;br /&gt;
        elif key == 'MOTION':&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='EDIT')&lt;br /&gt;
            root.build(amt, Vector((0,0,0)), None)&lt;br /&gt;
            #root.display('')&lt;br /&gt;
            bpy.ops.object.mode_set(mode='OBJECT')&lt;br /&gt;
            status = Motion&lt;br /&gt;
        elif status == Hierarchy:&lt;br /&gt;
            if key == 'ROOT':    &lt;br /&gt;
                node = CNode(words, None)&lt;br /&gt;
                root = node&lt;br /&gt;
                nodes = [root]&lt;br /&gt;
            elif key == 'JOINT':&lt;br /&gt;
                node = CNode(words, node)&lt;br /&gt;
                nodes.append(node)&lt;br /&gt;
            elif key == 'OFFSET':&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 == 'END':&lt;br /&gt;
                node = CNode(words, node)&lt;br /&gt;
            elif key == 'CHANNELS':&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 == '{':&lt;br /&gt;
                level += 1&lt;br /&gt;
            elif key == '}':&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 == 'FRAMES:':&lt;br /&gt;
                nFrames = int(words[1])&lt;br /&gt;
            elif key == 'FRAME' and words[1].upper() == 'TIME:':&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='POSE')&lt;br /&gt;
                pbones = rig.pose.bones&lt;br /&gt;
                for pb in pbones:&lt;br /&gt;
                    pb.rotation_mode = 'QUATERNION'&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 == 'Xrotation':&lt;br /&gt;
        return ('X', Rotation, +1)&lt;br /&gt;
    elif word == 'Yrotation':&lt;br /&gt;
        return ('Y', Rotation, +1)&lt;br /&gt;
    elif word == 'Zrotation':&lt;br /&gt;
        return ('Z', Rotation, +1)&lt;br /&gt;
    elif word == 'Xposition':&lt;br /&gt;
        return (0, Location, +1)&lt;br /&gt;
    elif word == 'Yposition':&lt;br /&gt;
        return (1, Location, +1)&lt;br /&gt;
    elif word == 'Zposition':&lt;br /&gt;
        return (2, Location, +1)&lt;br /&gt;
&lt;br /&gt;
def channelZup(word):&lt;br /&gt;
    if word == 'Xrotation':&lt;br /&gt;
        return ('X', Rotation, +1)&lt;br /&gt;
    elif word == 'Yrotation':&lt;br /&gt;
        return ('Z', Rotation, +1)&lt;br /&gt;
    elif word == 'Zrotation':&lt;br /&gt;
        return ('Y', Rotation, -1)&lt;br /&gt;
    elif word == 'Xposition':&lt;br /&gt;
        return (0, Location, +1)&lt;br /&gt;
    elif word == 'Yposition':&lt;br /&gt;
        return (2, Location, +1)&lt;br /&gt;
    elif word == 'Zposition':&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('location', 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('rotation_quaternion',&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['MyBvhRot90'] = 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['MyBvhScale'] = 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={'HIDDEN'})&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{'FINISHED'}    &lt;br /&gt;
&lt;br /&gt;
    def invoke(self, context, event):&lt;br /&gt;
        context.window_manager.fileselect_add(self)&lt;br /&gt;
        return {'RUNNING_MODAL'}    &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>