From e56a4e47b05760ab63a76c40f7add107486bb6fb Mon Sep 17 00:00:00 2001
From: Campbell Barton <ideasman42@gmail.com>
Date: Tue, 31 Jan 2012 17:08:46 +0000
Subject: [PATCH] fix some errors with import images to planes, 1) path
 comparison was not expanding, normalizing first,  2) non-utf8 paths made the
 script error out,  3) paths were exported with absolute paths by default, had
 to remember to make them relative which was annoying.

---
 io_import_images_as_planes.py | 355 +++++++++++++++++++---------------
 1 file changed, 199 insertions(+), 156 deletions(-)

diff --git a/io_import_images_as_planes.py b/io_import_images_as_planes.py
index 7b1224917..10549a025 100644
--- a/io_import_images_as_planes.py
+++ b/io_import_images_as_planes.py
@@ -20,7 +20,7 @@ bl_info = {
     "name": "Import Images as Planes",
     "author": "Florian Meyer (tstscr)",
     "version": (1, 0),
-    "blender": (2, 5, 7),
+    "blender": (2, 6, 1),
     "location": "File > Import > Images as Planes",
     "description": "Imports images and creates planes with the appropriate "
                    "aspect ratio. The images are mapped to the planes.",
@@ -32,6 +32,7 @@ bl_info = {
     "category": "Import-Export"}
 
 import bpy
+from bpy.types import Operator
 import mathutils
 import os
 
@@ -41,94 +42,113 @@ from bpy.props import (BoolProperty,
                        FloatProperty,
                        )
 
-from add_utils import *
+from add_utils import AddObjectHelper, add_object_data
 from bpy_extras.io_utils import ImportHelper
 from bpy_extras.image_utils import load_image
 
-## GLOBAL VARS ##
+# -----------------------------------------------------------------------------
+# Global Vars
+
 EXT_LIST = {
-    'jpeg': ['jpeg', 'jpg', 'jpe'],
-    'png': ['png'],
-    'tga': ['tga', 'tpic'],
-    'tiff': ['tiff', 'tif'],
-    'exr': ['exr'],
-    'hdr': ['hdr'],
-    'avi': ['avi'],
-    'mov': ['mov', 'qt'],
-    'mp4': ['mp4'],
-    'ogg': ['ogg', 'ogv'],
-    'bmp': ['bmp', 'dib'],
-    'cin': ['cin'],
-    'dpx': ['dpx'],
-    'psd': ['psd']}
-EXT_VALS = list(EXT_LIST.values())
-EXTENSIONS = []
-for i in EXT_VALS:
-    EXTENSIONS.extend(i)
-    
-## FUNCTIONS ##
+    'jpeg': ('jpeg', 'jpg', 'jpe'),
+    'png': ('png', ),
+    'tga': ('tga', 'tpic'),
+    'tiff': ('tiff', 'tif'),
+    'exr': ('exr', ),
+    'hdr': ('hdr', ),
+    'avi': ('avi', ),
+    'mov': ('mov', 'qt'),
+    'mp4': ('mp4', ),
+    'ogg': ('ogg', 'ogv'),
+    'bmp': ('bmp', 'dib'),
+    'cin': ('cin', ),
+    'dpx': ('dpx', ),
+    'psd': ('psd', ),
+    }
+
+EXTENSIONS = [ext for ext_ls in EXT_LIST.values() for ext in ext_ls]
+
+
+# -----------------------------------------------------------------------------
+# Functions
 def set_image_options(self, image):
     image.use_premultiply = self.use_premultiply
-    
+
+    if self.relative:
+        image.filepath = bpy.path.relpath(image.filepath)
+
+
+def is_image_fn_any(fn):
+    ext = os.path.splitext(fn)[1].lstrip(".").lower()
+    return ext in EXTENSIONS
+
+
+def is_image_fn_single(fn, ext_key):
+    ext = os.path.splitext(fn)[1].lstrip(".").lower()
+    return ext in EXT_LIST[ext_key]
+
+
 def create_image_textures(self, image):
-    #look for texture with importsettings
+
+    fn_full = os.path.normpath(bpy.path.abspath(image.filepath))
+
+    # look for texture with importsettings
     for texture in bpy.data.textures:
-        if texture.type == 'IMAGE'\
-        and texture.image\
-        and texture.image.filepath == image.filepath:
-            if self.use_transparency:
-                texture.use_alpha = True
-            else:
-                texture.use_alpha = False
-            return texture
-    
-    #if no texture is found: create one
-    texture = bpy.data.textures.new(name=os.path.split(image.filepath)[1],
-                                    type='IMAGE')
+        if texture.type == 'IMAGE':
+            tex_img = texture.image
+            if (tex_img is not None) and (tex_img.library is None):
+                fn_tex_full = os.path.normpath(bpy.path.abspath(tex_img.filepath))
+                if fn_full == fn_tex_full:
+                    texture.use_alpha = self.use_transparency
+                    return texture
+
+    # if no texture is found: create one
+    name_compat = bpy.path.display_name_from_filepath(image.filepath)
+    texture = bpy.data.textures.new(name=name_compat, type='IMAGE')
     texture.image = image
-    if self.use_transparency:
-        texture.use_alpha = True
-    else:
-        texture.use_alpha = False
+    texture.use_alpha = self.use_transparency
     return texture
 
+
 def create_material_for_texture(self, texture):
-    #look for material with the needed texture
+    # look for material with the needed texture
     for material in bpy.data.materials:
-        if material.texture_slots[0]\
-        and material.texture_slots[0].texture == texture:
+        slot = material.texture_slots[0]
+        if slot and slot.texture == texture:
             if self.use_transparency:
-                material.alpha = 0
-                material.specular_alpha = 0
-                material.texture_slots[0].use_map_alpha = True
+                material.alpha = 0.0
+                material.specular_alpha = 0.0
+                slot.use_map_alpha = True
             else:
-                material.alpha = 1
-                material.specular_alpha = 1
-                material.texture_slots[0].use_map_alpha = False
+                material.alpha = 1.0
+                material.specular_alpha = 1.0
+                slot.use_map_alpha = False
             material.use_transparency = self.use_transparency
             material.transparency_method = self.transparency_method
             material.use_shadeless = self.use_shadeless
             return material
-            
+
     # if no material found: create one
-    material = bpy.data.materials.new(name=os.path.split(texture.image.filepath)[1])
+    name_compat = bpy.path.display_name_from_filepath(texture.image.filepath)
+    material = bpy.data.materials.new(name=name_compat)
     slot = material.texture_slots.add()
     slot.texture = texture
     slot.texture_coords = 'UV'
     if self.use_transparency:
         slot.use_map_alpha = True
-        material.alpha = 0
-        material.specular_alpha = 0
+        material.alpha = 0.0
+        material.specular_alpha = 0.0
     else:
-        material.alpha = 1
-        material.specular_alpha = 1
+        material.alpha = 1.0
+        material.specular_alpha = 1.0
         slot.use_map_alpha = False
     material.use_transparency = self.use_transparency
     material.transparency_method = self.transparency_method
     material.use_shadeless = self.use_shadeless
-    
+
     return material
 
+
 def create_image_plane(self, context, material):
     img = material.texture_slots[0].texture.image
     px, py = img.size
@@ -144,11 +164,12 @@ def create_image_plane(self, context, material):
         x = (px * (1.0 / self.factor)) * 0.5
         y = (py * (1.0 / self.factor)) * 0.5
 
-    verts = [(-x, -y, 0),
-             (x, -y, 0),
-             (x, y, 0),
-             (-x, y, 0)]
-    faces = [[0, 1, 2, 3]]
+    verts = ((-x, -y, 0.0),
+             (+x, -y, 0.0),
+             (+x, +y, 0.0),
+             (-x, +y, 0.0),
+             )
+    faces = ((0, 1, 2, 3), )
 
     mesh_data = bpy.data.meshes.new(img.name)
     mesh_data.from_pydata(verts, [], faces)
@@ -163,54 +184,58 @@ def create_image_plane(self, context, material):
     material.game_settings.alpha_blend = 'ALPHA'
     return plane
 
+
 def generate_paths(self):
-    directory, file = os.path.split(self.filepath)
+    directory, fn = os.path.split(self.filepath)
 
-    if file and not self.all_in_directory:
-        #test for extension
-        if not os.path.splitext(file)[1].lstrip('.').lower() in EXTENSIONS:
+    if fn and not self.all_in_directory:
+        # test for extension
+        if not is_image_fn_any(fn):
             return [], directory
-        
+
         return [self.filepath], directory
-        
-    if not file or self.all_in_directory:
+
+    if not fn or self.all_in_directory:
         imagepaths = []
         files_in_directory = os.listdir(directory)
-        #clean files from nonimages
-        files_in_directory = [file for file in files_in_directory
-                              if os.path.splitext(file)[1].lstrip('.').lower()
-                              in EXTENSIONS]
-        #clean from unwanted extensions
-        if self.extension != '*':
-            files_in_directory = [file for file in files_in_directory
-                                  if os.path.splitext(file)[1].lstrip('.').lower()
-                                  in EXT_LIST[self.extension]]
-        #create paths
-        for file in files_in_directory:
-            imagepaths.append(os.path.join(directory, file))
-            
+        # clean files from nonimages
+        files_in_directory = [fn for fn in files_in_directory
+                              if is_image_fn_any(fn)]
+        # clean from unwanted extensions
+        if self.extension != "*":
+            files_in_directory = [fn for fn in files_in_directory
+                                  if is_image_fn_single(fn, self.extension)]
+        # create paths
+        for fn in files_in_directory:
+            imagepaths.append(os.path.join(directory, fn))
+
         #print(imagepaths)
         return imagepaths, directory
 
+
 def align_planes(self, planes):
     gap = self.align_offset
     offset = 0
     for i, plane in enumerate(planes):
         offset += (plane.dimensions.x / 2.0) + gap
-        if i == 0: continue
-        move_local = mathutils.Vector((offset, 0, 0))
+        if i == 0:
+            continue
+        move_local = mathutils.Vector((offset, 0.0, 0.0))
         move_world = plane.location + move_local * plane.matrix_world.inverted()
         plane.location += move_world
         offset += (plane.dimensions.x / 2.0)
-        
-##### MAIN #####
+
+
+# -----------------------------------------------------------------------------
+# Main
+
 def import_images(self, context):
     import_list, directory = generate_paths(self)
     images = []
     textures = []
     materials = []
     planes = []
-    
+
     for path in import_list:
         images.append(load_image(path, directory))
 
@@ -224,27 +249,30 @@ def import_images(self, context):
     for material in materials:
         plane = create_image_plane(self, context, material)
         planes.append(plane)
-        
+
     context.scene.update()
     if self.align:
         align_planes(self, planes)
-        
+
     for plane in planes:
         plane.select = True
-        
-    self.report(type={'INFO'},
-                message='Added %i Image Plane(s)' %len(planes))
 
-##### OPERATOR #####
-class IMPORT_OT_image_to_plane(bpy.types.Operator, ImportHelper, AddObjectHelper):
-    ''''''
+    self.report({'INFO'}, "Added %i Image Plane(s)" % len(planes))
+
+
+# -----------------------------------------------------------------------------
+# Operator
+
+class IMPORT_OT_image_to_plane(Operator, ImportHelper, AddObjectHelper):
+    """Create mesh plane(s) from image files """ \
+    """with the appropiate aspect ratio"""
+
     bl_idname = "import.image_to_plane"
     bl_label = "Import Images as Planes"
-    bl_description = "Create mesh plane(s) from image files" \
-                     " with the appropiate aspect ratio"
     bl_options = {'REGISTER', 'UNDO'}
 
-    ## OPTIONS ##
+    # -------
+    # Options
     all_in_directory = BoolProperty(
             name="All in directory",
             description=("Import all image files (of the selected type) "
@@ -263,39 +291,40 @@ class IMPORT_OT_image_to_plane(bpy.types.Operator, ImportHelper, AddObjectHelper
             soft_min=0,
             default=0.1,
             )
-    extEnum = (
-        ('*', 'All image formats',
-            'Import all know image (or movie) formats.'),
-        ('jpeg', 'JPEG (.jpg, .jpeg, .jpe)',
-            'Joint Photographic Experts Group'),
-        ('png', 'PNG (.png)', 'Portable Network Graphics'),
-        ('tga', 'Truevision TGA (.tga, tpic)', ''),
-        ('tiff', 'TIFF (.tif, .tiff)', 'Tagged Image File Format'),
-        ('exr', 'OpenEXR (.exr)', 'OpenEXR HDR imaging image file format'),
-        ('hdr', 'Radiance HDR (.hdr, .pic)', ''),
-        ('avi', 'AVI (.avi)', 'Audio Video Interleave'),
-        ('mov', 'QuickTime (.mov, .qt)', ''),
-        ('mp4', 'MPEG-4 (.mp4)', ' MPEG-4 Part 14'),
-        ('ogg', 'OGG Theora (.ogg, .ogv)', ''),
-        ('bmp', 'BMP (.bmp, .dib)', 'Windows Bitmap'),
-        ('cin', 'CIN (.cin)', ''),
-        ('dpx', 'DPX (.dpx)', 'DPX (Digital Picture Exchange)'),
-        ('psd', 'PSD (.psd)', 'Photoshop Document'),
-        )
     extension = EnumProperty(
             name="Extension",
             description="Only import files of this type",
-            items=extEnum)
+            items=(
+            ('*', 'All image formats',
+                'Import all know image (or movie) formats.'),
+            ('jpeg', 'JPEG (.jpg, .jpeg, .jpe)',
+                'Joint Photographic Experts Group'),
+            ('png', 'PNG (.png)', 'Portable Network Graphics'),
+            ('tga', 'Truevision TGA (.tga, tpic)', ''),
+            ('tiff', 'TIFF (.tif, .tiff)', 'Tagged Image File Format'),
+            ('exr', 'OpenEXR (.exr)', 'OpenEXR HDR imaging image file format'),
+            ('hdr', 'Radiance HDR (.hdr, .pic)', ''),
+            ('avi', 'AVI (.avi)', 'Audio Video Interleave'),
+            ('mov', 'QuickTime (.mov, .qt)', ''),
+            ('mp4', 'MPEG-4 (.mp4)', ' MPEG-4 Part 14'),
+            ('ogg', 'OGG Theora (.ogg, .ogv)', ''),
+            ('bmp', 'BMP (.bmp, .dib)', 'Windows Bitmap'),
+            ('cin', 'CIN (.cin)', ''),
+            ('dpx', 'DPX (.dpx)', 'DPX (Digital Picture Exchange)'),
+            ('psd', 'PSD (.psd)', 'Photoshop Document')),
+            )
     use_dimension = BoolProperty(name="Use image dimensions",
-            description="Use the images pixels to derive the size of the plane",
-            default=False)
+            description="Use the images pixels to derive planes size",
+            default=False,
+            )
     factor = IntProperty(name="Pixels/BU",
             description="Number of pixels per Blenderunit",
             min=1,
             default=500,
             )
 
-    ## MATERIAL OPTIONS ##
+    # ----------------
+    # Material Options
     use_shadeless = BoolProperty(
             name="Shadeless",
             description="Set material to shadeless",
@@ -306,81 +335,95 @@ class IMPORT_OT_image_to_plane(bpy.types.Operator, ImportHelper, AddObjectHelper
             description="Use alphachannel for transparency",
             default=False,
             )
-    tEnum = (
+
+    transparency_method = EnumProperty(
+            name="Transp. Method",
+            description="Transparency Method",
+            items=(
             ('Z_TRANSPARENCY',
             'Z Transparency',
             'Use alpha buffer for transparent faces'),
             ('RAYTRACE',
             'Raytrace',
-            'Use raytracing for transparent refraction rendering.'))
-    transparency_method = EnumProperty(
-            name="Transp. Method",
-            description="Transparency Method",
-            items=tEnum,
+            'Use raytracing for transparent refraction rendering.')),
             )
 
-    ## IMAGE OPTIONS ##
+    # -------------
+    # Image Options
     use_premultiply = BoolProperty(name="Premultiply",
                                 description="Premultiply image",
                                 default=False)
 
-    ## DRAW ##
+    relative = BoolProperty(
+            name="Relative",
+            description="Apply relative paths",
+            default=True,
+            )
+
     def draw(self, context):
         layout = self.layout
-        
-        box = layout.box()
-        box.label('Import Options:', icon='FILTER')
-        box.prop(self, 'all_in_directory')
-        box.prop(self, 'extension', icon='FILE_IMAGE')
-        box.prop(self, 'align')
-        box.prop(self, 'align_offset')
-        
+
         box = layout.box()
-        box.label('Material mappings:', icon='MATERIAL')
-        box.prop(self, 'use_shadeless')
-        box.prop(self, 'use_transparency')
-        box.prop(self, 'use_premultiply')
-        box.prop(self, 'transparency_method', expand=True)
-        
+        box.label("Import Options:", icon='FILTER')
+        box.prop(self, "all_in_directory")
+        box.prop(self, "extension", icon='FILE_IMAGE')
+        box.prop(self, "align")
+        box.prop(self, "align_offset")
+
+        row = box.row()
+        row.active = bpy.data.is_saved
+        row.prop(self, "relative")
+
         box = layout.box()
-        box.label('Plane dimensions:', icon='ARROW_LEFTRIGHT')
-        box.prop(self, 'use_dimension')
-        box.prop(self, 'factor', expand=True)
+        box.label("Material mappings:", icon='MATERIAL')
+        box.prop(self, "use_shadeless")
+        box.prop(self, "use_transparency")
+        box.prop(self, "use_premultiply")
+        box.prop(self, "transparency_method", expand=True)
 
+        box = layout.box()
+        box.label("Plane dimensions:", icon='ARROW_LEFTRIGHT')
+        box.prop(self, "use_dimension")
+        box.prop(self, "factor", expand=True)
 
-    ## EXECUTE ##
     def execute(self, context):
-        #the add utils don't work in this case
-        #because many objects are added
-        #disable relevant things beforehand
+
+        if not bpy.data.is_saved:
+            self.relative = False
+
+        # the add utils don't work in this case
+        # because many objects are added
+        # disable relevant things beforehand
         editmode = context.user_preferences.edit.use_enter_edit_mode
         context.user_preferences.edit.use_enter_edit_mode = False
         if context.active_object\
         and context.active_object.mode == 'EDIT':
             bpy.ops.object.mode_set(mode='OBJECT')
-        
+
         import_images(self, context)
-        
+
         context.user_preferences.edit.use_enter_edit_mode = editmode
         return {'FINISHED'}
 
 
+# -----------------------------------------------------------------------------
+# Register
 
 
-##### REGISTER #####
-
 def import_images_button(self, context):
     self.layout.operator(IMPORT_OT_image_to_plane.bl_idname,
                          text="Images as Planes",
                          icon='PLUGIN')
 
+
 def register():
     bpy.utils.register_module(__name__)
-
     bpy.types.INFO_MT_file_import.append(import_images_button)
+
+
 def unregister():
     bpy.utils.unregister_module(__name__)
-
     bpy.types.INFO_MT_file_import.remove(import_images_button)
+
 if __name__ == '__main__':
     register()
-- 
GitLab