﻿<?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%3APy%2FScripts%2FCookbook%2FCode_snippets%2FMulti-File_packages</id>
	<title>Dev:Py/Scripts/Cookbook/Code snippets/Multi-File packages - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=Dev%3APy%2FScripts%2FCookbook%2FCode_snippets%2FMulti-File_packages"/>
	<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:Py/Scripts/Cookbook/Code_snippets/Multi-File_packages&amp;action=history"/>
	<updated>2026-06-03T15:25:04Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=Dev:Py/Scripts/Cookbook/Code_snippets/Multi-File_packages&amp;diff=104797&amp;oldid=prev</id>
		<title>Yamyam: 1版 をインポートしました</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:Py/Scripts/Cookbook/Code_snippets/Multi-File_packages&amp;diff=104797&amp;oldid=prev"/>
		<updated>2018-06-28T19:43:25Z</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:Py/Scripts/Cookbook/Code_snippets/Multi-File_packages&amp;diff=104796&amp;oldid=prev</id>
		<title>wiki&gt;Lijenstina: /* __init__.py */</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:Py/Scripts/Cookbook/Code_snippets/Multi-File_packages&amp;diff=104796&amp;oldid=prev"/>
		<updated>2018-03-19T17:14:29Z</updated>

		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;__init__.py&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:2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons|Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Simulations}}&lt;br /&gt;
&lt;br /&gt;
=Multi-file packages=&lt;br /&gt;
Packages are a way of structuring Python's module namespace by using &amp;quot;dotted module names&amp;quot;. For example, the module name &amp;lt;code&amp;gt;A.B&amp;lt;/code&amp;gt; designates a submodule named &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; in a package named &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;. Just like the use of modules saves the authors of different modules from having to worry about each other's global variable names, the use of dotted module names saves the authors of multi-module packages from having to worry about each other's module names. For more information about Python packages, please refer to the Python documentation at [http://docs.python.org/tutorial/modules.html#packages Packages]&lt;br /&gt;
&lt;br /&gt;
Every package must contain file called &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt;. This file is required to make Python treat the directory as containing a package; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; can just be an empty file, but it can also execute initialization code for the package. In Blender, &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; often contains the user interface and the add-ons information, whereas the real work is done in other files.&lt;br /&gt;
&lt;br /&gt;
Unlike the other scripts in this book, a multi-file package can not be executed from the text editor. It must be copied to a location which is included in Blender's search path, e.g. the &amp;lt;code&amp;gt;addons&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;addons-contrib&amp;lt;/code&amp;gt;, cf. section [[Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons|Blender add-ons]]. Fortunately, you don't have to restart Blender to reload the files after each modification. Hitting {{Shortcut|F8}} on the keyboard reloads all activated add-ons into Blender.&lt;br /&gt;
&lt;br /&gt;
==A simple example==&lt;br /&gt;
This package is spread on four files. Three of these create meshes; a cube, a cylinder, and a sphere, respectively. These files are stand-alone scripts which can be executed in the text editor window for debug purposes. The condition &amp;lt;code&amp;gt;(__name__ == &amp;quot;__main__&amp;quot;)&amp;lt;/code&amp;gt; is true when the file is run in stand-alone mode.&lt;br /&gt;
&lt;br /&gt;
===mycube.py===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File mycube.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
import bpy&lt;br /&gt;
&lt;br /&gt;
def makeMesh(z):&lt;br /&gt;
    bpy.ops.mesh.primitive_cube_add(location=(0,0,z))&lt;br /&gt;
    return bpy.context.object&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    ob = makeMesh(1)&lt;br /&gt;
    print(ob, &amp;quot;created&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mycylinder.py===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File mycylinder.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
import bpy&lt;br /&gt;
&lt;br /&gt;
def makeMesh(z):&lt;br /&gt;
    bpy.ops.mesh.primitive_cylinder_add(location=(0,0,z))&lt;br /&gt;
    return bpy.context.object&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    ob = makeMesh(5)&lt;br /&gt;
    print(ob, &amp;quot;created&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===mysphere.py===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File mysphere.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
import bpy&lt;br /&gt;
&lt;br /&gt;
def makeMesh(z):&lt;br /&gt;
    bpy.ops.mesh.primitive_ico_sphere_add(location=(0,0,z))&lt;br /&gt;
    return bpy.context.object&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    ob = makeMesh(3)&lt;br /&gt;
    print(ob, &amp;quot;created&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===__init__.py===&lt;br /&gt;
The fourth file contains the &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; dictionary and registration needed for add-ons, and the user interface. It also contains the following piece of code to import the other files in the package.&lt;br /&gt;
&lt;br /&gt;
{{NiceTip|Note about imports|The examples here rely on using the '''imp''' python library, that should be phased out in the future. For the new alternative, please consult [[Dev:Py/Scripts/Cookbook/Python/Reload|this page]].}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# To support reload properly, try to access a package var, &lt;br /&gt;
# if it's there, reload everything&lt;br /&gt;
if &amp;quot;bpy&amp;quot; in locals():&lt;br /&gt;
    import imp&lt;br /&gt;
    imp.reload(mycube)&lt;br /&gt;
    imp.reload(mysphere)&lt;br /&gt;
    imp.reload(mycylinder)&lt;br /&gt;
    print(&amp;quot;Reloaded multifiles&amp;quot;)&lt;br /&gt;
else:&lt;br /&gt;
    from . import mycube, mysphere, mycylinder&lt;br /&gt;
    print(&amp;quot;Imported multifiles&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This code works as follows.&lt;br /&gt;
* If &amp;lt;code&amp;gt;__init__.py()&amp;lt;/code&amp;gt; is run for the first time, i.e. on starting Blender with the addon enabled in your default.blend, &amp;lt;code&amp;gt;&amp;quot;bpy&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;locals()&amp;lt;/code&amp;gt; is False. The other files in the package are imported, and Imported multifiles is printed in the terminal.&lt;br /&gt;
* If &amp;lt;code&amp;gt;__init__.py()&amp;lt;/code&amp;gt; is run for the first time after starting Blender with the addon disabled in your default.blend, and you click enable addon, &amp;lt;code&amp;gt;&amp;quot;bpy&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;locals()&amp;lt;/code&amp;gt; is False. The other files in the package are imported, and Imported multifiles is printed in the terminal.&lt;br /&gt;
* Once the add-on is enabled, anytime you press {{Shortcut|F8}} to reload add-ons, &amp;lt;code&amp;gt;&amp;quot;bpy&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;locals()&amp;lt;/code&amp;gt; is True. The other files in the package are reloaded, and Reloaded multifiles is printed in the terminal.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File __init__.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
#    Addon info&lt;br /&gt;
bl_info = {&lt;br /&gt;
    'name': 'Multifile',&lt;br /&gt;
    'author': 'Thomas Larsson',&lt;br /&gt;
    'location': 'View3D &amp;gt; UI panel &amp;gt; Add meshes',&lt;br /&gt;
    'category': '3D View'&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
# To support reload properly, try to access a package var, &lt;br /&gt;
# if it's there, reload everything&lt;br /&gt;
if &amp;quot;bpy&amp;quot; in locals():&lt;br /&gt;
    import imp&lt;br /&gt;
    imp.reload(mycube)&lt;br /&gt;
    imp.reload(mysphere)&lt;br /&gt;
    imp.reload(mycylinder)&lt;br /&gt;
    print(&amp;quot;Reloaded multifiles&amp;quot;)&lt;br /&gt;
else:&lt;br /&gt;
    from . import mycube, mysphere, mycylinder&lt;br /&gt;
    print(&amp;quot;Imported multifiles&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 AddMeshPanel(bpy.types.Panel):&lt;br /&gt;
#&lt;br /&gt;
class AddMeshPanel(bpy.types.Panel):&lt;br /&gt;
    bl_label = &amp;quot;Add meshes&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.operator(&amp;quot;multifile.add&amp;quot;, &lt;br /&gt;
            text=&amp;quot;Add cube&amp;quot;).mesh = &amp;quot;cube&amp;quot;&lt;br /&gt;
        self.layout.operator(&amp;quot;multifile.add&amp;quot;, &lt;br /&gt;
            text=&amp;quot;Add cylinder&amp;quot;).mesh = &amp;quot;cylinder&amp;quot;&lt;br /&gt;
        self.layout.operator(&amp;quot;multifile.add&amp;quot;, &lt;br /&gt;
            text=&amp;quot;Add sphere&amp;quot;).mesh = &amp;quot;sphere&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#   class OBJECT_OT_AddButton(bpy.types.Operator):&lt;br /&gt;
#&lt;br /&gt;
class OBJECT_OT_AddButton(bpy.types.Operator):&lt;br /&gt;
    bl_idname = &amp;quot;multifile.add&amp;quot;&lt;br /&gt;
    bl_label = &amp;quot;Add&amp;quot;&lt;br /&gt;
    mesh = bpy.props.StringProperty()&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        if self.mesh == &amp;quot;cube&amp;quot;:&lt;br /&gt;
            mycube.makeMesh(-8)&lt;br /&gt;
        elif self.mesh == &amp;quot;cylinder&amp;quot;:&lt;br /&gt;
            mycylinder.makeMesh(-5)&lt;br /&gt;
        elif self.mesh == &amp;quot;sphere&amp;quot;:&lt;br /&gt;
            mysphere.makeMesh(-2)&lt;br /&gt;
        return{'FINISHED'}    &lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    Registration&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
def register():&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;
==Simple obj importer and exporter==&lt;br /&gt;
The obj format is commonly used for exchanging mesh data between different applications. Originally invented for Wavefront Maya, it has become the industry standard. It is a simple ascii format which contain lines of the following form:&lt;br /&gt;
* v ''x y z''&amp;lt;br&amp;gt;Vertex coordinates are ''(x, y, z)''&lt;br /&gt;
* vt ''u v''&amp;lt;br&amp;gt;Texture vertex coordinates are ''(u, v)''&lt;br /&gt;
* f ''v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; ... v&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;'' &amp;lt;br&amp;gt; Face with ''n'' corners, at vertex ''v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, ... v&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;''. For meshes without UVs.&lt;br /&gt;
* f ''v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;/vt&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;/vt&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; ... v&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;/vt&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;''&amp;lt;br&amp;gt;Face with ''n'' corners. The corners are at vertex ''v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, ... v&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;'' in 3D space and at ''vt&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, vt&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;, ... vt&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;'' in texture space.&lt;br /&gt;
More constructs, e.g. for material settings and face groups, exist in full-fledged obj exporter and importers.&lt;br /&gt;
&lt;br /&gt;
There are two things to be aware of. First, most applications (to my knowledge, all except Blender) use a convention were the Y axis points up, whereas Blender uses the Z up convention. Second, Maya start counting vertices from 1, whereas Blender starts counting from 0. This means that the face corners are really located at ''v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;-1, v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;-1, ... v&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;-1'' in 3D space and at ''vt&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;-1, vt&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;-1, ... vt&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;-1'' in texture space.&lt;br /&gt;
&lt;br /&gt;
The simple obj exporter-importer is a Python package which consists of three files: two files that does the actual export/import work, and &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; which makes the directory into a package.&lt;br /&gt;
&lt;br /&gt;
===Simple obj exporter===&lt;br /&gt;
This script exports the selected mesh as an obj file.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File export_simple_obj.py&lt;br /&gt;
# Simple obj exporter which writes only verts, faces, and texture verts&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
import bpy, os&lt;br /&gt;
&lt;br /&gt;
def export_simple_obj(filepath, ob, rot90, scale):&lt;br /&gt;
    name = os.path.basename(filepath)&lt;br /&gt;
    realpath = os.path.realpath(os.path.expanduser(filepath))&lt;br /&gt;
    fp = open(realpath, 'w')    &lt;br /&gt;
    print('Exporting %s' % realpath)&lt;br /&gt;
&lt;br /&gt;
    if not ob or ob.type != 'MESH':&lt;br /&gt;
        raise NameError('Cannot export: active object %s is not a mesh.' % ob)&lt;br /&gt;
    me = ob.data&lt;br /&gt;
&lt;br /&gt;
    for v in me.vertices:&lt;br /&gt;
        x = scale*v.co&lt;br /&gt;
        if rot90:&lt;br /&gt;
            fp.write(&amp;quot;v %.5f %.5f %.5f\n&amp;quot; % (x[0], x[2], -x[1]))&lt;br /&gt;
        else:&lt;br /&gt;
            fp.write(&amp;quot;v %.5f %.5f %.5f\n&amp;quot; % (x[0], x[1], x[2]))&lt;br /&gt;
&lt;br /&gt;
    if len(me.uv_textures) &amp;gt; 0:&lt;br /&gt;
        uvtex = me.uv_textures[0]&lt;br /&gt;
        for f in me.faces:&lt;br /&gt;
            data = uvtex.data[f.index]&lt;br /&gt;
            fp.write(&amp;quot;vt %.5f %.5f\n&amp;quot; % (data.uv1[0], data.uv1[1]))&lt;br /&gt;
            fp.write(&amp;quot;vt %.5f %.5f\n&amp;quot; % (data.uv2[0], data.uv2[1]))&lt;br /&gt;
            fp.write(&amp;quot;vt %.5f %.5f\n&amp;quot; % (data.uv3[0], data.uv3[1]))&lt;br /&gt;
            if len(f.vertices) == 4:&lt;br /&gt;
                fp.write(&amp;quot;vt %.5f %.5f\n&amp;quot; % (data.uv4[0], data.uv4[1]))&lt;br /&gt;
&lt;br /&gt;
        vt = 1&lt;br /&gt;
        for f in me.faces:&lt;br /&gt;
            vs = f.vertices&lt;br /&gt;
            fp.write(&amp;quot;f %d/%d %d/%d %d/%d&amp;quot; % (vs[0]+1, vt, vs[1]+1, vt+1, vs[2]+1, vt+2))&lt;br /&gt;
            vt += 3&lt;br /&gt;
            if len(f.vertices) == 4:&lt;br /&gt;
                fp.write(&amp;quot; %d/%d\n&amp;quot; % (vs[3]+1, vt))&lt;br /&gt;
                vt += 1        &lt;br /&gt;
            else:&lt;br /&gt;
                fp.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        for f in me.faces:&lt;br /&gt;
            vs = f.vertices&lt;br /&gt;
            fp.write(&amp;quot;f %d %d %d&amp;quot; % (vs[0]+1, vs[1]+1, vs[2]+1))&lt;br /&gt;
            if len(f.vertices) == 4:&lt;br /&gt;
                fp.write(&amp;quot; %d\n&amp;quot; % (vs[3]+1))&lt;br /&gt;
            else:&lt;br /&gt;
                fp.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
    &lt;br /&gt;
    print('%s successfully exported' % realpath)&lt;br /&gt;
    fp.close()&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Simple obj import===&lt;br /&gt;
This script is the import companion of the previous one. It can of course also used to import obj files from other applications.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File import_simple_obj.py&lt;br /&gt;
# Simple obj importer which reads only verts, faces, and texture verts&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
import bpy, os&lt;br /&gt;
&lt;br /&gt;
def import_simple_obj(filepath, rot90, scale):&lt;br /&gt;
    name = os.path.basename(filepath)&lt;br /&gt;
    realpath = os.path.realpath(os.path.expanduser(filepath))&lt;br /&gt;
    fp = open(realpath, 'rU')    # Universal read&lt;br /&gt;
    print('Importing %s' % realpath)&lt;br /&gt;
&lt;br /&gt;
    verts = []&lt;br /&gt;
    faces = []&lt;br /&gt;
    texverts = []&lt;br /&gt;
    texfaces = []&lt;br /&gt;
&lt;br /&gt;
    for line in fp:&lt;br /&gt;
        words = line.split()&lt;br /&gt;
        if len(words) == 0:&lt;br /&gt;
            pass&lt;br /&gt;
        elif words[0] == 'v':&lt;br /&gt;
            (x,y,z) = (float(words[1]), float(words[2]), float(words[3]))&lt;br /&gt;
            if rot90:&lt;br /&gt;
                verts.append( (scale*x, -scale*z, scale*y) )&lt;br /&gt;
            else:&lt;br /&gt;
                verts.append( (scale*x, scale*y, scale*z) )&lt;br /&gt;
        elif words[0] == 'vt':&lt;br /&gt;
            texverts.append( (float(words[1]), float(words[2])) )&lt;br /&gt;
        elif words[0] == 'f':&lt;br /&gt;
            (f,tf) = parseFace(words)&lt;br /&gt;
            faces.append(f)&lt;br /&gt;
            if tf:&lt;br /&gt;
                texfaces.append(tf)&lt;br /&gt;
        else:&lt;br /&gt;
            pass&lt;br /&gt;
    print('%s successfully imported' % realpath)&lt;br /&gt;
    fp.close()&lt;br /&gt;
&lt;br /&gt;
    me = bpy.data.meshes.new(name)&lt;br /&gt;
    me.from_pydata(verts, [], faces)&lt;br /&gt;
    me.update()&lt;br /&gt;
&lt;br /&gt;
    if texverts:&lt;br /&gt;
        uvtex = me.uv_textures.new()&lt;br /&gt;
        uvtex.name = name&lt;br /&gt;
        data = uvtex.data&lt;br /&gt;
        for n in range(len(texfaces)):&lt;br /&gt;
            tf = texfaces[n]&lt;br /&gt;
            data[n].uv1 = texverts[tf[0]]&lt;br /&gt;
            data[n].uv2 = texverts[tf[1]]&lt;br /&gt;
            data[n].uv3 = texverts[tf[2]]&lt;br /&gt;
            if len(tf) == 4:&lt;br /&gt;
                data[n].uv4 = texverts[tf[3]]&lt;br /&gt;
&lt;br /&gt;
    scn = bpy.context.scene&lt;br /&gt;
    ob = bpy.data.objects.new(name, me)&lt;br /&gt;
    scn.objects.link(ob)&lt;br /&gt;
    scn.objects.active = ob&lt;br /&gt;
&lt;br /&gt;
    return&lt;br /&gt;
    &lt;br /&gt;
def parseFace(words):&lt;br /&gt;
    face = []&lt;br /&gt;
    texface = []&lt;br /&gt;
    for n in range(1, len(words)):&lt;br /&gt;
        li = words[n].split('/')&lt;br /&gt;
        face.append( int(li[0])-1 )&lt;br /&gt;
        try:&lt;br /&gt;
            texface.append( int(li[1])-1 )&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
    return (face, texface)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===__init__.py===&lt;br /&gt;
This file contains the user interface, i.e. the two classes that create menu items for the exporter and importer. The simple exporter is invoked from the {{Menu|File|Export}} menu. There are two options: a boolean choice to rotate the mesh 90 degrees (to convert between Y up and Z up), and a scale. The simple importer is invoked from the {{Menu|File|Import}} menu. There are two options: a boolean choice to rotate the mesh 90 degrees (to make Z up), and a scale.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; also contains the &amp;lt;code&amp;gt;bl_info&amp;lt;/code&amp;gt; dictionary which makes the package into a Blender add-on, the registration code, and the code to import/reload the two other files.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
# File __init__.py&lt;br /&gt;
#----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
#    Addon info&lt;br /&gt;
bl_info = {&lt;br /&gt;
    'name': 'Simple OBJ format',&lt;br /&gt;
    'author': 'Thomas Larsson',&lt;br /&gt;
    'location': 'File &amp;gt; Import-Export',&lt;br /&gt;
    'description': 'Simple Wavefront obj import/export. Does meshes and UV coordinates',&lt;br /&gt;
    'category': 'Import-Export'}&lt;br /&gt;
&lt;br /&gt;
# To support reload properly, try to access a package var, &lt;br /&gt;
# if it's there, reload everything&lt;br /&gt;
if &amp;quot;bpy&amp;quot; in locals():&lt;br /&gt;
    import imp&lt;br /&gt;
    if 'simple_obj_import' in locals():&lt;br /&gt;
        imp.reload(simple_obj_import)&lt;br /&gt;
    if 'simple_obj_export' in locals():&lt;br /&gt;
        imp.reload(simple_obj_export)&lt;br /&gt;
&lt;br /&gt;
import bpy&lt;br /&gt;
from bpy.props import *&lt;br /&gt;
from io_utils import ExportHelper, ImportHelper&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
#    Import menu&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class IMPORT_OT_simple_obj(bpy.types.Operator, ImportHelper):&lt;br /&gt;
    bl_idname = &amp;quot;io_import_scene.simple_obj&amp;quot;&lt;br /&gt;
    bl_description = 'Import from simple OBJ file format (.obj)'&lt;br /&gt;
    bl_label = &amp;quot;Import simple OBJ&amp;quot;&lt;br /&gt;
    bl_space_type = &amp;quot;PROPERTIES&amp;quot;&lt;br /&gt;
    bl_region_type = &amp;quot;WINDOW&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    filename_ext = &amp;quot;.obj&amp;quot;&lt;br /&gt;
    filter_glob = StringProperty(default=&amp;quot;*.obj;*.mtl&amp;quot;, options={'HIDDEN'})&lt;br /&gt;
&lt;br /&gt;
    filepath = bpy.props.StringProperty(&lt;br /&gt;
        name=&amp;quot;File Path&amp;quot;, &lt;br /&gt;
        description=&amp;quot;File path used for importing the simple OBJ file&amp;quot;, &lt;br /&gt;
        maxlen= 1024, default= &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    rot90 = bpy.props.BoolProperty(&lt;br /&gt;
        name = &amp;quot;Rotate 90 degrees&amp;quot;,&lt;br /&gt;
        description=&amp;quot;Rotate mesh to Z up&amp;quot;,&lt;br /&gt;
        default = True)&lt;br /&gt;
&lt;br /&gt;
    scale = bpy.props.FloatProperty(&lt;br /&gt;
        name = &amp;quot;Scale&amp;quot;, &lt;br /&gt;
        description=&amp;quot;Scale mesh&amp;quot;, &lt;br /&gt;
        default = 0.1, min = 0.001, max = 1000.0)&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        from . import simple_obj_import&lt;br /&gt;
        print(&amp;quot;Load&amp;quot;, self.properties.filepath)&lt;br /&gt;
        simple_obj_import.import_simple_obj(&lt;br /&gt;
            self.properties.filepath, &lt;br /&gt;
            self.rot90, &lt;br /&gt;
            self.scale)&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;
#    Export menu&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
class EXPORT_OT_simple_obj(bpy.types.Operator, ExportHelper):&lt;br /&gt;
    bl_idname = &amp;quot;io_export_scene.simple_obj&amp;quot;&lt;br /&gt;
    bl_description = 'Export from simple OBJ file format (.obj)'&lt;br /&gt;
    bl_label = &amp;quot;Export simple OBJ&amp;quot;&lt;br /&gt;
    bl_space_type = &amp;quot;PROPERTIES&amp;quot;&lt;br /&gt;
    bl_region_type = &amp;quot;WINDOW&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # From ExportHelper. Filter filenames.&lt;br /&gt;
    filename_ext = &amp;quot;.obj&amp;quot;&lt;br /&gt;
    filter_glob = StringProperty(default=&amp;quot;*.obj&amp;quot;, options={'HIDDEN'})&lt;br /&gt;
&lt;br /&gt;
    filepath = bpy.props.StringProperty(&lt;br /&gt;
        name=&amp;quot;File Path&amp;quot;, &lt;br /&gt;
        description=&amp;quot;File path used for exporting the simple OBJ file&amp;quot;, &lt;br /&gt;
        maxlen= 1024, default= &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    rot90 = bpy.props.BoolProperty(&lt;br /&gt;
        name = &amp;quot;Rotate 90 degrees&amp;quot;,&lt;br /&gt;
        description=&amp;quot;Rotate mesh to Y up&amp;quot;,&lt;br /&gt;
        default = True)&lt;br /&gt;
&lt;br /&gt;
    scale = bpy.props.FloatProperty(&lt;br /&gt;
        name = &amp;quot;Scale&amp;quot;, &lt;br /&gt;
        description=&amp;quot;Scale mesh&amp;quot;, &lt;br /&gt;
        default = 0.1, min = 0.001, max = 1000.0)&lt;br /&gt;
&lt;br /&gt;
    def execute(self, context):&lt;br /&gt;
        print(&amp;quot;Load&amp;quot;, self.properties.filepath)&lt;br /&gt;
        from . import simple_obj_export&lt;br /&gt;
        simple_obj_export.export_simple_obj(&lt;br /&gt;
            self.properties.filepath, &lt;br /&gt;
            context.object, &lt;br /&gt;
            self.rot90, &lt;br /&gt;
            1.0/self.scale)&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_import(self, context):&lt;br /&gt;
    self.layout.operator(IMPORT_OT_simple_obj.bl_idname, text=&amp;quot;Simple OBJ (.obj)...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def menu_func_export(self, context):&lt;br /&gt;
    self.layout.operator(EXPORT_OT_simple_obj.bl_idname, text=&amp;quot;Simple OBJ (.obj)...&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_import)&lt;br /&gt;
    bpy.types.INFO_MT_file_export.append(menu_func_export)&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_import)&lt;br /&gt;
    bpy.types.INFO_MT_file_export.remove(menu_func_export)&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;
{{Page/Footer|Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons|Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Simulations}}&lt;/div&gt;</summary>
		<author><name>wiki&gt;Lijenstina</name></author>
		
	</entry>
</feed>