Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-09-01 16:11:34 +0400
committerCampbell Barton <ideasman42@gmail.com>2010-09-01 16:11:34 +0400
commita89c526a92a9f3568d4c0dad139d608518edecbb (patch)
tree1c803ec9baeb56d0e90efee17aadd9c503318656 /release
parent7532bc23254b6efbee26f69b02da04d66b32c0bb (diff)
finished moving importers and exporters into python packages (as proposed on the mailing list).
- made operator dir's into python packages - lazy loading of module which do the actual import and export (faster blender load times) - general maintanance and small fixes. - bugfix for exporting x3d materials - leak fix for exporting 3ds
Diffstat (limited to 'release')
-rw-r--r--release/scripts/io/netrender/__init__.py7
-rw-r--r--release/scripts/modules/io_utils.py45
-rw-r--r--release/scripts/op/io_anim_bvh/__init__.py74
-rw-r--r--release/scripts/op/io_anim_bvh/import_bvh.py77
-rw-r--r--release/scripts/op/io_mesh_ply/__init__.py76
-rw-r--r--release/scripts/op/io_mesh_ply/export_ply.py143
-rw-r--r--release/scripts/op/io_scene_3ds/__init__.py86
-rw-r--r--release/scripts/op/io_scene_3ds/export_3ds.py160
-rw-r--r--release/scripts/op/io_scene_3ds/import_3ds.py223
-rw-r--r--release/scripts/op/io_scene_fbx/__init__.py102
-rw-r--r--release/scripts/op/io_scene_fbx/export_fbx.py193
-rw-r--r--release/scripts/op/io_scene_obj/__init__.py144
-rw-r--r--release/scripts/op/io_scene_obj/export_obj.py138
-rw-r--r--release/scripts/op/io_scene_obj/import_obj.py349
-rw-r--r--release/scripts/op/io_scene_x3d/__init__.py61
-rw-r--r--release/scripts/op/io_scene_x3d/export_x3d.py111
-rw-r--r--release/scripts/op/io_shape_mdd/__init__.py115
-rw-r--r--release/scripts/op/io_shape_mdd/export_mdd.py102
-rw-r--r--release/scripts/op/io_shape_mdd/import_mdd.py91
19 files changed, 1050 insertions, 1247 deletions
diff --git a/release/scripts/io/netrender/__init__.py b/release/scripts/io/netrender/__init__.py
index 5a705e95aa8..e4f6bf65fe2 100644
--- a/release/scripts/io/netrender/__init__.py
+++ b/release/scripts/io/netrender/__init__.py
@@ -19,9 +19,7 @@
# This directory is a Python package.
# To support reload properly, try to access a package var, if it's there, reload everything
-try:
- init_data
-
+if "bpy" in locals():
reload(model)
reload(operators)
reload(client)
@@ -32,7 +30,7 @@ try:
reload(balancing)
reload(ui)
reload(repath)
-except:
+else:
from netrender import model
from netrender import operators
from netrender import client
@@ -49,7 +47,6 @@ slaves = []
blacklist = []
init_file = ""
-init_data = True
init_address = True
def register():
diff --git a/release/scripts/modules/io_utils.py b/release/scripts/modules/io_utils.py
index b65ada8d804..db783dd1054 100644
--- a/release/scripts/modules/io_utils.py
+++ b/release/scripts/modules/io_utils.py
@@ -42,6 +42,23 @@ class ImportHelper:
return {'RUNNING_MODAL'}
+# limited replacement for BPyImage.comprehensiveImageLoad
+def load_image(imagepath, dirname):
+
+ if os.path.exists(imagepath):
+ return bpy.data.images.load(imagepath)
+
+ variants = [imagepath, os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
+
+ for filepath in variants:
+ for nfilepath in (filepath, bpy.path.resolve_ncase(filepath)):
+ if os.path.exists(nfilepath):
+ return bpy.data.images.load(nfilepath)
+
+ # TODO comprehensiveImageLoad also searched in bpy.config.textureDir
+ return None
+
+
# return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects()
def create_derived_objects(scene, ob):
if ob.parent and ob.parent.dupli_type != 'NONE':
@@ -54,42 +71,16 @@ def create_derived_objects(scene, ob):
return False, [(ob, ob.matrix_world)]
-
def free_derived_objects(ob):
ob.free_dupli_list()
-# So 3ds max can open files, limit names to 12 in length
-# this is verry annoying for filenames!
-name_unique = []
-name_mapping = {}
-def sane_name(name):
- name_fixed = name_mapping.get(name)
- if name_fixed != None:
- return name_fixed
-
- if len(name) > 12:
- new_name = name[:12]
- else:
- new_name = name
-
- i = 0
-
- while new_name in name_unique:
- new_name = new_name[:-4] + '.%.3d' % i
- i+=1
-
- name_unique.append(new_name)
- name_mapping[name] = new_name
- return new_name
-
-
def unpack_list(list_of_tuples):
flat_list = []
flat_list_extend = flat_list.extend # a tich faster
for t in list_of_tuples:
flat_list_extend(t)
- return l
+ return flat_list
# same as above except that it adds 0 for triangle faces
def unpack_face_list(list_of_tuples):
diff --git a/release/scripts/op/io_anim_bvh/__init__.py b/release/scripts/op/io_anim_bvh/__init__.py
new file mode 100644
index 00000000000..6b529f87dd7
--- /dev/null
+++ b/release/scripts/op/io_anim_bvh/__init__.py
@@ -0,0 +1,74 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ # only reload if we alredy loaded, highly annoying
+ import sys
+ reload(sys.modules.get("io_mesh_ply.export_ply", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ImportHelper
+
+
+class BvhImporter(bpy.types.Operator, ImportHelper):
+ '''Load a OBJ Motion Capture File'''
+ bl_idname = "import_anim.bvh"
+ bl_label = "Import BVH"
+
+ filename_ext = ".bvh"
+
+ scale = FloatProperty(name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=0.1)
+ frame_start = IntProperty(name="Start Frame", description="Starting frame for the animation", default=1)
+ loop = BoolProperty(name="Loop", description="Loop the animation playback", default=False)
+ rotate_mode = EnumProperty(items=(
+ ('QUATERNION', "Quaternion", "Convert rotations to quaternions"),
+ ('NATIVE', "Euler (Native)", "Use the rotation order defined in the BVH file"),
+ ('XYZ', "Euler (XYZ)", "Convert rotations to euler XYZ"),
+ ('XZY', "Euler (XZY)", "Convert rotations to euler XZY"),
+ ('YXZ', "Euler (YXZ)", "Convert rotations to euler YXZ"),
+ ('YZX', "Euler (YZX)", "Convert rotations to euler YZX"),
+ ('ZXY', "Euler (ZXY)", "Convert rotations to euler ZXY"),
+ ('ZYX', "Euler (ZYX)", "Convert rotations to euler ZYX"),
+ ),
+ name="Rotation",
+ description="Rotation conversion.",
+ default='NATIVE')
+
+ def execute(self, context):
+ import io_anim_bvh.import_bvh
+ return io_anim_bvh.import_bvh.load(self, context, **self.properties)
+
+
+def menu_func(self, context):
+ self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)")
+
+
+def register():
+ bpy.types.INFO_MT_file_import.append(menu_func)
+
+
+def unregister():
+ bpy.types.INFO_MT_file_import.remove(menu_func)
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_anim_bvh/import_bvh.py b/release/scripts/op/io_anim_bvh/import_bvh.py
index 21b3e5e9aa1..befd6cdbe89 100644
--- a/release/scripts/op/io_anim_bvh/import_bvh.py
+++ b/release/scripts/op/io_anim_bvh/import_bvh.py
@@ -555,67 +555,24 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
return arm_ob
-from bpy.props import *
-from io_utils import ImportHelper
+def load(operator, context, filepath="", rotate_mode='NATIVE', scale=1.0, use_cyclic=False, frame_start=1):
+ import time
+ t1 = time.time()
+ print('\tparsing bvh %r...' % filepath, end="")
+ bvh_nodes = read_bvh(context, filepath,
+ ROT_MODE=rotate_mode,
+ GLOBAL_SCALE=scale)
-class BvhImporter(bpy.types.Operator, ImportHelper):
- '''Load a OBJ Motion Capture File'''
- bl_idname = "import_anim.bvh"
- bl_label = "Import BVH"
-
- filename_ext = ".bvh"
-
- scale = FloatProperty(name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=0.1)
- frame_start = IntProperty(name="Start Frame", description="Starting frame for the animation", default=1)
- loop = BoolProperty(name="Loop", description="Loop the animation playback", default=False)
- rotate_mode = EnumProperty(items=(
- ('QUATERNION', "Quaternion", "Convert rotations to quaternions"),
- ('NATIVE', "Euler (Native)", "Use the rotation order defined in the BVH file"),
- ('XYZ', "Euler (XYZ)", "Convert rotations to euler XYZ"),
- ('XZY', "Euler (XZY)", "Convert rotations to euler XZY"),
- ('YXZ', "Euler (YXZ)", "Convert rotations to euler YXZ"),
- ('YZX', "Euler (YZX)", "Convert rotations to euler YZX"),
- ('ZXY', "Euler (ZXY)", "Convert rotations to euler ZXY"),
- ('ZYX', "Euler (ZYX)", "Convert rotations to euler ZYX"),
- ),
- name="Rotation",
- description="Rotation conversion.",
- default='NATIVE')
-
- def execute(self, context):
- # print("Selected: " + context.active_object.name)
- import time
- t1 = time.time()
- print('\tparsing bvh...', end="")
-
- bvh_nodes = read_bvh(context, self.properties.filepath,
- ROT_MODE=self.properties.rotate_mode,
- GLOBAL_SCALE=self.properties.scale)
-
- print('%.4f' % (time.time() - t1))
- t1 = time.time()
- print('\timporting to blender...', end="")
-
- bvh_node_dict2armature(context, bvh_nodes,
- ROT_MODE=self.properties.rotate_mode,
- IMPORT_START_FRAME=self.properties.frame_start,
- IMPORT_LOOP=self.properties.loop)
-
- print('Done in %.4f\n' % (time.time() - t1))
- return {'FINISHED'}
+ print('%.4f' % (time.time() - t1))
+ t1 = time.time()
+ print('\timporting to blender...', end="")
+ bvh_node_dict2armature(context, bvh_nodes,
+ ROT_MODE=rotate_mode,
+ IMPORT_START_FRAME=frame_start,
+ IMPORT_LOOP=use_cyclic)
-def menu_func(self, context):
- self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)")
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-if __name__ == "__main__":
- register()
+ print('Done in %.4f\n' % (time.time() - t1))
+
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_mesh_ply/__init__.py b/release/scripts/op/io_mesh_ply/__init__.py
new file mode 100644
index 00000000000..c174b16f46c
--- /dev/null
+++ b/release/scripts/op/io_mesh_ply/__init__.py
@@ -0,0 +1,76 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ import sys
+ reload(sys.modules.get("io_mesh_ply.export_ply", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper
+
+
+class ExportPLY(bpy.types.Operator, ExportHelper):
+ '''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
+ bl_idname = "export.ply"
+ bl_label = "Export PLY"
+
+ filename_ext = ".ply"
+
+ use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
+ use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
+ use_uv_coords = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
+ use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
+
+ @classmethod
+ def poll(cls, context):
+ return context.active_object != None
+
+ def execute(self, context):
+ filepath = self.properties.filepath
+ filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
+ import io_mesh_ply.export_ply
+ return io_mesh_ply.export_ply.save(self, context, **self.properties)
+
+ def draw(self, context):
+ layout = self.layout
+ props = self.properties
+
+ row = layout.row()
+ row.prop(props, "use_modifiers")
+ row.prop(props, "use_normals")
+ row = layout.row()
+ row.prop(props, "use_uv_coords")
+ row.prop(props, "use_colors")
+
+
+def menu_func(self, context):
+ self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)")
+
+
+def register():
+ bpy.types.INFO_MT_file_export.append(menu_func)
+
+
+def unregister():
+ bpy.types.INFO_MT_file_export.remove(menu_func)
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_mesh_ply/export_ply.py b/release/scripts/op/io_mesh_ply/export_ply.py
index f6b33239fe7..aef4df43841 100644
--- a/release/scripts/op/io_mesh_ply/export_ply.py
+++ b/release/scripts/op/io_mesh_ply/export_ply.py
@@ -21,79 +21,64 @@
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
# Contributors: Bruce Merry, Campbell Barton
-import bpy
-
"""
This script exports Stanford PLY files from Blender. It supports normals,
colours, and texture coordinates per face or per vertex.
Only one mesh can be exported at a time.
"""
-def rvec3d(v):
- return round(v[0], 6), round(v[1], 6), round(v[2], 6)
-
+import bpy
+import os
-def rvec2d(v):
- return round(v[0], 6), round(v[1], 6)
+def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
+
+ def rvec3d(v):
+ return round(v[0], 6), round(v[1], 6), round(v[2], 6)
-def write(filename, scene, ob, \
- EXPORT_APPLY_MODIFIERS=True,\
- EXPORT_NORMALS=True,\
- EXPORT_UV=True,\
- EXPORT_COLORS=True):
- if not filename.lower().endswith('.ply'):
- filename += '.ply'
+ def rvec2d(v):
+ return round(v[0], 6), round(v[1], 6)
+
+ scene = context.scene
+ obj = context.object
- if not ob:
+ if not obj:
raise Exception("Error, Select 1 active object")
- return
- file = open(filename, 'w')
+ file = open(filepath, 'w')
-
- #EXPORT_EDGES = Draw.Create(0)
- """
- is_editmode = Blender.Window.EditMode()
- if is_editmode:
- Blender.Window.EditMode(0, '', 0)
-
- Window.WaitCursor(1)
- """
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
- #mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) # XXX
- if EXPORT_APPLY_MODIFIERS:
- mesh = ob.create_mesh(scene, True, 'PREVIEW')
+ if use_modifiers:
+ mesh = obj.create_mesh(scene, True, 'PREVIEW')
else:
- mesh = ob.data
+ mesh = obj.data
if not mesh:
- raise ("Error, could not get mesh data from active object")
- return
+ raise Exception("Error, could not get mesh data from active object")
- # mesh.transform(ob.matrix_world) # XXX
+ # mesh.transform(obj.matrix_world) # XXX
faceUV = (len(mesh.uv_textures) > 0)
vertexUV = (len(mesh.sticky) > 0)
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
- EXPORT_UV = False
+ use_uv_coords = False
if not vertexColors:
- EXPORT_COLORS = False
+ use_colors = False
- if not EXPORT_UV:
+ if not use_uv_coords:
faceUV = vertexUV = False
- if not EXPORT_COLORS:
+ if not use_colors:
vertexColors = False
if faceUV:
active_uv_layer = mesh.uv_textures.active
if not active_uv_layer:
- EXPORT_UV = False
+ use_uv_coords = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
@@ -101,7 +86,7 @@ def write(filename, scene, ob, \
if vertexColors:
active_col_layer = mesh.vertex_colors.active
if not active_col_layer:
- EXPORT_COLORS = False
+ use_colors = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
@@ -166,7 +151,7 @@ def write(filename, scene, ob, \
file.write('ply\n')
file.write('format ascii 1.0\n')
- file.write('comment Created by Blender %s - www.blender.org, source file: %s\n' % (bpy.app.version_string, bpy.data.filepath.split('/')[-1].split('\\')[-1]))
+ file.write('comment Created by Blender %s - www.blender.org, source file: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath)))
file.write('element vertex %d\n' % len(ply_verts))
@@ -174,14 +159,14 @@ def write(filename, scene, ob, \
file.write('property float y\n')
file.write('property float z\n')
- if EXPORT_NORMALS:
+ if use_normals:
file.write('property float nx\n')
file.write('property float ny\n')
file.write('property float nz\n')
- if EXPORT_UV:
+ if use_uv_coords:
file.write('property float s\n')
file.write('property float t\n')
- if EXPORT_COLORS:
+ if use_colors:
file.write('property uchar red\n')
file.write('property uchar green\n')
file.write('property uchar blue\n')
@@ -192,11 +177,11 @@ def write(filename, scene, ob, \
for i, v in enumerate(ply_verts):
file.write('%.6f %.6f %.6f ' % tuple(mesh_verts[v[0]].co)) # co
- if EXPORT_NORMALS:
+ if use_normals:
file.write('%.6f %.6f %.6f ' % v[1]) # no
- if EXPORT_UV:
+ if use_uv_coords:
file.write('%.6f %.6f ' % v[2]) # uv
- if EXPORT_COLORS:
+ if use_colors:
file.write('%u %u %u' % v[3]) # col
file.write('\n')
@@ -207,9 +192,9 @@ def write(filename, scene, ob, \
file.write('4 %d %d %d %d\n' % tuple(pf))
file.close()
- print("writing", filename, "done")
+ print("writing %r done" % filepath)
- if EXPORT_APPLY_MODIFIERS:
+ if use_modifiers:
bpy.data.meshes.remove(mesh)
# XXX
@@ -217,65 +202,5 @@ def write(filename, scene, ob, \
if is_editmode:
Blender.Window.EditMode(1, '', 0)
"""
-
-from bpy.props import *
-from io_utils import ExportHelper
-
-
-class ExportPLY(bpy.types.Operator, ExportHelper):
- '''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
- bl_idname = "export.ply"
- bl_label = "Export PLY"
- filename_ext = ".ply"
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
- use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
- use_uvs = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
- use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- write(filepath, context.scene, context.active_object,\
- EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
- EXPORT_NORMALS=self.properties.use_normals,
- EXPORT_UV=self.properties.use_uvs,
- EXPORT_COLORS=self.properties.use_colors,
- )
-
- return {'FINISHED'}
-
- def draw(self, context):
- layout = self.layout
- props = self.properties
-
- row = layout.row()
- row.prop(props, "use_modifiers")
- row.prop(props, "use_normals")
- row = layout.row()
- row.prop(props, "use_uvs")
- row.prop(props, "use_colors")
-
-
-def menu_func(self, context):
- self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_scene_3ds/__init__.py b/release/scripts/op/io_scene_3ds/__init__.py
new file mode 100644
index 00000000000..cff8feb7255
--- /dev/null
+++ b/release/scripts/op/io_scene_3ds/__init__.py
@@ -0,0 +1,86 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ import sys
+ reload(sys.modules.get("io_scene_3ds.import_3ds", sys))
+ reload(sys.modules.get("io_scene_3ds.export_3ds", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ImportHelper, ExportHelper
+
+
+class Import3DS(bpy.types.Operator, ImportHelper):
+ '''Import from 3DS file format (.3ds)'''
+ bl_idname = "import_scene.autodesk_3ds"
+ bl_label = 'Import 3DS'
+
+ filename_ext = ".3ds"
+
+ constrain_size = FloatProperty(name="Size Constraint", description="Scale the model by 10 until it reacehs the size constraint. Zero Disables.", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=10.0)
+ use_image_search = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True)
+ use_apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=False)
+
+ def execute(self, context):
+ import io_scene_3ds.import_3ds
+ return io_scene_3ds.import_3ds.load(self, context, **self.properties)
+
+
+class Export3DS(bpy.types.Operator, ExportHelper):
+ '''Export to 3DS file format (.3ds)'''
+ bl_idname = "export_scene.autodesk_3ds"
+ bl_label = 'Export 3DS'
+
+ filename_ext = ".3ds"
+
+ def execute(self, context):
+ import io_scene_3ds.export_3ds
+ return io_scene_3ds.export_3ds.save(self, context, **self.properties)
+
+
+# Add to a menu
+def menu_func_export(self, context):
+ self.layout.operator(Export3DS.bl_idname, text="3D Studio (.3ds)")
+
+def menu_func_import(self, context):
+ self.layout.operator(Import3DS.bl_idname, text="3D Studio (.3ds)")
+
+def register():
+ bpy.types.INFO_MT_file_import.append(menu_func_import)
+ bpy.types.INFO_MT_file_export.append(menu_func_export)
+
+
+def unregister():
+ bpy.types.INFO_MT_file_import.remove(menu_func_import)
+ bpy.types.INFO_MT_file_export.remove(menu_func_export)
+
+if __name__ == "__main__":
+ register()
+
+# NOTES:
+# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D"
+# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)
+
+if __name__ == "__main__":
+ register()
+
diff --git a/release/scripts/op/io_scene_3ds/export_3ds.py b/release/scripts/op/io_scene_3ds/export_3ds.py
index c972ba22178..3d1cc02a8d8 100644
--- a/release/scripts/op/io_scene_3ds/export_3ds.py
+++ b/release/scripts/op/io_scene_3ds/export_3ds.py
@@ -32,58 +32,81 @@ from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode.
#Some of the chunks that we will export
#----- Primary Chunk, at the beginning of each file
-PRIMARY= int("0x4D4D",16)
+PRIMARY= 0x4D4D
#------ Main Chunks
-OBJECTINFO = int("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information
-VERSION = int("0x0002",16); #This gives the version of the .3ds file
-KFDATA = int("0xB000",16); #This is the header for all of the key frame info
+OBJECTINFO = 0x3D3D #This gives the version of the mesh and is found right before the material and object information
+VERSION = 0x0002 #This gives the version of the .3ds file
+KFDATA = 0xB000 #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO
MATERIAL=45055 #0xAFFF // This stored the texture info
OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL
-MATNAME = int("0xA000",16); # This holds the material name
-MATAMBIENT = int("0xA010",16); # Ambient color of the object/material
-MATDIFFUSE = int("0xA020",16); # This holds the color of the object/material
-MATSPECULAR = int("0xA030",16); # SPecular color of the object/material
-MATSHINESS = int("0xA040",16); # ??
-MATMAP = int("0xA200",16); # This is a header for a new material
-MATMAPFILE = int("0xA300",16); # This holds the file name of the texture
+MATNAME = 0xA000 # This holds the material name
+MATAMBIENT = 0xA010 # Ambient color of the object/material
+MATDIFFUSE = 0xA020 # This holds the color of the object/material
+MATSPECULAR = 0xA030 # SPecular color of the object/material
+MATSHINESS = 0xA040 # ??
+MATMAP = 0xA200 # This is a header for a new material
+MATMAPFILE = 0xA300 # This holds the file name of the texture
-RGB1= int("0x0011",16)
-RGB2= int("0x0012",16)
+RGB1= 0x0011
+RGB2= 0x0012
#>------ sub defines of OBJECT
-OBJECT_MESH = int("0x4100",16); # This lets us know that we are reading a new object
-OBJECT_LIGHT = int("0x4600",16); # This lets un know we are reading a light object
-OBJECT_CAMERA= int("0x4700",16); # This lets un know we are reading a camera object
+OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
+OBJECT_LIGHT = 0x4600 # This lets un know we are reading a light object
+OBJECT_CAMERA= 0x4700 # This lets un know we are reading a camera object
#>------ sub defines of CAMERA
-OBJECT_CAM_RANGES= int("0x4720",16); # The camera range values
+OBJECT_CAM_RANGES= 0x4720 # The camera range values
#>------ sub defines of OBJECT_MESH
-OBJECT_VERTICES = int("0x4110",16); # The objects vertices
-OBJECT_FACES = int("0x4120",16); # The objects faces
-OBJECT_MATERIAL = int("0x4130",16); # This is found if the object has a material, either texture map or color
-OBJECT_UV = int("0x4140",16); # The UV texture coordinates
-OBJECT_TRANS_MATRIX = int("0x4160",16); # The Object Matrix
+OBJECT_VERTICES = 0x4110 # The objects vertices
+OBJECT_FACES = 0x4120 # The objects faces
+OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
+OBJECT_UV = 0x4140 # The UV texture coordinates
+OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
#>------ sub defines of KFDATA
-KFDATA_KFHDR = int("0xB00A",16);
-KFDATA_KFSEG = int("0xB008",16);
-KFDATA_KFCURTIME = int("0xB009",16);
-KFDATA_OBJECT_NODE_TAG = int("0xB002",16);
+KFDATA_KFHDR = 0xB00A
+KFDATA_KFSEG = 0xB008
+KFDATA_KFCURTIME = 0xB009
+KFDATA_OBJECT_NODE_TAG = 0xB002
#>------ sub defines of OBJECT_NODE_TAG
-OBJECT_NODE_ID = int("0xB030",16);
-OBJECT_NODE_HDR = int("0xB010",16);
-OBJECT_PIVOT = int("0xB013",16);
-OBJECT_INSTANCE_NAME = int("0xB011",16);
-POS_TRACK_TAG = int("0xB020",16);
-ROT_TRACK_TAG = int("0xB021",16);
-SCL_TRACK_TAG = int("0xB022",16);
+OBJECT_NODE_ID = 0xB030
+OBJECT_NODE_HDR = 0xB010
+OBJECT_PIVOT = 0xB013
+OBJECT_INSTANCE_NAME = 0xB011
+POS_TRACK_TAG = 0xB020
+ROT_TRACK_TAG = 0xB021
+SCL_TRACK_TAG = 0xB022
+
+import struct
+
+# So 3ds max can open files, limit names to 12 in length
+# this is verry annoying for filenames!
+name_unique = []
+name_mapping = {}
+def sane_name(name):
+ name_fixed = name_mapping.get(name)
+ if name_fixed is not None:
+ return name_fixed
+
+ new_name = name[:12]
+
+ i = 0
+
+ while new_name in name_unique:
+ new_name = new_name[:-4] + '.%.3d' % i
+ i+=1
+
+ name_unique.append(new_name)
+ name_mapping[name] = new_name
+ return new_name
def uv_key(uv):
return round(uv[0], 6), round(uv[1], 6)
@@ -293,7 +316,7 @@ class _3ds_named_variable(object):
if (self.value!=None):
spaces=""
for i in range(indent):
- spaces+=" ";
+ spaces += " "
if (self.name!=""):
print(spaces, self.name, " = ", self.value)
else:
@@ -358,7 +381,7 @@ class _3ds_chunk(object):
Uses the dump function of the named variables and the subchunks to do the actual work.'''
spaces=""
for i in range(indent):
- spaces+=" ";
+ spaces += " "
print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size())
for variable in self.variables:
variable.dump(indent+1)
@@ -393,11 +416,11 @@ def make_material_subchunk(id, color):
Used for color subchunks, such as diffuse color or ambient color subchunks.'''
mat_sub = _3ds_chunk(id)
col1 = _3ds_chunk(RGB1)
- col1.add_variable("color1", _3ds_rgb_color(color));
+ col1.add_variable("color1", _3ds_rgb_color(color))
mat_sub.add_subchunk(col1)
# optional:
# col2 = _3ds_chunk(RGB1)
-# col2.add_variable("color2", _3ds_rgb_color(color));
+# col2.add_variable("color2", _3ds_rgb_color(color))
# mat_sub.add_subchunk(col2)
return mat_sub
@@ -835,21 +858,21 @@ def make_kf_obj_node(obj, name_to_id):
return kf_obj_node
"""
-# import BPyMessages
-def write(filename, context):
+
+def save(operator, context, filepath=""):
+ import bpy
+ import time
+ from io_utils import create_derived_objects, free_derived_objects
+
'''Save the Blender scene to a 3ds file.'''
+
# Time the export
-
- # XXX
-# if not BPyMessages.Warning_SaveOver(filename):
-# return
-
time1 = time.clock()
# Blender.Window.WaitCursor(1)
sce = context.scene
- if context.object:
+ if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# Initialize the main chunk (primary):
@@ -998,7 +1021,7 @@ def write(filename, context):
# Check the size:
primary.get_size()
# Open the file for writing:
- file = open( filename, 'wb' )
+ file = open(filepath, 'wb')
# Recursively write the chunks to file:
primary.write(file)
@@ -1006,50 +1029,15 @@ def write(filename, context):
# Close the file:
file.close()
+ # Clear name mapping vars, could make locals too
+ name_unique[:] = []
+ name_mapping.clear()
+
# Debugging only: report the exporting time:
# Blender.Window.WaitCursor(0)
print("3ds export time: %.2f" % (time.clock() - time1))
-# print("3ds export time: %.2f" % (Blender.sys.time() - time1))
# Debugging only: dump the chunk hierarchy:
#primary.dump()
-
-import bpy
-from bpy.props import *
-from io_utils import ExportHelper
-from io_utils import create_derived_objects, free_derived_objects
-
-
-class Export3DS(bpy.types.Operator, ExportHelper):
- '''Export to 3DS file format (.3ds)'''
- bl_idname = "export.autodesk_3ds"
- bl_label = 'Export 3DS'
- filename_ext = ".3ds"
-
- @classmethod
- def poll(cls, context): # Poll isnt working yet
- return context.active_object != None
-
- def execute(self, context):
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- write(filepath, context)
- return {'FINISHED'}
-
-
-# Add to a menu
-def menu_func(self, context):
- self.layout.operator(Export3DS.bl_idname, text="3D Studio (.3ds)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_scene_3ds/import_3ds.py b/release/scripts/op/io_scene_3ds/import_3ds.py
index 37f707af3e3..5ea705f15f7 100644
--- a/release/scripts/op/io_scene_3ds/import_3ds.py
+++ b/release/scripts/op/io_scene_3ds/import_3ds.py
@@ -25,7 +25,7 @@ import os
import time
import struct
-from import_scene_obj import load_image
+from io_utils import load_image
import bpy
import mathutils
@@ -42,9 +42,9 @@ BOUNDS_3DS = []
PRIMARY = int('0x4D4D',16)
#------ Main Chunks
-OBJECTINFO = int('0x3D3D',16); #This gives the version of the mesh and is found right before the material and object information
-VERSION = int('0x0002',16); #This gives the version of the .3ds file
-EDITKEYFRAME= int('0xB000',16); #This is the header for all of the key frame info
+OBJECTINFO = 0x3D3D #This gives the version of the mesh and is found right before the material and object information
+VERSION = 0x0002 #This gives the version of the .3ds file
+EDITKEYFRAME= 0xB000 #This is the header for all of the key frame info
#------ sub defines of OBJECTINFO
MATERIAL = 45055 #0xAFFF // This stored the texture info
@@ -52,62 +52,62 @@ OBJECT = 16384 #0x4000 // This stores the faces, vertices, etc...
#>------ sub defines of MATERIAL
#------ sub defines of MATERIAL_BLOCK
-MAT_NAME = int('0xA000',16) # This holds the material name
-MAT_AMBIENT = int('0xA010',16) # Ambient color of the object/material
-MAT_DIFFUSE = int('0xA020',16) # This holds the color of the object/material
-MAT_SPECULAR = int('0xA030',16) # SPecular color of the object/material
-MAT_SHINESS = int('0xA040',16) # ??
-MAT_TRANSPARENCY= int('0xA050',16) # Transparency value of material
-MAT_SELF_ILLUM = int('0xA080',16) # Self Illumination value of material
-MAT_WIRE = int('0xA085',16) # Only render's wireframe
-
-MAT_TEXTURE_MAP = int('0xA200',16) # This is a header for a new texture map
-MAT_SPECULAR_MAP= int('0xA204',16) # This is a header for a new specular map
-MAT_OPACITY_MAP = int('0xA210',16) # This is a header for a new opacity map
-MAT_REFLECTION_MAP= int('0xA220',16) # This is a header for a new reflection map
-MAT_BUMP_MAP = int('0xA230',16) # This is a header for a new bump map
-MAT_MAP_FILENAME = int('0xA300',16) # This holds the file name of the texture
-
-MAT_FLOAT_COLOR = int ('0x0010', 16) #color defined as 3 floats
-MAT_24BIT_COLOR = int ('0x0011', 16) #color defined as 3 bytes
+MAT_NAME = 0xA000 # This holds the material name
+MAT_AMBIENT = 0xA010 # Ambient color of the object/material
+MAT_DIFFUSE = 0xA020 # This holds the color of the object/material
+MAT_SPECULAR = 0xA030 # SPecular color of the object/material
+MAT_SHINESS = 0xA040 # ??
+MAT_TRANSPARENCY= 0xA050 # Transparency value of material
+MAT_SELF_ILLUM = 0xA080 # Self Illumination value of material
+MAT_WIRE = 0xA085 # Only render's wireframe
+
+MAT_TEXTURE_MAP = 0xA200 # This is a header for a new texture map
+MAT_SPECULAR_MAP= 0xA204 # This is a header for a new specular map
+MAT_OPACITY_MAP = 0xA210 # This is a header for a new opacity map
+MAT_REFLECTION_MAP= 0xA220 # This is a header for a new reflection map
+MAT_BUMP_MAP = 0xA230 # This is a header for a new bump map
+MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
+
+MAT_FLOAT_COLOR = 0x0010 #color defined as 3 floats
+MAT_24BIT_COLOR = 0x0011 #color defined as 3 bytes
#>------ sub defines of OBJECT
-OBJECT_MESH = int('0x4100',16); # This lets us know that we are reading a new object
-OBJECT_LAMP = int('0x4600',16); # This lets un know we are reading a light object
-OBJECT_LAMP_SPOT = int('0x4610',16); # The light is a spotloght.
-OBJECT_LAMP_OFF = int('0x4620',16); # The light off.
-OBJECT_LAMP_ATTENUATE = int('0x4625',16);
-OBJECT_LAMP_RAYSHADE = int('0x4627',16);
-OBJECT_LAMP_SHADOWED = int('0x4630',16);
-OBJECT_LAMP_LOCAL_SHADOW = int('0x4640',16);
-OBJECT_LAMP_LOCAL_SHADOW2 = int('0x4641',16);
-OBJECT_LAMP_SEE_CONE = int('0x4650',16);
-OBJECT_LAMP_SPOT_RECTANGULAR = int('0x4651',16);
-OBJECT_LAMP_SPOT_OVERSHOOT = int('0x4652',16);
-OBJECT_LAMP_SPOT_PROJECTOR = int('0x4653',16);
-OBJECT_LAMP_EXCLUDE = int('0x4654',16);
-OBJECT_LAMP_RANGE = int('0x4655',16);
-OBJECT_LAMP_ROLL = int('0x4656',16);
-OBJECT_LAMP_SPOT_ASPECT = int('0x4657',16);
-OBJECT_LAMP_RAY_BIAS = int('0x4658',16);
-OBJECT_LAMP_INNER_RANGE = int('0x4659',16);
-OBJECT_LAMP_OUTER_RANGE = int('0x465A',16);
-OBJECT_LAMP_MULTIPLIER = int('0x465B',16);
-OBJECT_LAMP_AMBIENT_LIGHT = int('0x4680',16);
-
-
-
-OBJECT_CAMERA= int('0x4700',16); # This lets un know we are reading a camera object
+OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
+OBJECT_LAMP = 0x4600 # This lets un know we are reading a light object
+OBJECT_LAMP_SPOT = 0x4610 # The light is a spotloght.
+OBJECT_LAMP_OFF = 0x4620 # The light off.
+OBJECT_LAMP_ATTENUATE = 0x4625
+OBJECT_LAMP_RAYSHADE = 0x4627
+OBJECT_LAMP_SHADOWED = 0x4630
+OBJECT_LAMP_LOCAL_SHADOW = 0x4640
+OBJECT_LAMP_LOCAL_SHADOW2 = 0x4641
+OBJECT_LAMP_SEE_CONE = 0x4650
+OBJECT_LAMP_SPOT_RECTANGULAR = 0x4651
+OBJECT_LAMP_SPOT_OVERSHOOT = 0x4652
+OBJECT_LAMP_SPOT_PROJECTOR = 0x4653
+OBJECT_LAMP_EXCLUDE = 0x4654
+OBJECT_LAMP_RANGE = 0x4655
+OBJECT_LAMP_ROLL = 0x4656
+OBJECT_LAMP_SPOT_ASPECT = 0x4657
+OBJECT_LAMP_RAY_BIAS = 0x4658
+OBJECT_LAMP_INNER_RANGE = 0x4659
+OBJECT_LAMP_OUTER_RANGE = 0x465A
+OBJECT_LAMP_MULTIPLIER = 0x465B
+OBJECT_LAMP_AMBIENT_LIGHT = 0x4680
+
+
+
+OBJECT_CAMERA= 0x4700 # This lets un know we are reading a camera object
#>------ sub defines of CAMERA
-OBJECT_CAM_RANGES= int('0x4720',16); # The camera range values
+OBJECT_CAM_RANGES= 0x4720 # The camera range values
#>------ sub defines of OBJECT_MESH
-OBJECT_VERTICES = int('0x4110',16); # The objects vertices
-OBJECT_FACES = int('0x4120',16); # The objects faces
-OBJECT_MATERIAL = int('0x4130',16); # This is found if the object has a material, either texture map or color
-OBJECT_UV = int('0x4140',16); # The UV texture coordinates
-OBJECT_TRANS_MATRIX = int('0x4160',16); # The Object Matrix
+OBJECT_VERTICES = 0x4110 # The objects vertices
+OBJECT_FACES = 0x4120 # The objects faces
+OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
+OBJECT_UV = 0x4140 # The UV texture coordinates
+OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
global scn
scn = None
@@ -304,7 +304,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#print 'MAT_TEXTURE_MAP..while', new_chunk.bytes_read, new_chunk.length
read_chunk(file, temp_chunk)
- if (temp_chunk.ID == MAT_MAP_FILENAME):
+ if (temp_chunk.ID == MAT_MAP_FILEPATH):
texture_name = read_string(file)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
@@ -318,7 +318,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if img:
add_texture_to_material(img, new_texture, contextMaterial, mapto)
- dirname = os.path.dirname(FILENAME)
+ dirname = os.path.dirname(file.name)
#loop through all the data for this chunk (previous chunk) and see what it is
while (previous_chunk.bytes_read < previous_chunk.length):
@@ -604,14 +604,14 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
#contextMatrix = contextMatrix * tx
#contextMatrix = contextMatrix *tx
- elif (new_chunk.ID == MAT_MAP_FILENAME):
+ elif (new_chunk.ID == MAT_MAP_FILEPATH):
texture_name = read_string(file)
try:
TEXTURE_DICT[contextMaterial.name]
except:
- #img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME)
+ #img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH)
img = TEXTURE_DICT[contextMaterial.name] = load_image(texture_name, dirname)
-# img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER=False, RECURSIVE=IMAGE_SEARCH)
+# img = TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILEPATH, PLACE_HOLDER=False, RECURSIVE=IMAGE_SEARCH)
new_chunk.bytes_read += len(texture_name)+1 #plus one for the null character that gets removed
@@ -634,30 +634,27 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH):
if CreateBlenderObject:
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
-def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False):
- global FILENAME, SCN
-# global FILENAME, SCN_OBJECTS
+def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=False):
+ global SCN
# XXX
-# if BPyMessages.Error_NoFile(filename):
+# if BPyMessages.Error_NoFile(filepath):
# return
- print('\n\nImporting 3DS: "%s"' % (filename))
-# print('\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)))
+ print('\n\nImporting 3DS: %r' % (filepath))
time1 = time.clock()
# time1 = Blender.sys.time()
- FILENAME = filename
current_chunk = chunk()
- file = open(filename,'rb')
+ file = open(filepath, 'rb')
#here we go!
# print 'reading the first chunk'
read_chunk(file, current_chunk)
if (current_chunk.ID!=PRIMARY):
- print('\tFatal Error: Not a valid 3ds file: ', filename)
+ print('\tFatal Error: Not a valid 3ds file: %r' % filepath)
file.close()
return
@@ -718,7 +715,7 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done DUMMYVERT
"""
if IMPORT_AS_INSTANCE:
- name = filename.split('\\')[-1].split('/')[-1]
+ name = filepath.split('\\')[-1].split('/')[-1]
# Create a group for this import.
group_scn = Scene.New(name)
for ob in importedObjects:
@@ -776,90 +773,10 @@ def load_3ds(filename, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True,
# Done constraining to bounds.
# Select all new objects.
- print('finished importing: "%s" in %.4f sec.' % (filename, (time.clock()-time1)))
-# print('finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)))
+ print('finished importing: %r in %.4f sec.' % (filepath, (time.clock()-time1)))
file.close()
-DEBUG = False
-# For testing compatibility
-#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False)
-#load_3ds('/metavr/archive/convert/old/arranged_3ds_to_hpx-2/only-need-engine-trains/Engine2.3DS', False)
-'''
-
-else:
- import os
- # DEBUG ONLY
- TIME = Blender.sys.time()
- import os
- print 'Searching for files'
- os.system('find /metavr/ -iname "*.3ds" > /tmp/temp3ds_list')
- # os.system('find /storage/ -iname "*.3ds" > /tmp/temp3ds_list')
- print '...Done'
- file = open('/tmp/temp3ds_list', 'r')
- lines = file.readlines()
- file.close()
- # sort by filesize for faster testing
- lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines]
- lines_size.sort()
- lines = [f[1] for f in lines_size]
-
-
- def between(v,a,b):
- if v <= max(a,b) and v >= min(a,b):
- return True
- return False
-
- for i, _3ds in enumerate(lines):
- if between(i, 650,800):
- #_3ds= _3ds[:-1]
- print 'Importing', _3ds, '\nNUMBER', i, 'of', len(lines)
- _3ds_file= _3ds.split('/')[-1].split('\\')[-1]
- newScn = Blender.Scene.New(_3ds_file)
- newScn.makeCurrent()
- load_3ds(_3ds, False)
-
- print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
-
-'''
-from bpy.props import *
-from io_utils import ImportHelper
-
-
-class IMPORT_OT_autodesk_3ds(bpy.types.Operator, ImportHelper):
- '''Import from 3DS file format (.3ds)'''
- bl_idname = "import_scene.autodesk_3ds"
- bl_label = 'Import 3DS'
-
- filename_ext = ".3ds"
-
- constrain_size = FloatProperty(name="Size Constraint", description="Scale the model by 10 until it reacehs the size constraint. Zero Disables.", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=10.0)
- search_images = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True)
- apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=False)
-
- def execute(self, context):
- load_3ds(self.properties.filepath,
- context,
- IMPORT_CONSTRAIN_BOUNDS=self.properties.constrain_size,
- IMAGE_SEARCH=self.properties.search_images,
- APPLY_MATRIX=self.properties.apply_transform)
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)")
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-# NOTES:
-# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D"
-# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)
-
-if __name__ == "__main__":
- register()
-
+def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True):
+ load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform)
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_scene_fbx/__init__.py b/release/scripts/op/io_scene_fbx/__init__.py
new file mode 100644
index 00000000000..f7195600de5
--- /dev/null
+++ b/release/scripts/op/io_scene_fbx/__init__.py
@@ -0,0 +1,102 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ # only reload if we alredy loaded, highly annoying
+ import sys
+ reload(sys.modules.get("io_scene_fbx.export_fbx", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper
+
+
+class ExportFBX(bpy.types.Operator, ExportHelper):
+ '''Selection to an ASCII Autodesk FBX'''
+ bl_idname = "export_scene.fbx"
+ bl_label = "Export FBX"
+
+ filename_ext = ".fbx"
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+
+ EXP_OBS_SELECTED = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=True)
+# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
+ TX_SCALE = FloatProperty(name="Scale", description="Scale all data, (Note! some imports dont support scaled armatures)", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
+ TX_XROT90 = BoolProperty(name="Rot X90", description="Rotate all objects 90 degrees about the X axis", default=True)
+ TX_YROT90 = BoolProperty(name="Rot Y90", description="Rotate all objects 90 degrees about the Y axis", default=False)
+ TX_ZROT90 = BoolProperty(name="Rot Z90", description="Rotate all objects 90 degrees about the Z axis", default=False)
+ EXP_EMPTY = BoolProperty(name="Empties", description="Export empty objects", default=True)
+ EXP_CAMERA = BoolProperty(name="Cameras", description="Export camera objects", default=True)
+ EXP_LAMP = BoolProperty(name="Lamps", description="Export lamp objects", default=True)
+ EXP_ARMATURE = BoolProperty(name="Armatures", description="Export armature objects", default=True)
+ EXP_MESH = BoolProperty(name="Meshes", description="Export mesh objects", default=True)
+ EXP_MESH_APPLY_MOD = BoolProperty(name="Modifiers", description="Apply modifiers to mesh objects", default=True)
+ EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
+ EXP_IMAGE_COPY = BoolProperty(name="Copy Image Files", description="Copy image files to the destination path", default=False)
+ # armature animation
+ ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
+ ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
+ ANIM_OPTIMIZE_PRECISSION = FloatProperty(name="Precision", description="Tolerence for comparing double keyframes (higher for greater accuracy)", min=1, max=16, soft_min=1, soft_max=16, default=6.0)
+# ANIM_ACTION_ALL = BoolProperty(name="Current Action", description="Use actions currently applied to the armatures (use scene start/end frame)", default=True)
+ ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Use all actions for armatures, if false, use current action", default=False)
+ # batch
+ BATCH_ENABLE = BoolProperty(name="Enable Batch", description="Automate exporting multiple scenes or groups to files", default=False)
+ BATCH_GROUP = BoolProperty(name="Group > File", description="Export each group as an FBX file, if false, export each scene as an FBX file", default=False)
+ BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
+ BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen=1024, default="")
+
+
+ def execute(self, context):
+ import math
+ from mathutils import Matrix
+ if not self.properties.filepath:
+ raise Exception("filepath not set")
+
+ mtx4_x90n = Matrix.Rotation(-math.pi/2.0, 4, 'X')
+ mtx4_y90n = Matrix.Rotation(-math.pi/2.0, 4, 'Y')
+ mtx4_z90n = Matrix.Rotation(-math.pi/2.0, 4, 'Z')
+
+ GLOBAL_MATRIX = Matrix()
+ GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.properties.TX_SCALE
+ if self.properties.TX_XROT90: GLOBAL_MATRIX = mtx4_x90n * GLOBAL_MATRIX
+ if self.properties.TX_YROT90: GLOBAL_MATRIX = mtx4_y90n * GLOBAL_MATRIX
+ if self.properties.TX_ZROT90: GLOBAL_MATRIX = mtx4_z90n * GLOBAL_MATRIX
+
+ import io_scene_fbx.export_fbx
+ return io_scene_fbx.export_fbx.save(self, context, GLOBAL_MATRIX=GLOBAL_MATRIX, **self.properties)
+
+
+def menu_func(self, context):
+ self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX (.fbx)")
+
+
+def register():
+ bpy.types.INFO_MT_file_export.append(menu_func)
+
+
+def unregister():
+ bpy.types.INFO_MT_file_export.remove(menu_func)
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_scene_fbx/export_fbx.py b/release/scripts/op/io_scene_fbx/export_fbx.py
index c48e86c2519..ec13decc026 100644
--- a/release/scripts/op/io_scene_fbx/export_fbx.py
+++ b/release/scripts/op/io_scene_fbx/export_fbx.py
@@ -34,19 +34,10 @@ import shutil # for file copying
import bpy
from mathutils import Vector, Euler, Matrix
-def copy_file(source, dest):
- # XXX - remove, can use shutil
- file = open(source, 'rb')
- data = file.read()
- file.close()
-
- file = open(dest, 'wb')
- file.write(data)
- file.close()
-
-
# XXX not used anymore, images are copied one at a time
def copy_images(dest_dir, textures):
+ import shutil
+
if not dest_dir.endswith(os.sep):
dest_dir += os.sep
@@ -61,12 +52,12 @@ def copy_images(dest_dir, textures):
# Make a name for the target path.
dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
if not Blender.sys.exists(dest_image_path): # Image isnt already there
- print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
+ print("\tCopying %r > %r" % (image_path, dest_image_path))
try:
- copy_file(image_path, dest_image_path)
+ shutil.copy(image_path, dest_image_path)
copyCount+=1
except:
- print('\t\tWarning, file failed to copy, skipping.')
+ print("\t\tWarning, file failed to copy, skipping.")
print('\tCopied %d images' % copyCount)
@@ -81,27 +72,11 @@ def eulerRadToDeg(eul):
return ret
-mtx4_identity = Matrix()
-
-# testing
-mtx_x90 = Matrix.Rotation( math.pi/2, 3, 'X') # used
-#mtx_x90n = Matrix.Rotation(-90, 3, 'x')
-#mtx_y90 = Matrix.Rotation( 90, 3, 'y')
-#mtx_y90n = Matrix.Rotation(-90, 3, 'y')
-#mtx_z90 = Matrix.Rotation( 90, 3, 'z')
-#mtx_z90n = Matrix.Rotation(-90, 3, 'z')
-
-#mtx4_x90 = Matrix.Rotation( 90, 4, 'x')
-mtx4_x90n = Matrix.Rotation(-math.pi/2, 4, 'X') # used
-#mtx4_y90 = Matrix.Rotation( 90, 4, 'y')
-mtx4_y90n = Matrix.Rotation(-math.pi/2, 4, 'Y') # used
-mtx4_z90 = Matrix.Rotation( math.pi/2, 4, 'Z') # used
-mtx4_z90n = Matrix.Rotation(-math.pi/2, 4, 'Z') # used
# def strip_path(p):
# return p.split('\\')[-1].split('/')[-1]
-# Used to add the scene name into the filename without using odd chars
+# Used to add the scene name into the filepath without using odd chars
sane_name_mapping_ob = {}
sane_name_mapping_mat = {}
sane_name_mapping_tex = {}
@@ -174,7 +149,7 @@ def sane_groupname(data): return sane_name(data, sane_name_mapping_group)
# '''
# fname_orig - blender path, can be relative
# basepath - fname_rel will be relative to this
-# FORCE_CWD - dont use the basepath, just add a ./ to the filename.
+# FORCE_CWD - dont use the basepath, just add a ./ to the filepath.
# use when we know the file will be in the basepath.
# '''
# fname = bpy.path.abspath(fname_orig)
@@ -259,19 +234,17 @@ header_comment = \
'''
-# This func can be called with just the filename
-def write(filename, batch_objects = None, \
- context = None,
+# This func can be called with just the filepath
+def save(operator, context, filepath="", \
EXP_OBS_SELECTED = True,
EXP_MESH = True,
EXP_MESH_APPLY_MOD = True,
-# EXP_MESH_HQ_NORMALS = False,
EXP_ARMATURE = True,
EXP_LAMP = True,
EXP_CAMERA = True,
EXP_EMPTY = True,
EXP_IMAGE_COPY = False,
- GLOBAL_MATRIX = Matrix(),
+ GLOBAL_MATRIX = None,
ANIM_ENABLE = True,
ANIM_OPTIMIZE = True,
ANIM_OPTIMIZE_PRECISSION = 6,
@@ -282,16 +255,26 @@ def write(filename, batch_objects = None, \
BATCH_OWN_DIR = False
):
- if bpy.context.object:
+ #XXX, missing arg
+ batch_objects = None
+
+ # testing
+ mtx_x90 = Matrix.Rotation( math.pi/2.0, 3, 'X') # used
+ mtx4_z90 = Matrix.Rotation( math.pi/2.0, 4, 'Z')
+
+ if GLOBAL_MATRIX is None:
+ GLOBAL_MATRIX = Matrix()
+
+ if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# ----------------- Batch support!
if BATCH_ENABLE:
if os == None: BATCH_OWN_DIR = False
- fbxpath = filename
+ fbxpath = filepath
- # get the path component of filename
+ # get the path component of filepath
tmp_exists = bpy.utils.exists(fbxpath)
# tmp_exists = Blender.sys.exists(fbxpath)
@@ -300,7 +283,7 @@ def write(filename, batch_objects = None, \
# while fbxpath and fbxpath[-1] not in ('/', '\\'):
# fbxpath = fbxpath[:-1]
if not fbxpath:
-# if not filename:
+# if not filepath:
# XXX
print('Error%t|Directory does not exist!')
# Draw.PupMenu('Error%t|Directory does not exist!')
@@ -345,9 +328,9 @@ def write(filename, batch_objects = None, \
os.mkdir(new_fbxpath)
- filename = new_fbxpath + newname + '.fbx'
+ filepath = new_fbxpath + newname + '.fbx'
- print('\nBatch exporting %s as...\n\t"%s"' % (data, filename))
+ print('\nBatch exporting %s as...\n\t%r' % (data, filepath))
# XXX don't know what to do with this, probably do the same? (Arystan)
if BATCH_GROUP: #group
@@ -370,12 +353,11 @@ def write(filename, batch_objects = None, \
# Call self with modified args
# Dont pass batch options since we already usedt them
- write(filename, data.objects,
+ write(filepath, data.objects,
context,
False,
EXP_MESH,
EXP_MESH_APPLY_MOD,
-# EXP_MESH_HQ_NORMALS,
EXP_ARMATURE,
EXP_LAMP,
EXP_CAMERA,
@@ -400,9 +382,9 @@ def write(filename, batch_objects = None, \
# end batch support
# Use this for working out paths relative to the export location
- basepath = os.path.dirname(filename) or '.'
+ basepath = os.path.dirname(filepath) or '.'
basepath += os.sep
-# basepath = Blender.sys.dirname(filename)
+# basepath = Blender.sys.dirname(filepath)
# ----------------------------------------------
# storage classes
@@ -549,11 +531,11 @@ def write(filename, batch_objects = None, \
- print('\nFBX export starting...', filename)
+ print('\nFBX export starting... %r' % filepath)
start_time = time.clock()
# start_time = Blender.sys.time()
try:
- file = open(filename, 'w')
+ file = open(filepath, 'w')
except:
return False
@@ -2449,7 +2431,7 @@ Objects: {''')
file.write('\n\t\tPoseNode: {')
file.write('\n\t\t\tNode: "Model::%s"' % fbxName )
if matrix: file.write('\n\t\t\tMatrix: %s' % mat4x4str(matrix))
- else: file.write('\n\t\t\tMatrix: %s' % mat4x4str(mtx4_identity))
+ else: file.write('\n\t\t\tMatrix: %s' % mat4x4str(Matrix()))
file.write('\n\t\t}')
file.write('\n\t}')
@@ -2946,12 +2928,10 @@ Takes: {''')
mist_start = m.start
mist_end = m.depth
mist_height = m.height
-# mist_intense, mist_start, mist_end, mist_height = world.mist
world_hor = world.horizon_color
-# world_hor = world.hor
else:
has_mist = mist_intense = mist_start = mist_end = mist_height = 0
- world_hor = 0,0,0
+ world_hor = 0, 0, 0
file.write('\n;Version 5 settings')
file.write('\n;------------------------------------------------------------------')
@@ -3003,94 +2983,7 @@ Takes: {''')
# bpy.util.copy_images( [ tex[1] for tex in textures if tex[1] != None ], basepath)
print('export finished in %.4f sec.' % (time.clock() - start_time))
- return True
-
-from bpy.props import *
-from io_utils import ExportHelper
-
-
-class ExportFBX(bpy.types.Operator, ExportHelper):
- '''Selection to an ASCII Autodesk FBX'''
- bl_idname = "export.fbx"
- bl_label = "Export FBX"
-
- filename_ext = ".fbx"
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- EXP_OBS_SELECTED = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=True)
-# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
- TX_SCALE = FloatProperty(name="Scale", description="Scale all data, (Note! some imports dont support scaled armatures)", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
- TX_XROT90 = BoolProperty(name="Rot X90", description="Rotate all objects 90 degrees about the X axis", default=True)
- TX_YROT90 = BoolProperty(name="Rot Y90", description="Rotate all objects 90 degrees about the Y axis", default=False)
- TX_ZROT90 = BoolProperty(name="Rot Z90", description="Rotate all objects 90 degrees about the Z axis", default=False)
- EXP_EMPTY = BoolProperty(name="Empties", description="Export empty objects", default=True)
- EXP_CAMERA = BoolProperty(name="Cameras", description="Export camera objects", default=True)
- EXP_LAMP = BoolProperty(name="Lamps", description="Export lamp objects", default=True)
- EXP_ARMATURE = BoolProperty(name="Armatures", description="Export armature objects", default=True)
- EXP_MESH = BoolProperty(name="Meshes", description="Export mesh objects", default=True)
- EXP_MESH_APPLY_MOD = BoolProperty(name="Modifiers", description="Apply modifiers to mesh objects", default=True)
- EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
- EXP_IMAGE_COPY = BoolProperty(name="Copy Image Files", description="Copy image files to the destination path", default=False)
- # armature animation
- ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
- ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
- ANIM_OPTIMIZE_PRECISSION = FloatProperty(name="Precision", description="Tolerence for comparing double keyframes (higher for greater accuracy)", min=1, max=16, soft_min=1, soft_max=16, default=6.0)
-# ANIM_ACTION_ALL = BoolProperty(name="Current Action", description="Use actions currently applied to the armatures (use scene start/end frame)", default=True)
- ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Use all actions for armatures, if false, use current action", default=False)
- # batch
- BATCH_ENABLE = BoolProperty(name="Enable Batch", description="Automate exporting multiple scenes or groups to files", default=False)
- BATCH_GROUP = BoolProperty(name="Group > File", description="Export each group as an FBX file, if false, export each scene as an FBX file", default=False)
- BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
- BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen=1024, default="")
-
-
- @classmethod
- def poll(cls, context):
- return context.active_object
-
- def execute(self, context):
- if not self.properties.filepath:
- raise Exception("filepath not set")
-
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- GLOBAL_MATRIX = mtx4_identity
- GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.properties.TX_SCALE
- if self.properties.TX_XROT90: GLOBAL_MATRIX = mtx4_x90n * GLOBAL_MATRIX
- if self.properties.TX_YROT90: GLOBAL_MATRIX = mtx4_y90n * GLOBAL_MATRIX
- if self.properties.TX_ZROT90: GLOBAL_MATRIX = mtx4_z90n * GLOBAL_MATRIX
-
- write(filepath,
- None, # XXX
- context,
- self.properties.EXP_OBS_SELECTED,
- self.properties.EXP_MESH,
- self.properties.EXP_MESH_APPLY_MOD,
-# self.properties.EXP_MESH_HQ_NORMALS,
- self.properties.EXP_ARMATURE,
- self.properties.EXP_LAMP,
- self.properties.EXP_CAMERA,
- self.properties.EXP_EMPTY,
- self.properties.EXP_IMAGE_COPY,
- GLOBAL_MATRIX,
- self.properties.ANIM_ENABLE,
- self.properties.ANIM_OPTIMIZE,
- self.properties.ANIM_OPTIMIZE_PRECISSION,
- self.properties.ANIM_ACTION_ALL,
- self.properties.BATCH_ENABLE,
- self.properties.BATCH_GROUP,
- self.properties.BATCH_FILE_PREFIX,
- self.properties.BATCH_OWN_DIR,
- )
-
- return {'FINISHED'}
-
-
-# if __name__ == "__main__":
-# bpy.ops.EXPORT_OT_ply(filepath="/tmp/test.ply")
+ return {'FINISHED'}
# NOTES (all line numbers correspond to original export_fbx.py (under release/scripts)
@@ -3111,21 +3004,3 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
# - bpy.sys.time move to bpy.sys.util?
# - new scene creation, activation: lines 327-342, 368
# - uses bpy.path.abspath, *.relpath - replace at least relpath
-
-# SMALL or COSMETICAL
-# - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
-
-
-def menu_func(self, context):
- self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX (.fbx)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/io_scene_obj/__init__.py b/release/scripts/op/io_scene_obj/__init__.py
new file mode 100644
index 00000000000..d3791d1cd95
--- /dev/null
+++ b/release/scripts/op/io_scene_obj/__init__.py
@@ -0,0 +1,144 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ # only reload if we alredy loaded, highly annoying
+ import sys
+ reload(sys.modules.get("io_scene_obj.import_obj", sys))
+ reload(sys.modules.get("io_scene_obj.export_obj", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper, ImportHelper
+
+
+class ImportOBJ(bpy.types.Operator, ImportHelper):
+ '''Load a Wavefront OBJ File'''
+ bl_idname = "import_scene.obj"
+ bl_label = "Import OBJ"
+
+ filename_ext = ".obj"
+
+ CREATE_SMOOTH_GROUPS = BoolProperty(name="Smooth Groups", description="Surround smooth groups by sharp edges", default= True)
+ CREATE_FGONS = BoolProperty(name="NGons as FGons", description="Import faces with more then 4 verts as fgons", default= True)
+ CREATE_EDGES = BoolProperty(name="Lines as Edges", description="Import lines and faces with 2 verts as edge", default= True)
+ SPLIT_OBJECTS = BoolProperty(name="Object", description="Import OBJ Objects into Blender Objects", default= True)
+ SPLIT_GROUPS = BoolProperty(name="Group", description="Import OBJ Groups into Blender Objects", default= True)
+ # old comment: only used for user feedback
+ # disabled this option because in old code a handler for it disabled SPLIT* params, it's not passed to load_obj
+ # KEEP_VERT_ORDER = BoolProperty(name="Keep Vert Order", description="Keep vert and face order, disables split options, enable for morph targets", default= True)
+ ROTATE_X90 = BoolProperty(name="-X90", description="Rotate X 90.", default= True)
+ CLAMP_SIZE = FloatProperty(name="Clamp Scale", description="Clamp the size to this maximum (Zero to Disable)", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=0.0)
+ POLYGROUPS = BoolProperty(name="Poly Groups", description="Import OBJ groups as vertex groups.", default= True)
+ IMAGE_SEARCH = BoolProperty(name="Image Search", description="Search subdirs for any assosiated images (Warning, may be slow)", default= True)
+
+
+ def execute(self, context):
+ # print("Selected: " + context.active_object.name)
+ import io_scene_obj.import_obj
+ return io_scene_obj.import_obj.load(self, context, **self.properties)
+ '''
+ load_obj(self.properties.filepath,
+ context,
+ self.properties.CLAMP_SIZE,
+ self.properties.CREATE_FGONS,
+ self.properties.CREATE_SMOOTH_GROUPS,
+ self.properties.CREATE_EDGES,
+ self.properties.SPLIT_OBJECTS,
+ self.properties.SPLIT_GROUPS,
+ self.properties.ROTATE_X90,
+ self.properties.IMAGE_SEARCH,
+ self.properties.POLYGROUPS)
+ '''
+
+ return {'FINISHED'}
+
+
+class ExportOBJ(bpy.types.Operator, ExportHelper):
+ '''Save a Wavefront OBJ File'''
+
+ bl_idname = "export_scene.obj"
+ bl_label = 'Export OBJ'
+
+ filename_ext = ".obj"
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+
+ # context group
+ use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default= False)
+ use_all_scenes = BoolProperty(name="All Scenes", description="", default= False)
+ use_animation = BoolProperty(name="Animation", description="", default= False)
+
+ # object group
+ use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers (preview resolution)", default= True)
+ use_rotate_x90 = BoolProperty(name="Rotate X90", description="", default= True)
+
+ # extra data group
+ use_edges = BoolProperty(name="Edges", description="", default=True)
+ use_normals = BoolProperty(name="Normals", description="", default=False)
+ use_hq_normals = BoolProperty(name="High Quality Normals", description="", default=True)
+ use_uvs = BoolProperty(name="UVs", description="", default= True)
+ use_materials = BoolProperty(name="Materials", description="", default=True)
+ copy_images = BoolProperty(name="Copy Images", description="", default=False)
+ use_triangles = BoolProperty(name="Triangulate", description="", default=False)
+ use_vertex_groups = BoolProperty(name="Polygroups", description="", default=False)
+ use_nurbs = BoolProperty(name="Nurbs", description="", default=False)
+
+ # grouping group
+ use_blen_objects = BoolProperty(name="Objects as OBJ Objects", description="", default= True)
+ group_by_object = BoolProperty(name="Objects as OBJ Groups ", description="", default= False)
+ group_by_material = BoolProperty(name="Material Groups", description="", default= False)
+ keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default= False)
+
+
+ def execute(self, context):
+ import io_scene_obj.export_obj
+ print(self.properties.keys())
+ return io_scene_obj.export_obj.save(self, context, **self.properties)
+
+
+def menu_func_import(self, context):
+ self.layout.operator(ImportOBJ.bl_idname, text="Wavefront (.obj)")
+
+
+def menu_func_export(self, context):
+ self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)")
+
+
+def register():
+ bpy.types.INFO_MT_file_import.append(menu_func_import)
+ bpy.types.INFO_MT_file_export.append(menu_func_export)
+
+def unregister():
+ bpy.types.INFO_MT_file_import.remove(menu_func_import)
+ bpy.types.INFO_MT_file_export.remove(menu_func_export)
+
+
+# CONVERSION ISSUES
+# - matrix problem
+# - duplis - only tested dupliverts
+# - all scenes export
+# + normals calculation
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_scene_obj/export_obj.py b/release/scripts/op/io_scene_obj/export_obj.py
index 2265177c85a..01f5b221546 100644
--- a/release/scripts/op/io_scene_obj/export_obj.py
+++ b/release/scripts/op/io_scene_obj/export_obj.py
@@ -734,7 +734,8 @@ def write_file(filepath, objects, scene,
print("OBJ Export time: %.2f" % (time.clock() - time1))
-def write(filepath, context,
+#
+def _write(context, filepath,
EXPORT_TRI, # ok
EXPORT_EDGES,
EXPORT_NORMALS, # not yet
@@ -760,7 +761,7 @@ def write(filepath, context,
orig_scene = context.scene
# Exit edit mode before exporting, so current object states are exported properly.
- if context.object:
+ if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# if EXPORT_ALL_SCENES:
@@ -831,98 +832,51 @@ def write(filepath, context,
'''
Currently the exporter lacks these features:
-* nurbs
* multiple scene export (only active scene is written)
* particles
'''
-from bpy.props import *
-from io_utils import ExportHelper
-
-class ExportOBJ(bpy.types.Operator, ExportHelper):
- '''Save a Wavefront OBJ File'''
-
- bl_idname = "export.obj"
- bl_label = 'Export OBJ'
-
- filename_ext = ".obj"
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- # context group
- use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default= False)
- use_all_scenes = BoolProperty(name="All Scenes", description="", default= False)
- use_animation = BoolProperty(name="Animation", description="", default= False)
-
- # object group
- use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers (preview resolution)", default= True)
- use_rotate90 = BoolProperty(name="Rotate X90", description="", default= True)
-
- # extra data group
- use_edges = BoolProperty(name="Edges", description="", default=True)
- use_normals = BoolProperty(name="Normals", description="", default=False)
- use_hq_normals = BoolProperty(name="High Quality Normals", description="", default=True)
- use_uvs = BoolProperty(name="UVs", description="", default= True)
- use_materials = BoolProperty(name="Materials", description="", default=True)
- copy_images = BoolProperty(name="Copy Images", description="", default=False)
- use_triangles = BoolProperty(name="Triangulate", description="", default=False)
- use_vertex_groups = BoolProperty(name="Polygroups", description="", default=False)
- use_nurbs = BoolProperty(name="Nurbs", description="", default=False)
-
- # grouping group
- use_blen_objects = BoolProperty(name="Objects as OBJ Objects", description="", default= True)
- group_by_object = BoolProperty(name="Objects as OBJ Groups ", description="", default= False)
- group_by_material = BoolProperty(name="Material Groups", description="", default= False)
- keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default= False)
-
-
- def execute(self, context):
-
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- write(filepath, context,
- EXPORT_TRI=self.properties.use_triangles,
- EXPORT_EDGES=self.properties.use_edges,
- EXPORT_NORMALS=self.properties.use_normals,
- EXPORT_NORMALS_HQ=self.properties.use_hq_normals,
- EXPORT_UV=self.properties.use_uvs,
- EXPORT_MTL=self.properties.use_materials,
- EXPORT_COPY_IMAGES=self.properties.copy_images,
- EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
- EXPORT_ROTX90=self.properties.use_rotate90,
- EXPORT_BLEN_OBS=self.properties.use_blen_objects,
- EXPORT_GROUP_BY_OB=self.properties.group_by_object,
- EXPORT_GROUP_BY_MAT=self.properties.group_by_material,
- EXPORT_KEEP_VERT_ORDER=self.properties.keep_vertex_order,
- EXPORT_POLYGROUPS=self.properties.use_vertex_groups,
- EXPORT_CURVE_AS_NURBS=self.properties.use_nurbs,
- EXPORT_SEL_ONLY=self.properties.use_selection,
- EXPORT_ALL_SCENES=self.properties.use_all_scenes,
- EXPORT_ANIMATION=self.properties.use_animation)
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-
-# CONVERSION ISSUES
-# - matrix problem
-# - duplis - only tested dupliverts
-# - NURBS - needs API additions
-# - all scenes export
-# + normals calculation
-
-if __name__ == "__main__":
- register()
+def save(operator, context, filepath="",
+ use_triangles=False,
+ use_edges=False,
+ use_normals=False,
+ use_hq_normals=False,
+ use_uvs=True,
+ use_materials=True,
+ copy_images=False,
+ use_modifiers=True,
+ use_rotate_x90=True,
+ use_blen_objects=True,
+ group_by_object=False,
+ group_by_material=False,
+ keep_vertex_order=False,
+ use_vertex_groups=False,
+ use_nurbs=True,
+ use_selection=True,
+ use_all_scenes=False,
+ use_animation=False,
+ ):
+
+ _write(context, filepath,
+ EXPORT_TRI=use_triangles,
+ EXPORT_EDGES=use_edges,
+ EXPORT_NORMALS=use_normals,
+ EXPORT_NORMALS_HQ=use_hq_normals,
+ EXPORT_UV=use_uvs,
+ EXPORT_MTL=use_materials,
+ EXPORT_COPY_IMAGES=copy_images,
+ EXPORT_APPLY_MODIFIERS=use_modifiers,
+ EXPORT_ROTX90=use_rotate_x90,
+ EXPORT_BLEN_OBS=use_blen_objects,
+ EXPORT_GROUP_BY_OB=group_by_object,
+ EXPORT_GROUP_BY_MAT=group_by_material,
+ EXPORT_KEEP_VERT_ORDER=keep_vertex_order,
+ EXPORT_POLYGROUPS=use_vertex_groups,
+ EXPORT_CURVE_AS_NURBS=use_nurbs,
+ EXPORT_SEL_ONLY=use_selection,
+ EXPORT_ALL_SCENES=use_all_scenes,
+ EXPORT_ANIMATION=use_animation,
+ )
+
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_scene_obj/import_obj.py b/release/scripts/op/io_scene_obj/import_obj.py
index ab3c6ac19ca..441a11a5f6e 100644
--- a/release/scripts/op/io_scene_obj/import_obj.py
+++ b/release/scripts/op/io_scene_obj/import_obj.py
@@ -36,30 +36,8 @@ import time
import bpy
import mathutils
from geometry import PolyFill
+from io_utils import load_image, unpack_list, unpack_face_list
-def unpack_list(list_of_tuples):
- l = []
- for t in list_of_tuples:
- l.extend(t)
- return l
-
-# same as above except that it adds 0 for triangle faces
-def unpack_face_list(list_of_tuples):
- # allocate the entire list
- flat_ls = [0] * (len(list_of_tuples) * 4)
- i = 0
-
- for t in list_of_tuples:
- if len(t) == 3:
- if t[2] == 0:
- t = t[1], t[2], t[0]
- else: # assuem quad
- if t[3] == 0 or t[2] == 0:
- t = t[2], t[3], t[0], t[1]
-
- flat_ls[i:i + len(t)] = t
- i += 4
- return flat_ls
def BPyMesh_ngon(from_data, indices, PREF_FIX_LOOPS= True):
'''
@@ -260,21 +238,6 @@ def line_value(line_split):
elif length > 2:
return ' '.join( line_split[1:] )
-# limited replacement for BPyImage.comprehensiveImageLoad
-def load_image(imagepath, dirname):
-
- if os.path.exists(imagepath):
- return bpy.data.images.load(imagepath)
-
- variants = [imagepath, os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
-
- for filepath in variants:
- for nfilepath in (filepath, bpy.path.resolve_ncase(filepath)):
- if os.path.exists(nfilepath):
- return bpy.data.images.load(nfilepath)
-
- # TODO comprehensiveImageLoad also searched in bpy.config.textureDir
- return None
def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
if '_' in imagepath:
@@ -874,17 +837,16 @@ def get_float_func(filepath):
# incase all vert values were ints
return float
-def load_obj(filepath,
- context,
- CLAMP_SIZE= 0.0,
- CREATE_FGONS= True,
- CREATE_SMOOTH_GROUPS= True,
- CREATE_EDGES= True,
- SPLIT_OBJECTS= True,
- SPLIT_GROUPS= True,
- ROTATE_X90= True,
- IMAGE_SEARCH=True,
- POLYGROUPS=False):
+def load(operator, context, filepath,
+ CLAMP_SIZE= 0.0,
+ CREATE_FGONS= True,
+ CREATE_SMOOTH_GROUPS= True,
+ CREATE_EDGES= True,
+ SPLIT_OBJECTS= True,
+ SPLIT_GROUPS= True,
+ ROTATE_X90= True,
+ IMAGE_SEARCH=True,
+ POLYGROUPS=False):
'''
Called by the user interface or another script.
load_obj(path) - should give acceptable results.
@@ -1218,295 +1180,8 @@ def load_obj(filepath,
time_new= time.time()
# time_new= sys.time()
- print('%.4f sec' % (time_new-time_sub))
print('finished importing: %r in %.4f sec.' % (filepath, (time_new-time_main)))
-
-
-DEBUG= True
-
-
-def load_obj_ui(filepath, BATCH_LOAD= False):
- if BPyMessages.Error_NoFile(filepath):
- return
-
- global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
-
- CREATE_SMOOTH_GROUPS= Draw.Create(0)
- CREATE_FGONS= Draw.Create(1)
- CREATE_EDGES= Draw.Create(1)
- SPLIT_OBJECTS= Draw.Create(0)
- SPLIT_GROUPS= Draw.Create(0)
- CLAMP_SIZE= Draw.Create(10.0)
- IMAGE_SEARCH= Draw.Create(1)
- POLYGROUPS= Draw.Create(0)
- KEEP_VERT_ORDER= Draw.Create(1)
- ROTATE_X90= Draw.Create(1)
-
-
- # Get USER Options
- # Note, Works but not pretty, instead use a more complicated GUI
- '''
- pup_block= [\
- 'Import...',\
- ('Smooth Groups', CREATE_SMOOTH_GROUPS, 'Surround smooth groups by sharp edges'),\
- ('Create FGons', CREATE_FGONS, 'Import faces with more then 4 verts as fgons.'),\
- ('Lines', CREATE_EDGES, 'Import lines and faces with 2 verts as edges'),\
- 'Separate objects from obj...',\
- ('Object', SPLIT_OBJECTS, 'Import OBJ Objects into Blender Objects'),\
- ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\
- 'Options...',\
- ('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\
- ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\
- ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
- ]
-
- if not Draw.PupBlock('Import OBJ...', pup_block):
- return
-
- if KEEP_VERT_ORDER.val:
- SPLIT_OBJECTS.val = False
- SPLIT_GROUPS.val = False
- '''
-
-
-
- # BEGIN ALTERNATIVE UI *******************
- if True:
-
- EVENT_NONE = 0
- EVENT_EXIT = 1
- EVENT_REDRAW = 2
- EVENT_IMPORT = 3
-
- GLOBALS = {}
- GLOBALS['EVENT'] = EVENT_REDRAW
- #GLOBALS['MOUSE'] = Window.GetMouseCoords()
- GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
-
- def obj_ui_set_event(e,v):
- GLOBALS['EVENT'] = e
-
- def do_split(e,v):
- global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER, POLYGROUPS
- if SPLIT_OBJECTS.val or SPLIT_GROUPS.val:
- KEEP_VERT_ORDER.val = 0
- POLYGROUPS.val = 0
- else:
- KEEP_VERT_ORDER.val = 1
-
- def do_vertorder(e,v):
- global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER
- if KEEP_VERT_ORDER.val:
- SPLIT_OBJECTS.val = SPLIT_GROUPS.val = 0
- else:
- if not (SPLIT_OBJECTS.val or SPLIT_GROUPS.val):
- KEEP_VERT_ORDER.val = 1
-
- def do_polygroups(e,v):
- global SPLIT_OBJECTS, SPLIT_GROUPS, KEEP_VERT_ORDER, POLYGROUPS
- if POLYGROUPS.val:
- SPLIT_OBJECTS.val = SPLIT_GROUPS.val = 0
-
- def do_help(e,v):
- url = __url__[0]
- print('Trying to open web browser with documentation at this address...')
- print('\t' + url)
-
- try:
- import webbrowser
- webbrowser.open(url)
- except:
- print('...could not open a browser window.')
-
- def obj_ui():
- ui_x, ui_y = GLOBALS['MOUSE']
-
- # Center based on overall pup size
- ui_x -= 165
- ui_y -= 90
-
- global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
-
- Draw.Label('Import...', ui_x+9, ui_y+159, 220, 21)
- Draw.BeginAlign()
- CREATE_SMOOTH_GROUPS = Draw.Toggle('Smooth Groups', EVENT_NONE, ui_x+9, ui_y+139, 110, 20, CREATE_SMOOTH_GROUPS.val, 'Surround smooth groups by sharp edges')
- CREATE_FGONS = Draw.Toggle('NGons as FGons', EVENT_NONE, ui_x+119, ui_y+139, 110, 20, CREATE_FGONS.val, 'Import faces with more then 4 verts as fgons')
- CREATE_EDGES = Draw.Toggle('Lines as Edges', EVENT_NONE, ui_x+229, ui_y+139, 110, 20, CREATE_EDGES.val, 'Import lines and faces with 2 verts as edges')
- Draw.EndAlign()
-
- Draw.Label('Separate objects by OBJ...', ui_x+9, ui_y+110, 220, 20)
- Draw.BeginAlign()
- SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 55, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split)
- SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+64, ui_y+89, 55, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split)
- Draw.EndAlign()
-
- # Only used for user feedback
- KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+184, ui_y+89, 113, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder)
-
- ROTATE_X90 = Draw.Toggle('-X90', EVENT_REDRAW, ui_x+302, ui_y+89, 38, 21, ROTATE_X90.val, 'Rotate X 90.')
-
- Draw.Label('Options...', ui_x+9, ui_y+60, 211, 20)
- CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 130, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)')
- POLYGROUPS = Draw.Toggle('Poly Groups', EVENT_REDRAW, ui_x+144, ui_y+39, 90, 21, POLYGROUPS.val, 'Import OBJ groups as vertex groups.', do_polygroups)
- IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+239, ui_y+39, 100, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)')
- Draw.BeginAlign()
- Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 21, 'Load the wiki page for this script', do_help)
- Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 21, '', obj_ui_set_event)
- Draw.PushButton('Import', EVENT_IMPORT, ui_x+229, ui_y+9, 110, 21, 'Import with these settings', obj_ui_set_event)
- Draw.EndAlign()
-
-
- # hack so the toggle buttons redraw. this is not nice at all
- while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_IMPORT):
- Draw.UIBlock(obj_ui, 0)
-
- if GLOBALS['EVENT'] != EVENT_IMPORT:
- return
-
- # END ALTERNATIVE UI *********************
-
-
-
-
-
-
-
- Window.WaitCursor(1)
-
- if BATCH_LOAD: # load the dir
- try:
- files= [ f for f in os.listdir(filepath) if f.lower().endswith('.obj') ]
- except:
- Window.WaitCursor(0)
- Draw.PupMenu('Error%t|Could not open path ' + filepath)
- return
-
- if not files:
- Window.WaitCursor(0)
- Draw.PupMenu('Error%t|No files at path ' + filepath)
- return
-
- for f in files:
- scn= bpy.data.scenes.new(os.path.splitext(f)[0])
- scn.makeCurrent()
-
- load_obj(sys.join(filepath, f),\
- CLAMP_SIZE.val,\
- CREATE_FGONS.val,\
- CREATE_SMOOTH_GROUPS.val,\
- CREATE_EDGES.val,\
- SPLIT_OBJECTS.val,\
- SPLIT_GROUPS.val,\
- ROTATE_X90.val,\
- IMAGE_SEARCH.val,\
- POLYGROUPS.val
- )
-
- else: # Normal load
- load_obj(filepath,\
- CLAMP_SIZE.val,\
- CREATE_FGONS.val,\
- CREATE_SMOOTH_GROUPS.val,\
- CREATE_EDGES.val,\
- SPLIT_OBJECTS.val,\
- SPLIT_GROUPS.val,\
- ROTATE_X90.val,\
- IMAGE_SEARCH.val,\
- POLYGROUPS.val
- )
-
- Window.WaitCursor(0)
-
-
-def load_obj_ui_batch(file):
- load_obj_ui(file, True)
-
-DEBUG= False
-
-# if __name__=='__main__' and not DEBUG:
-# if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT:
-# Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '')
-# else:
-# Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
-
- # For testing compatibility
-'''
-else:
- # DEBUG ONLY
- TIME= sys.time()
- DIR = '/fe/obj'
- import os
- print 'Searching for files'
- def fileList(path):
- for dirpath, dirnames, filenames in os.walk(path):
- for filename in filenames:
- yield os.path.join(dirpath, filename)
-
- files = [f for f in fileList(DIR) if f.lower().endswith('.obj')]
- files.sort()
-
- for i, obj_file in enumerate(files):
- if 0 < i < 20:
- print 'Importing', obj_file, '\nNUMBER', i, 'of', len(files)
- newScn= bpy.data.scenes.new(os.path.basename(obj_file))
- newScn.makeCurrent()
- load_obj(obj_file, False, IMAGE_SEARCH=0)
-
- print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
-'''
-
-from bpy.props import *
-from io_utils import ImportHelper
-
-
-class IMPORT_OT_obj(bpy.types.Operator, ImportHelper):
- '''Load a Wavefront OBJ File'''
- bl_idname = "import_scene.obj"
- bl_label = "Import OBJ"
-
- filename_ext = ".obj"
-
- CREATE_SMOOTH_GROUPS = BoolProperty(name="Smooth Groups", description="Surround smooth groups by sharp edges", default= True)
- CREATE_FGONS = BoolProperty(name="NGons as FGons", description="Import faces with more then 4 verts as fgons", default= True)
- CREATE_EDGES = BoolProperty(name="Lines as Edges", description="Import lines and faces with 2 verts as edge", default= True)
- SPLIT_OBJECTS = BoolProperty(name="Object", description="Import OBJ Objects into Blender Objects", default= True)
- SPLIT_GROUPS = BoolProperty(name="Group", description="Import OBJ Groups into Blender Objects", default= True)
- # old comment: only used for user feedback
- # disabled this option because in old code a handler for it disabled SPLIT* params, it's not passed to load_obj
- # KEEP_VERT_ORDER = BoolProperty(name="Keep Vert Order", description="Keep vert and face order, disables split options, enable for morph targets", default= True)
- ROTATE_X90 = BoolProperty(name="-X90", description="Rotate X 90.", default= True)
- CLAMP_SIZE = FloatProperty(name="Clamp Scale", description="Clamp the size to this maximum (Zero to Disable)", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=0.0)
- POLYGROUPS = BoolProperty(name="Poly Groups", description="Import OBJ groups as vertex groups.", default= True)
- IMAGE_SEARCH = BoolProperty(name="Image Search", description="Search subdirs for any assosiated images (Warning, may be slow)", default= True)
-
-
- def execute(self, context):
- # print("Selected: " + context.active_object.name)
-
- load_obj(self.properties.filepath,
- context,
- self.properties.CLAMP_SIZE,
- self.properties.CREATE_FGONS,
- self.properties.CREATE_SMOOTH_GROUPS,
- self.properties.CREATE_EDGES,
- self.properties.SPLIT_OBJECTS,
- self.properties.SPLIT_GROUPS,
- self.properties.ROTATE_X90,
- self.properties.IMAGE_SEARCH,
- self.properties.POLYGROUPS)
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)")
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
+ return {'FINISHED'}
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file)
diff --git a/release/scripts/op/io_scene_x3d/__init__.py b/release/scripts/op/io_scene_x3d/__init__.py
new file mode 100644
index 00000000000..4ccd29808bf
--- /dev/null
+++ b/release/scripts/op/io_scene_x3d/__init__.py
@@ -0,0 +1,61 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ # only reload if we alredy loaded, highly annoying
+ import sys
+ reload(sys.modules.get("io_scene_x3d.export_x3d", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper
+
+
+class ExportX3D(bpy.types.Operator, ExportHelper):
+ '''Export selection to Extensible 3D file (.x3d)'''
+ bl_idname = "export_scene.x3d"
+ bl_label = 'Export X3D'
+
+ filename_ext = ".x3d"
+
+ use_apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
+ use_triangulate = BoolProperty(name="Triangulate", description="Triangulate quads.", default=False)
+ use_compress = BoolProperty(name="Compress", description="GZip the resulting file, requires a full python install", default=False)
+
+ def execute(self, context):
+ import io_scene_x3d.export_x3d
+ return io_scene_x3d.export_x3d.save(self, context, **self.properties)
+
+
+def menu_func(self, context):
+ self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)")
+
+
+def register():
+ bpy.types.INFO_MT_file_export.append(menu_func)
+
+def unregister():
+ bpy.types.INFO_MT_file_export.remove(menu_func)
+
+# NOTES
+# - blender version is hardcoded
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_scene_x3d/export_x3d.py b/release/scripts/op/io_scene_x3d/export_x3d.py
index 9dc9c6cb981..dd8b9b2c5f6 100644
--- a/release/scripts/op/io_scene_x3d/export_x3d.py
+++ b/release/scripts/op/io_scene_x3d/export_x3d.py
@@ -48,8 +48,7 @@ MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X')
# Global Variables
####################################
-filename = ""
-# filename = Blender.Get('filename')
+filepath = ""
_safeOverwrite = True
extension = ''
@@ -60,7 +59,7 @@ extension = ''
class x3d_class:
- def __init__(self, filename):
+ def __init__(self, filepath):
#--- public you can change these ---
self.writingcolor = 0
self.writingtexture = 0
@@ -83,18 +82,18 @@ class x3d_class:
self.matNames={} # dictionary of materiaNames
self.meshNames={} # dictionary of meshNames
self.indentLevel=0 # keeps track of current indenting
- self.filename=filename
+ self.filepath=filepath
self.file = None
- if filename.lower().endswith('.x3dz'):
+ if filepath.lower().endswith('.x3dz'):
try:
import gzip
- self.file = gzip.open(filename, "w")
+ self.file = gzip.open(filepath, "w")
except:
print("failed to import compression modules, exporting uncompressed")
- self.filename = filename[:-1] # remove trailing z
+ self.filepath = filepath[:-1] # remove trailing z
if self.file == None:
- self.file = open(self.filename, "w")
+ self.file = open(self.filepath, "w")
self.bNav=0
self.nodeID=0
@@ -136,8 +135,8 @@ class x3d_class:
##########################################################
def writeHeader(self):
- #bfile = sys.expandpath( Blender.Get('filename') ).replace('<', '&lt').replace('>', '&gt')
- bfile = self.filename.replace('<', '&lt').replace('>', '&gt') # use outfile name
+ #bfile = sys.expandpath( Blender.Get('filepath') ).replace('<', '&lt').replace('>', '&gt')
+ bfile = self.filepath.replace('<', '&lt').replace('>', '&gt') # use outfile name
self.file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
self.file.write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n")
self.file.write("<X3D version=\"3.0\" profile=\"Immersive\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\">\n")
@@ -426,6 +425,7 @@ class x3d_class:
self.writeIndented("<Appearance>\n", 1)
# right now this script can only handle a single material per mesh.
if len(maters) >= 1 and maters[0].use_face_texture == False:
+ mat = maters[0]
self.writeMaterial(mat, self.cleanStr(mat.name,''), world)
if len(maters) > 1:
print("Warning: mesh named %s has multiple materials" % meshName)
@@ -672,13 +672,13 @@ class x3d_class:
def writeImageTexture(self, image):
name = image.name
- filename = os.path.basename(image.filepath)
+ filepath = os.path.basename(image.filepath)
if name in self.texNames:
self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name))
self.texNames[name] += 1
else:
self.writeIndented("<ImageTexture DEF=\"%s\" " % self.cleanStr(name), 1)
- self.file.write("url=\"%s\" />" % filename)
+ self.file.write("url=\"%s\" />" % filepath)
self.writeIndented("\n",-1)
self.texNames[name] = 1
@@ -781,7 +781,7 @@ class x3d_class:
EXPORT_TRI= False,\
):
- print("Info: starting X3D export to " + self.filename + "...")
+ print("Info: starting X3D export to " + self.filepath + "...")
self.writeHeader()
# self.writeScript()
self.writeNavigationInfo(scene)
@@ -879,7 +879,7 @@ class x3d_class:
self.texNames={}
self.matNames={}
self.indentLevel=0
- print("Info: finished X3D export to %s\n" % self.filename)
+ print("Info: finished X3D export to %s\n" % self.filepath)
def cleanStr(self, name, prefix='rsvd_'):
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
@@ -1089,82 +1089,35 @@ class x3d_class:
# Callbacks, needed before Main
##########################################################
-def write(filename,
- context,
- EXPORT_APPLY_MODIFIERS=False,
- EXPORT_TRI=False,
- EXPORT_GZIP=False):
+def save(operator, context, filepath="",
+ use_apply_modifiers=False,
+ use_triangulate=False,
+ use_compress=False):
- if EXPORT_GZIP:
- if not filename.lower().endswith('.x3dz'):
- filename = '.'.join(filename.split('.')[:-1]) + '.x3dz'
+ if use_compress:
+ if not filepath.lower().endswith('.x3dz'):
+ filepath = '.'.join(filepath.split('.')[:-1]) + '.x3dz'
else:
- if not filename.lower().endswith('.x3d'):
- filename = '.'.join(filename.split('.')[:-1]) + '.x3d'
-
+ if not filepath.lower().endswith('.x3d'):
+ filepath = '.'.join(filepath.split('.')[:-1]) + '.x3d'
scene = context.scene
world = scene.world
- if scene.objects.active:
+ if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
# XXX these are global textures while .Get() returned only scene's?
alltextures = bpy.data.textures
# alltextures = Blender.Texture.Get()
- wrlexport=x3d_class(filename)
- wrlexport.export(\
- scene,\
- world,\
- alltextures,\
- \
- EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS,\
- EXPORT_TRI = EXPORT_TRI,\
- )
-
-
-from bpy.props import *
-from io_utils import ExportHelper
-
-
-class ExportX3D(bpy.types.Operator, ExportHelper):
- '''Export selection to Extensible 3D file (.x3d)'''
- bl_idname = "export.x3d"
- bl_label = 'Export X3D'
-
- filename_ext = ".x3d"
-
- apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
- triangulate = BoolProperty(name="Triangulate", description="Triangulate quads.", default=False)
- compress = BoolProperty(name="Compress", description="GZip the resulting file, requires a full python install", default=False)
-
- def execute(self, context):
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- write(filepath,
- context,
- self.properties.apply_modifiers,
- self.properties.triangulate,
- self.properties.compress,
- )
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
+ wrlexport = x3d_class(filepath)
+ wrlexport.export(scene,
+ world,
+ alltextures,
+ EXPORT_APPLY_MODIFIERS=use_apply_modifiers,
+ EXPORT_TRI=use_triangulate,
+ )
-# NOTES
-# - blender version is hardcoded
+ return {'FINISHED'}
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/io_shape_mdd/__init__.py b/release/scripts/op/io_shape_mdd/__init__.py
new file mode 100644
index 00000000000..0af4af92b7c
--- /dev/null
+++ b/release/scripts/op/io_shape_mdd/__init__.py
@@ -0,0 +1,115 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+ # only reload if we alredy loaded, highly annoying
+ import sys
+ reload(sys.modules.get("io_shape_mdd.import_mdd", sys))
+ reload(sys.modules.get("io_shape_mdd.export_mdd", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper, ImportHelper
+
+
+class ImportMDD(bpy.types.Operator, ImportHelper):
+ '''Import MDD vertex keyframe file to shape keys'''
+ bl_idname = "import_shape.mdd"
+ bl_label = "Import MDD"
+
+ filename_ext = ".mdd"
+ frame_start = IntProperty(name="Start Frame", description="Start frame for inserting animation", min=-300000, max=300000, default=0)
+ frame_step = IntProperty(name="Step", min=1, max=1000, default=1)
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+
+ # initialize from scene if unset
+ scene = context.scene
+ if not self.properties.is_property_set("frame_start"):
+ self.properties.frame_start = scene.frame_current
+
+ import io_shape_mdd.import_mdd
+ return io_shape_mdd.import_mdd.load(self, context, **self.properties)
+
+class ExportMDD(bpy.types.Operator, ExportHelper):
+ '''Animated mesh to MDD vertex keyframe file'''
+ bl_idname = "export_shape.mdd"
+ bl_label = "Export MDD"
+
+ filename_ext = ".mdd"
+
+ # get first scene to get min and max properties for frames, fps
+
+ minframe = 1
+ maxframe = 300000
+ minfps = 1
+ maxfps = 120
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+ fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
+ frame_start = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1)
+ frame_end = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250)
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return (obj and obj.type == 'MESH')
+
+ def execute(self, context):
+ # initialize from scene if unset
+ scene = context.scene
+ if not self.properties.is_property_set("frame_start"):
+ self.properties.frame_start = scene.frame_start
+ if not self.properties.is_property_set("frame_end"):
+ self.properties.frame_end = scene.frame_end
+ if not self.properties.is_property_set("fps"):
+ self.properties.fps = scene.render.fps
+
+ import io_shape_mdd.export_mdd
+ return io_shape_mdd.export_mdd.save(self, context, **self.properties)
+
+
+def menu_func_import(self, context):
+ self.layout.operator(ImportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
+
+
+def menu_func_export(self, context):
+ self.layout.operator(ExportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
+
+
+def register():
+ bpy.types.INFO_MT_file_import.append(menu_func_import)
+ bpy.types.INFO_MT_file_export.append(menu_func_export)
+
+
+def unregister():
+ bpy.types.INFO_MT_file_import.remove(menu_func_import)
+ bpy.types.INFO_MT_file_export.remove(menu_func_export)
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/op/io_shape_mdd/export_mdd.py b/release/scripts/op/io_shape_mdd/export_mdd.py
index 91d75aaf445..1f0a5d94320 100644
--- a/release/scripts/op/io_shape_mdd/export_mdd.py
+++ b/release/scripts/op/io_shape_mdd/export_mdd.py
@@ -54,19 +54,23 @@ def check_vertcount(mesh, vertcount):
return
-def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
+def save(operator, context, filepath="", frame_start=1, frame_end=300, fps=25):
"""
Blender.Window.WaitCursor(1)
mesh_orig = Mesh.New()
- mesh_orig.getFromObject(ob.name)
+ mesh_orig.getFromObject(obj.name)
"""
- bpy.ops.object.mode_set(mode='OBJECT')
+ scene = context.scene
+ obj = context.object
- orig_frame = sce.frame_current
- sce.set_frame(PREF_STARTFRAME)
- me = ob.create_mesh(sce, True, 'PREVIEW')
+ if bpy.ops.object.mode_set.poll():
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ orig_frame = scene.frame_current
+ scene.set_frame(frame_start)
+ me = obj.create_mesh(scene, True, 'PREVIEW')
#Flip y and z
mat_flip = mathutils.Matrix(\
@@ -78,36 +82,36 @@ def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
numverts = len(me.vertices)
- numframes = PREF_ENDFRAME - PREF_STARTFRAME + 1
- PREF_FPS = float(PREF_FPS)
- f = open(filename, 'wb') #no Errors yet:Safe to create file
+ numframes = frame_end - frame_start + 1
+ fps = float(fps)
+ f = open(filepath, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
- f.write(pack(">%df" % (numframes), *[frame / PREF_FPS for frame in range(numframes)])) # seconds
+ f.write(pack(">%df" % (numframes), *[frame / fps for frame in range(numframes)])) # seconds
#rest frame needed to keep frames in sync
"""
- Blender.Set('curframe', PREF_STARTFRAME)
- me_tmp.getFromObject(ob.name)
+ Blender.Set('curframe', frame_start)
+ me_tmp.getFromObject(obj.name)
"""
check_vertcount(me, numverts)
- me.transform(mat_flip * ob.matrix_world)
+ me.transform(mat_flip * obj.matrix_world)
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
- for frame in range(PREF_STARTFRAME, PREF_ENDFRAME + 1):#in order to start at desired frame
+ for frame in range(frame_start, frame_end + 1):#in order to start at desired frame
"""
Blender.Set('curframe', frame)
- me_tmp.getFromObject(ob.name)
+ me_tmp.getFromObject(obj.name)
"""
- sce.set_frame(frame)
- me = ob.create_mesh(sce, True, 'PREVIEW')
+ scene.set_frame(frame)
+ me = obj.create_mesh(scene, True, 'PREVIEW')
check_vertcount(me, numverts)
- me.transform(mat_flip * ob.matrix_world)
+ me.transform(mat_flip * obj.matrix_world)
# Write the vertex data
f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co]))
@@ -117,67 +121,11 @@ def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
"""
f.close()
- print('MDD Exported: %s frames:%d\n' % (filename, numframes - 1))
+ print('MDD Exported: %r frames:%d\n' % (filepath, numframes - 1))
"""
Blender.Window.WaitCursor(0)
Blender.Set('curframe', orig_frame)
"""
- sce.set_frame(orig_frame)
-
-from bpy.props import *
-from io_utils import ExportHelper
-
-
-class ExportMDD(bpy.types.Operator, ExportHelper):
- '''Animated mesh to MDD vertex keyframe file'''
- bl_idname = "export.mdd"
- bl_label = "Export MDD"
+ scene.set_frame(orig_frame)
- filename_ext = ".mdd"
-
- # get first scene to get min and max properties for frames, fps
-
- minframe = 1
- maxframe = 300000
- minfps = 1
- maxfps = 120
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
- frame_start = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1)
- frame_end = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250)
-
- @classmethod
- def poll(cls, context):
- ob = context.active_object
- return (ob and ob.type == 'MESH')
-
- def execute(self, context):
- filepath = self.properties.filepath
- filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
-
- write(filepath,
- context.scene,
- context.active_object,
- self.properties.frame_start,
- self.properties.frame_end,
- self.properties.fps,
- )
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(ExportMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()
+ return {'FINISHED'}
diff --git a/release/scripts/op/io_shape_mdd/import_mdd.py b/release/scripts/op/io_shape_mdd/import_mdd.py
index ff67d3bf7f3..d008ff931ff 100644
--- a/release/scripts/op/io_shape_mdd/import_mdd.py
+++ b/release/scripts/op/io_shape_mdd/import_mdd.py
@@ -35,11 +35,15 @@ import bpy
from struct import unpack
-def mdd_import(filepath, ob, scene, PREF_START_FRAME=0, PREF_JUMP=1):
+def load(operator, context, filepath, frame_start=0, frame_step=1):
+
+ scene = context.scene
+ obj = context.object
+
+ print('\n\nimporting mdd %r' % filepath)
- print('\n\nimporting mdd "%s"' % filepath)
-
- bpy.ops.object.mode_set(mode='OBJECT')
+ if bpy.ops.object.mode_set.poll():
+ bpy.ops.object.mode_set(mode='OBJECT')
file = open(filepath, 'rb')
frames, points = unpack(">2i", file.read(8))
@@ -49,92 +53,53 @@ def mdd_import(filepath, ob, scene, PREF_START_FRAME=0, PREF_JUMP=1):
# If target object doesn't have Basis shape key, create it.
try:
- num_keys = len(ob.data.shape_keys.keys)
+ num_keys = len(obj.data.shape_keys.keys)
except:
- basis = ob.add_shape_key()
+ basis = obj.add_shape_key()
basis.name = "Basis"
- ob.data.update()
+ obj.data.update()
- scene.frame_current = PREF_START_FRAME
+ scene.frame_current = frame_start
def UpdateMesh(ob, fr):
# Insert new shape key
- new_shapekey = ob.add_shape_key()
+ new_shapekey = obj.add_shape_key()
new_shapekey.name = ("frame_%.4d" % fr)
new_shapekey_name = new_shapekey.name
- ob.active_shape_key_index = len(ob.data.shape_keys.keys)-1
- index = len(ob.data.shape_keys.keys)-1
- ob.show_shape_key = True
+ obj.active_shape_key_index = len(obj.data.shape_keys.keys)-1
+ index = len(obj.data.shape_keys.keys)-1
+ obj.show_shape_key = True
- verts = ob.data.shape_keys.keys[len(ob.data.shape_keys.keys)-1].data
+ verts = obj.data.shape_keys.keys[len(obj.data.shape_keys.keys)-1].data
for v in verts: # 12 is the size of 3 floats
v.co[:] = unpack('>3f', file.read(12))
#me.update()
- ob.show_shape_key = False
+ obj.show_shape_key = False
# insert keyframes
- shape_keys = ob.data.shape_keys
+ shape_keys = obj.data.shape_keys
scene.frame_current -= 1
- ob.data.shape_keys.keys[index].value = 0.0
- shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
+ obj.data.shape_keys.keys[index].value = 0.0
+ shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
- ob.data.shape_keys.keys[index].value = 1.0
- shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
+ obj.data.shape_keys.keys[index].value = 1.0
+ shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
scene.frame_current += 1
- ob.data.shape_keys.keys[index].value = 0.0
- shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
+ obj.data.shape_keys.keys[index].value = 0.0
+ shape_keys.keys[len(obj.data.shape_keys.keys)-1].keyframe_insert("value")
- ob.data.update()
+ obj.data.update()
for i in range(frames):
- UpdateMesh(ob, i)
-
-
-from bpy.props import *
-from io_utils import ImportHelper
-
-
-class importMDD(bpy.types.Operator, ImportHelper):
- '''Import MDD vertex keyframe file to shape keys'''
- bl_idname = "import_shape.mdd"
- bl_label = "Import MDD"
-
- filename_ext = ".mdd"
- frame_start = IntProperty(name="Start Frame", description="Start frame for inserting animation", min=-300000, max=300000, default=0)
-
- @classmethod
- def poll(cls, context):
- ob = context.active_object
- return (ob and ob.type == 'MESH')
-
- def execute(self, context):
- if not self.properties.filepath:
- raise Exception("filename not set")
-
- mdd_import(self.properties.filepath, bpy.context.active_object, context.scene, self.properties.frame_start, 1)
-
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(importMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
+ UpdateMesh(obj, i)
-if __name__ == "__main__":
- register()
+ return {'FINISHED'}