diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 162e30de82f81bae895966e88e34e0974a637345..bf7bd9909149841038a1edda11135d649b12a87b 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -893,6 +893,7 @@ def save(operator, context, filepath="", import bpy import time + import io_utils from io_utils import create_derived_objects, free_derived_objects '''Save the Blender scene to a 3ds file.''' @@ -901,8 +902,6 @@ def save(operator, context, filepath="", time1 = time.clock() # Blender.Window.WaitCursor(1) - sce = context.scene - if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') @@ -921,15 +920,11 @@ def save(operator, context, filepath="", kfdata = make_kfdata() ''' - # Get all the supported objects selected in this scene: - # ob_sel= list(sce.objects.context) - # mesh_objects = [ (ob, me) for ob in ob_sel for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ] - # empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ] - # Make a list of all materials used in the selected meshes (use a dictionary, # each material is added once): materialDict = {} mesh_objects = [] + scene = context.scene if use_selection: diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index 191f5824fdc80af82ef6be48c1eab8a776335131..54433a6506b31767ddb64d7332607601ea5aac88 100644 --- a/io_scene_fbx/__init__.py +++ b/io_scene_fbx/__init__.py @@ -41,6 +41,7 @@ if "bpy" in locals(): import bpy from bpy.props import StringProperty, BoolProperty, FloatProperty, EnumProperty +import io_utils from io_utils import ExportHelper @@ -69,7 +70,6 @@ class ExportFBX(bpy.types.Operator, ExportHelper): 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) @@ -87,6 +87,8 @@ class ExportFBX(bpy.types.Operator, ExportHelper): BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True) use_metadata = BoolProperty(name="Use Metadata", default=True, options={'HIDDEN'}) + path_mode = io_utils.path_reference_mode + @property def check_extension(self): return self.batch_mode == 'OFF' diff --git a/io_scene_fbx/export_fbx.py b/io_scene_fbx/export_fbx.py index c4b03ddbd2ac6da7287ab44c1c66e747c366fb6a..8c533d82121a8b4b4d400361c3fc547514eb08b5 100644 --- a/io_scene_fbx/export_fbx.py +++ b/io_scene_fbx/export_fbx.py @@ -35,34 +35,6 @@ import bpy from mathutils import Vector, Matrix -# 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 - - image_paths = set() - for tex in textures: - image_paths.add(bpy.path.abspath(tex.filepath)) - - # Now copy images - copyCount = 0 - for image_path in image_paths: - if Blender.sys.exists(image_path): - # 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 %r > %r" % (image_path, dest_image_path)) - try: - shutil.copy(image_path, dest_image_path) - copyCount += 1 - except: - print("\t\tWarning, file failed to copy, skipping.") - - print('\tCopied %d images' % copyCount) - - # I guess FBX uses degrees instead of radians (Arystan). # Call this function just before writing to FBX. # 180 / math.pi == 57.295779513 @@ -157,25 +129,6 @@ def sane_takename(data): def sane_groupname(data): return sane_name(data, sane_name_mapping_group) -# def derived_paths(fname_orig, basepath, FORCE_CWD=False): -# ''' -# 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 filepath. -# use when we know the file will be in the basepath. -# ''' -# fname = bpy.path.abspath(fname_orig) -# # fname = Blender.sys.expandpath(fname_orig) -# fname_strip = os.path.basename(fname) -# # fname_strip = strip_path(fname) -# if FORCE_CWD: -# fname_rel = '.' + os.sep + fname_strip -# else: -# fname_rel = bpy.path.relpath(fname, basepath) -# # fname_rel = Blender.sys.relpath(fname, basepath) -# if fname_rel.startswith('//'): fname_rel = '.' + os.sep + fname_rel[2:] -# return fname, fname_strip, fname_rel - def mat4x4str(mat): return '%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f' % tuple([f for v in mat for f in v]) @@ -257,27 +210,28 @@ def save_single(operator, scene, filepath="", EXP_LAMP=True, EXP_CAMERA=True, EXP_EMPTY=True, - EXP_IMAGE_COPY=False, ANIM_ENABLE=True, ANIM_OPTIMIZE=True, ANIM_OPTIMIZE_PRECISSION=6, ANIM_ACTION_ALL=False, use_metadata=True, + path_mode='AUTO', ): - # testing - mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X') # used + import io_utils + + mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X') mtx4_z90 = Matrix.Rotation(math.pi / 2.0, 4, 'Z') if GLOBAL_MATRIX is None: GLOBAL_MATRIX = Matrix() - # end batch support - # Use this for working out paths relative to the export location - basepath = os.path.dirname(filepath) or '.' - basepath += os.sep -# basepath = Blender.sys.dirname(filepath) + base_src = os.path.dirname(bpy.data.filepath) + base_dst = os.path.dirname(filepath) + + # collect images to copy + copy_set = set() # ---------------------------------------------- # storage classes @@ -1139,22 +1093,6 @@ def save_single(operator, scene, filepath="", file.write('\n\t\t}') file.write('\n\t}') - def copy_image(image): - fn = bpy.path.abspath(image.filepath) - fn_strip = os.path.basename(fn) - - if EXP_IMAGE_COPY: - rel = fn_strip - fn_abs_dest = os.path.join(basepath, fn_strip) - if not os.path.exists(fn_abs_dest): - shutil.copy(fn, fn_abs_dest) - elif bpy.path.is_subdir(fn, basepath): - rel = os.path.relpath(fn, basepath) - else: - rel = fn - - return (rel, fn_strip) - # tex is an Image (Arystan) def write_video(texname, tex): # Same as texture really! @@ -1168,10 +1106,10 @@ def save_single(operator, scene, filepath="", Property: "Width", "int", "",0 Property: "Height", "int", "",0''') if tex: - fname_rel, fname_strip = copy_image(tex) -# fname, fname_strip, fname_rel = derived_paths(tex.filepath, basepath, EXP_IMAGE_COPY) + fname_rel = io_utils.path_reference(tex.filepath, base_src, base_dst, path_mode, "", copy_set) + fname_strip = os.path.basename(fname_rel) else: - fname = fname_strip = fname_rel = '' + fname_strip = fname_rel = "" file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip) @@ -1188,8 +1126,6 @@ def save_single(operator, scene, filepath="", UseMipMap: 0''') file.write('\n\t\tFilename: "%s"' % fname_strip) - if fname_strip: - fname_strip = '/' + fname_strip file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # make relative file.write('\n\t}') @@ -1229,10 +1165,10 @@ def save_single(operator, scene, filepath="", file.write('\n\t\tMedia: "Video::%s"' % texname) if tex: - fname_rel, fname_strip = copy_image(tex) -# fname, fname_strip, fname_rel = derived_paths(tex.filepath, basepath, EXP_IMAGE_COPY) + fname_rel = io_utils.path_reference(tex.filepath, base_src, base_dst, path_mode, "", copy_set) + fname_strip = os.path.basename(fname_rel) else: - fname = fname_strip = fname_rel = '' + fname_strip = fname_rel = "" file.write('\n\t\tFileName: "%s"' % fname_strip) file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # need some make relative command @@ -2810,12 +2746,11 @@ Takes: {''') ob_meshes[:] = [] ob_null[:] = [] - # copy images if enabled -# if EXP_IMAGE_COPY: -# # copy_images( basepath, [ tex[1] for tex in textures if tex[1] != None ]) -# bpy.util.copy_images( [ tex[1] for tex in textures if tex[1] != None ], basepath) file.close() + # copy all collected files. + io_utils.path_reference_copy(copy_set) + print('export finished in %.4f sec.' % (time.clock() - start_time)) return {'FINISHED'} diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py index 18685e5e30dc9649c62af694e3d3ede515e2dc36..d374bd6476909bce99aec4f4a071a58d1a6a0b2a 100644 --- a/io_scene_obj/__init__.py +++ b/io_scene_obj/__init__.py @@ -43,6 +43,7 @@ if "bpy" in locals(): import bpy from bpy.props import BoolProperty, FloatProperty, StringProperty +import io_utils from io_utils import ExportHelper, ImportHelper @@ -102,7 +103,7 @@ class ExportOBJ(bpy.types.Operator, ExportHelper): 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) + # 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) @@ -113,6 +114,8 @@ class ExportOBJ(bpy.types.Operator, ExportHelper): group_by_material = BoolProperty(name="Material Groups", description="", default=False) keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default=False) + path_mode = io_utils.path_reference_mode + def execute(self, context): from . import export_obj return export_obj.save(self, context, **self.as_keywords(ignore=("check_existing", "filter_glob"))) diff --git a/io_scene_obj/export_obj.py b/io_scene_obj/export_obj.py index f5fed6a83310d86e67724abb133e06fd18e6b8c2..3b4737ae22a4220b9c39999bb72b3eac27086d73 100644 --- a/io_scene_obj/export_obj.py +++ b/io_scene_obj/export_obj.py @@ -24,6 +24,7 @@ import shutil import bpy import mathutils +import io_utils def name_compat(name): @@ -33,7 +34,7 @@ def name_compat(name): return name.replace(' ', '_') -def write_mtl(scene, filepath, copy_images, mtl_dict): +def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict): world = scene.world if world: @@ -41,6 +42,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict): else: worldAmb = 0.0, 0.0, 0.0 + source_dir = bpy.data.filepath dest_dir = os.path.dirname(filepath) def copy_image(image): @@ -106,9 +108,8 @@ def write_mtl(scene, filepath, copy_images, mtl_dict): # Write images! if img: # We have an image on the face! # write relative image path - rel = copy_image(img) + rel = io_utils.path_reference(img.filepath, source_dir, dest_dir, path_mode, "", copy_set) file.write('map_Kd %s\n' % rel) # Diffuse mapping image -# file.write('map_Kd %s\n' % img.filepath.split('\\')[-1].split('/')[-1]) # Diffuse mapping image elif mat: # No face image. if we havea material search for MTex image. image_map = {} @@ -133,7 +134,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict): image_map["map_Ns"] = image for key, image in image_map.items(): - filepath = copy_image(image) + filepath = io_utils.path_reference(image.filepath, source_dir, dest_dir, path_mode, "", copy_set) file.write('%s %s\n' % (key, repr(filepath)[1:-1])) file.write('\n\n') @@ -141,58 +142,6 @@ def write_mtl(scene, filepath, copy_images, mtl_dict): file.close() -# XXX not used -def copy_file(source, dest): - file = open(source, 'rb') - data = file.read() - file.close() - - file = open(dest, 'wb') - file.write(data) - file.close() - - -# XXX not used -def copy_images(dest_dir): - if dest_dir[-1] != os.sep: - dest_dir += os.sep - - # Get unique image names - uniqueImages = {} - for matname, mat, image in mtl_dict.values(): # Only use image name - # Get Texface images - if image: - uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default. - - # Get MTex images - if mat: - for mtex in mat.texture_slots: - if mtex and mtex.texture.type == 'IMAGE': - image_tex = mtex.texture.image - if image_tex: - try: - uniqueImages[image_tex] = image_tex - except: - pass - - # Now copy images - copyCount = 0 - -# for bImage in uniqueImages.values(): -# image_path = bpy.path.abspath(bImage.filepath) -# if bpy.sys.exists(image_path): -# # Make a name for the target path. -# dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1] -# if not bpy.utils.exists(dest_image_path): # Image isnt already there -# print('\tCopying "%s" > "%s"' % (image_path, dest_image_path)) -# copy_file(image_path, dest_image_path) -# copyCount+=1 - -# paths= bpy.util.copy_images(uniqueImages.values(), dest_dir) - - print('\tCopied %d images' % copyCount) - - def test_nurbs_compat(ob): if ob.type != 'CURVE': return False @@ -272,21 +221,22 @@ def write_nurb(file, ob, ob_mat): def write_file(filepath, objects, scene, - EXPORT_TRI=False, - EXPORT_EDGES=False, - EXPORT_NORMALS=False, - EXPORT_NORMALS_HQ=False, - EXPORT_UV=True, - EXPORT_MTL=True, - EXPORT_COPY_IMAGES=False, - EXPORT_APPLY_MODIFIERS=True, - EXPORT_ROTX90=True, - EXPORT_BLEN_OBS=True, - EXPORT_GROUP_BY_OB=False, - EXPORT_GROUP_BY_MAT=False, - EXPORT_KEEP_VERT_ORDER=False, - EXPORT_POLYGROUPS=False, - EXPORT_CURVE_AS_NURBS=True): + EXPORT_TRI=False, + EXPORT_EDGES=False, + EXPORT_NORMALS=False, + EXPORT_NORMALS_HQ=False, + EXPORT_UV=True, + EXPORT_MTL=True, + EXPORT_APPLY_MODIFIERS=True, + EXPORT_ROTX90=True, + EXPORT_BLEN_OBS=True, + EXPORT_GROUP_BY_OB=False, + EXPORT_GROUP_BY_MAT=False, + EXPORT_KEEP_VERT_ORDER=False, + EXPORT_POLYGROUPS=False, + EXPORT_CURVE_AS_NURBS=True, + EXPORT_PATH_MODE='AUTO', + ): ''' Basic write function. The context and options must be already set This can be accessed externaly @@ -358,6 +308,8 @@ def write_file(filepath, objects, scene, # A Dict of Materials # (material.name, image.name):matname_imagename # matname_imagename has gaps removed. mtl_dict = {} + + copy_set = set() # Get all meshes for ob_main in objects: @@ -694,17 +646,10 @@ def write_file(filepath, objects, scene, # Now we have all our materials, save them if EXPORT_MTL: - write_mtl(scene, mtlfilepath, EXPORT_COPY_IMAGES, mtl_dict) -# if EXPORT_COPY_IMAGES: -# dest_dir = os.path.basename(filepath) -# # dest_dir = filepath -# # # Remove chars until we are just the path. -# # while dest_dir and dest_dir[-1] not in '\\/': -# # dest_dir = dest_dir[:-1] -# if dest_dir: -# copy_images(dest_dir, mtl_dict) -# else: -# print('\tError: "%s" could not be used as a base for an image path.' % filepath) + write_mtl(scene, mtlfilepath, EXPORT_PATH_MODE, copy_set, mtl_dict) + + # copy all collected files. + io_utils.path_reference_copy(copy_set) print("OBJ Export time: %.2f" % (time.clock() - time1)) @@ -716,7 +661,6 @@ def _write(context, filepath, EXPORT_NORMALS_HQ, # not yet EXPORT_UV, # ok EXPORT_MTL, - EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS, # ok EXPORT_ROTX90, # wrong EXPORT_BLEN_OBS, @@ -727,7 +671,9 @@ def _write(context, filepath, EXPORT_CURVE_AS_NURBS, EXPORT_SEL_ONLY, # ok EXPORT_ALL_SCENES, # XXX not working atm - EXPORT_ANIMATION): # Not used + EXPORT_ANIMATION, + EXPORT_PATH_MODE, + ): # Not used base_name, ext = os.path.splitext(filepath) context_name = [base_name, '', '', ext] # Base name, scene name, frame number, extension @@ -778,21 +724,22 @@ def _write(context, filepath, # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad. # EXPORT THE FILE. write_file(full_path, objects, scene, - EXPORT_TRI, - EXPORT_EDGES, - EXPORT_NORMALS, - EXPORT_NORMALS_HQ, - EXPORT_UV, - EXPORT_MTL, - EXPORT_COPY_IMAGES, - EXPORT_APPLY_MODIFIERS, - EXPORT_ROTX90, - EXPORT_BLEN_OBS, - EXPORT_GROUP_BY_OB, - EXPORT_GROUP_BY_MAT, - EXPORT_KEEP_VERT_ORDER, - EXPORT_POLYGROUPS, - EXPORT_CURVE_AS_NURBS) + EXPORT_TRI, + EXPORT_EDGES, + EXPORT_NORMALS, + EXPORT_NORMALS_HQ, + EXPORT_UV, + EXPORT_MTL, + EXPORT_APPLY_MODIFIERS, + EXPORT_ROTX90, + EXPORT_BLEN_OBS, + EXPORT_GROUP_BY_OB, + EXPORT_GROUP_BY_MAT, + EXPORT_KEEP_VERT_ORDER, + EXPORT_POLYGROUPS, + EXPORT_CURVE_AS_NURBS, + EXPORT_PATH_MODE, + ) scene.frame_set(orig_frame, 0.0) @@ -815,7 +762,6 @@ def save(operator, context, filepath="", use_hq_normals=False, use_uvs=True, use_materials=True, - copy_images=False, use_apply_modifiers=True, use_rotate_x90=True, use_blen_objects=True, @@ -827,6 +773,7 @@ def save(operator, context, filepath="", use_selection=True, use_all_scenes=False, use_animation=False, + path_mode='AUTO' ): _write(context, filepath, @@ -836,7 +783,6 @@ def save(operator, context, filepath="", EXPORT_NORMALS_HQ=use_hq_normals, EXPORT_UV=use_uvs, EXPORT_MTL=use_materials, - EXPORT_COPY_IMAGES=copy_images, EXPORT_APPLY_MODIFIERS=use_apply_modifiers, EXPORT_ROTX90=use_rotate_x90, EXPORT_BLEN_OBS=use_blen_objects, @@ -848,6 +794,7 @@ def save(operator, context, filepath="", EXPORT_SEL_ONLY=use_selection, EXPORT_ALL_SCENES=use_all_scenes, EXPORT_ANIMATION=use_animation, + EXPORT_PATH_MODE=path_mode, ) return {'FINISHED'}