Skip to content
Snippets Groups Projects
io_import_images_as_planes.py 42.3 KiB
Newer Older
  • Learn to ignore specific revisions
  •         if not material:
                material = bpy.data.materials.new(name=name_compat)
    
            material.use_nodes = True
            node_tree = material.node_tree
            out_node = clean_node_tree(node_tree)
    
    
            tex_image = self.create_cycles_texnode(context, node_tree, img_spec)
    
            if self.shader == 'DIFFUSE':
                core_shader = node_tree.nodes.new('ShaderNodeBsdfDiffuse')
            elif self.shader == 'SHADELESS':
                core_shader = get_shadeless_node(node_tree)
            else:  # Emission Shading
                core_shader = node_tree.nodes.new('ShaderNodeEmission')
                core_shader.inputs[1].default_value = self.emit_strength
    
            # Connect color from texture
            node_tree.links.new(core_shader.inputs[0], tex_image.outputs[0])
    
            if self.use_transparency:
                bsdf_transparent = node_tree.nodes.new('ShaderNodeBsdfTransparent')
    
                mix_shader = node_tree.nodes.new('ShaderNodeMixShader')
                node_tree.links.new(mix_shader.inputs[0], tex_image.outputs[1])
                node_tree.links.new(mix_shader.inputs[1], bsdf_transparent.outputs[0])
                node_tree.links.new(mix_shader.inputs[2], core_shader.outputs[0])
                core_shader = mix_shader
    
            node_tree.links.new(out_node.inputs[0], core_shader.outputs[0])
    
    
            auto_align_nodes(node_tree)
            return material
    
    
        # -------------------------------------------------------------------------
        # Geometry Creation
        def create_image_plane(self, context, name, img_spec):
    
            width, height = self.compute_plane_size(context, img_spec)
    
            # Create new mesh
            bpy.ops.mesh.primitive_plane_add('INVOKE_REGION_WIN')
    
            plane = context.active_object
    
            # Why does mesh.primitive_plane_add leave the object in edit mode???
            if plane.mode is not 'OBJECT':
                bpy.ops.object.mode_set(mode='OBJECT')
            plane.dimensions = width, height, 0.0
            plane.data.name = plane.name = name
            bpy.ops.object.transform_apply(scale=True)
    
            # If sizing for camera, also insert into the camera's field of view
            if self.size_mode == 'CAMERA':
    
                offset_axis = self.axis_id_to_vector[self.offset_axis]
    
                translate_axis = [0 if offset_axis[i] else 1 for i in (0, 1)]
                center_in_camera(context.scene, context.scene.camera, plane, translate_axis)
    
            self.align_plane(context, plane)
    
            return plane
    
        def compute_plane_size(self, context, img_spec):
            """Given the image size in pixels and location, determine size of plane"""
            px, py = img_spec.size
    
            # can't load data
            if px == 0 or py == 0:
                px = py = 1
    
            if self.size_mode == 'ABSOLUTE':
                y = self.height
                x = px / py * y
    
            elif self.size_mode == 'CAMERA':
                x, y = compute_camera_size(
                    context, context.scene.cursor_location,
                    self.fill_mode, px / py
                )
    
            elif self.size_mode == 'DPI':
                fact = 1 / self.factor / context.scene.unit_settings.scale_length * 0.0254
                x = px * fact
                y = py * fact
    
            else:  # elif self.size_mode == 'DPBU'
                fact = 1 / self.factor
                x = px * fact
                y = py * fact
    
            return x, y
    
        def align_plane(self, context, plane):
            """Pick an axis and align the plane to it"""
            if 'CAM' in self.align_axis:
                # Camera-aligned
                camera = context.scene.camera
                if (camera):
                    # Find the axis that best corresponds to the camera's view direction
    
                    axis = camera.matrix_world @ \
    
                        Vector((0, 0, 1)) - camera.matrix_world.col[3].xyz
                    # pick the axis with the greatest magnitude
                    mag = max(map(abs, axis))
                    # And use that axis & direction
                    axis = Vector([
                        n / mag if abs(n) == mag else 0.0
                        for n in axis
                    ])
                else:
                    # No camera? Just face Z axis
                    axis = Vector((0, 0, 1))
    
            else:
                # Axis-aligned
    
                axis = self.axis_id_to_vector[self.align_axis]
    
            # rotate accordingly for x/y axiis
    
            if not axis.z:
                plane.rotation_euler.x = pi / 2
    
                if axis.y > 0:
                    plane.rotation_euler.z = pi
                elif axis.y < 0:
                    plane.rotation_euler.z = 0
                elif axis.x > 0:
                    plane.rotation_euler.z = pi / 2
                elif axis.x < 0:
                    plane.rotation_euler.z = -pi / 2
    
            # or flip 180 degrees for negative z
            elif axis.z < 0:
                plane.rotation_euler.y = pi
    
            if self.align_axis == 'CAM':
                constraint = plane.constraints.new('COPY_ROTATION')
                constraint.target = camera
                constraint.use_x = constraint.use_y = constraint.use_z = True
                if not self.align_track:
                    bpy.ops.object.visual_transform_apply()
                    plane.constraints.clear()
    
            if self.align_axis == 'CAM_AX' and self.align_track:
                constraint = plane.constraints.new('LOCKED_TRACK')
                constraint.target = camera
                constraint.track_axis = 'TRACK_Z'
                constraint.lock_axis = 'LOCK_Y'
    
    
    
    # -----------------------------------------------------------------------------
    # Register
    
        self.layout.operator(IMPORT_IMAGE_OT_to_plane.bl_idname, text="Images as Planes", icon='TEXTURE')
    
        for cls in classes:
            bpy.utils.register_class(cls)
    
    
        bpy.types.TOPBAR_MT_file_import.append(import_images_button)
    
        bpy.types.VIEW3D_MT_image_add.append(import_images_button)
    
        bpy.app.handlers.load_post.append(register_driver)
        register_driver()
    
        bpy.types.TOPBAR_MT_file_import.remove(import_images_button)
    
        bpy.types.VIEW3D_MT_image_add.remove(import_images_button)
    
        # This will only exist if drivers are active
    
        if check_drivers in bpy.app.handlers.scene_update_post:
    
            bpy.app.handlers.scene_update_post.remove(check_drivers)
    
    
        bpy.app.handlers.load_post.remove(register_driver)
        del bpy.app.driver_namespace['import_image__find_plane_corner']
    
    
        for cls in classes:
            bpy.utils.unregister_class(cls)
    
    if __name__ == "__main__":
    
        # Run simple doc tests
        import doctest
        doctest.testmod()
    
        unregister()