[Bf-extensions-cvs] [97812d7] master: import images as planes rewrite: D2239

meta-androcto noreply at git.blender.org
Sun Jan 15 05:33:24 CET 2017


Commit: 97812d737e446da73f24754340cc9b7e6003c774
Author: meta-androcto
Date:   Sun Jan 15 15:32:56 2017 +1100
Branches: master
https://developer.blender.org/rBA97812d737e446da73f24754340cc9b7e6003c774

import images as planes rewrite: D2239

===================================================================

M	io_import_images_as_planes.py

===================================================================

diff --git a/io_import_images_as_planes.py b/io_import_images_as_planes.py
index 7ba5bfa..26dcba3 100644
--- a/io_import_images_as_planes.py
+++ b/io_import_images_as_planes.py
@@ -16,11 +16,13 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "Import Images as Planes",
-    "author": "Florian Meyer (tstscr), mont29, matali",
-    "version": (2, 0, 5),
-    "blender": (2, 76, 1),
+    "author": "Florian Meyer (tstscr), mont29, matali, Ted Schundler (SpkyElctrc)",
+    "version": (3, 0, 0),
+    "blender": (2, 77, 0),
     "location": "File > Import > Images as Planes or Add > Mesh > Images as Planes",
     "description": "Imports images and creates planes with the appropriate aspect ratio. "
                    "The images are mapped to the planes.",
@@ -30,72 +32,262 @@ bl_info = {
     "category": "Import-Export",
 }
 
+import os
+import warnings
+import re
+from itertools import count, repeat
+from collections import namedtuple
+from math import pi
+
 import bpy
 from bpy.types import Operator
-import mathutils
-import os
-import collections
+from mathutils import Vector
 
 from bpy.props import (
-        StringProperty,
-        BoolProperty,
-        EnumProperty,
-        IntProperty,
-        FloatProperty,
-        CollectionProperty,
-        )
+    StringProperty,
+    BoolProperty,
+    EnumProperty,
+    FloatProperty,
+    CollectionProperty)
+
+from bpy_extras.object_utils import (
+    AddObjectHelper,
+    world_to_camera_view)
 
-from bpy_extras.object_utils import AddObjectHelper, object_data_add
 from bpy_extras.image_utils import load_image
 
 # -----------------------------------------------------------------------------
-# Global Vars
-
-DEFAULT_EXT = "*"
-
-EXT_FILTER = getattr(collections, "OrderedDict", dict)((
-    (DEFAULT_EXT, ((), "All image formats", "Import all known image (or movie) formats.")),
-    ("jpeg", (("jpeg", "jpg", "jpe"), "JPEG ({})", "Joint Photographic Experts Group")),
-    ("png", (("png", ), "PNG ({})", "Portable Network Graphics")),
-    ("tga", (("tga", "tpic"), "Truevision TGA ({})", "")),
-    ("tiff", (("tiff", "tif"), "TIFF ({})", "Tagged Image File Format")),
-    ("bmp", (("bmp", "dib"), "BMP ({})", "Windows Bitmap")),
-    ("cin", (("cin", ), "CIN ({})", "")),
-    ("dpx", (("dpx", ), "DPX ({})", "DPX (Digital Picture Exchange)")),
-    ("psd", (("psd", ), "PSD ({})", "Photoshop Document")),
-    ("exr", (("exr", ), "OpenEXR ({})", "OpenEXR HDR imaging image file format")),
-    ("hdr", (("hdr", "pic"), "Radiance HDR ({})", "")),
-    ("avi", (("avi", ), "AVI ({})", "Audio Video Interleave")),
-    ("mov", (("mov", "qt"), "QuickTime ({})", "")),
-    ("mp4", (("mp4", ), "MPEG-4 ({})", "MPEG-4 Part 14")),
-    ("ogg", (("ogg", "ogv"), "OGG Theora ({})", "")),
-))
-
-# XXX Hack to avoid allowing videos with Cycles, crashes currently!
-VID_EXT_FILTER = {e for ext_k, ext_v in EXT_FILTER.items() if ext_k in {"avi", "mov", "mp4", "ogg"} for e in ext_v[0]}
-
-CYCLES_SHADERS = (
-    ('BSDF_DIFFUSE', "Diffuse", "Diffuse Shader"),
-    ('EMISSION', "Emission", "Emission Shader")
-)
+# Module-level Shared State
+
+watched_objects = {}  # used to trigger compositor updates on scene updates
+
 
 # -----------------------------------------------------------------------------
 # Misc utils.
-def gen_ext_filter_ui_items():
-    return tuple((k, name.format(", ".join("." + e for e in exts)) if "{}" in name else name, desc)
-                 for k, (exts, name, desc) in EXT_FILTER.items())
 
+def str_to_vector(s):
+    """Convert a string into a vector.
+
+    >>> str_to_vector("1,2,3")
+    Vector((1.0, 2.0, 3.0))
+
+    >>> str_to_vector("1.0, 0.0, 0, 1")
+    Vector((1.0, 0.0, 0.0, 1.0))
+    """
+    return Vector(map(float, s.split(',')))
+
+
+def add_driver_prop(driver, name, type, id, path):
+    """Configure a new driver variable."""
+    dv = driver.variables.new()
+    dv.name = name
+    dv.type = 'SINGLE_PROP'
+    target = dv.targets[0]
+    target.id_type = type
+    target.id = id
+    target.data_path = path
+
+
+def context_to_dict(context):
+    """Create a dictionary from the current context
+
+    >>> import bpy
+    >>> ctx = context_to_dict(bpy.context)
+    >>> assert ctx['window'] == bpy.context.window
+    """
+    return {
+        k: getattr(context, k) for k in
+        ('window', 'screen', 'area', 'scene', 'object', 'selected_objects')
+    }
+
+# -----------------------------------------------------------------------------
+# Image loading
+
+ImageSpec = namedtuple(
+    'ImageSpec',
+    ['image', 'size', 'frame_start', 'frame_offset', 'frame_duration'])
+
+num_regex = re.compile('[0-9]')  # Find a single number
+nums_regex = re.compile('[0-9]+')  # Find a set of numbers
+
+
+def find_image_sequences(files):
+    """From a group of files, detect image sequences.
+
+    This returns a generator of tuples, which contain the filename,
+    start frame, and length of the detected sequence
+
+    >>> list(find_image_sequences([
+    ...     "test2-001.jp2", "test2-002.jp2",
+    ...     "test3-003.jp2", "test3-004.jp2", "test3-005.jp2", "test3-006.jp2",
+    ...     "blaah"]))
+    [('blaah', 1, 1), ('test2-001.jp2', 1, 2), ('test3-003.jp2', 3, 4)]
+
+    """
+    files = iter(sorted(files))
+    prev_file = None
+    pattern = ""
+    matches = []
+    segment = None
+    length = 1
+    for filename in files:
+        new_pattern = num_regex.sub('#', filename)
+        new_matches = list(map(int, nums_regex.findall(filename)))
+        if new_pattern == pattern:
+            # this file looks like it may be in sequence from the previous
+
+            # if there are multiple sets of numbers, figure out what changed
+            if segment is None:
+                for i, prev, cur in zip(count(), matches, new_matches):
+                    if prev != cur:
+                        segment = i
+                        break
+
+            # did it only change by one?
+            for i, prev, cur in zip(count(), matches, new_matches):
+                if i == segment:
+                    # We expect this to increment
+                    prev = prev + length
+                if prev != cur:
+                    break
+
+            # All good!
+            else:
+                length += 1
+                continue
+
+        # No continuation -> spit out what we found and reset counters
+        if prev_file:
+            if length > 1:
+                yield prev_file, matches[segment], length
+            else:
+                yield prev_file, 1, 1
+
+        prev_file = filename
+        matches = new_matches
+        pattern = new_pattern
+        segment = None
+        length = 1
 
-def is_image_fn(fn, ext_key):
-    if ext_key == DEFAULT_EXT:
-        return True  # Using Blender's image/movie filter.
-    ext = os.path.splitext(fn)[1].lstrip(".").lower()
-    return ext in EXT_FILTER[ext_key][0]
+    if prev_file:
+        if length > 1:
+            yield prev_file, matches[segment], length
+        else:
+            yield prev_file, 1, 1
+
+
+def load_images(filenames, directory, force_reload=False, frame_start=1, find_sequences=False):
+    """Wrapper for bpy's load_image
+
+    Loads a set of images, movies, or even image sequences
+    Returns a generator of ImageSpec wrapper objects later used for texture setup
+    """
+    if find_sequences:  # if finding sequences, we need some pre-processing first
+        file_iter = find_image_sequences(filenames)
+    else:
+        file_iter = zip(filenames, repeat(1), repeat(1))
+
+    for filename, offset, frames in file_iter:
+        image = load_image(filename, directory, check_existing=True, force_reload=force_reload)
+
+        # Size is unavailable for sequences, so we grab it early
+        size = tuple(image.size)
+
+        if image.source == 'MOVIE':
+            # Blender BPY BUG!
+            # This number is only valid when read a second time in 2.77
+            # This repeated line is not a mistake
+            frames = image.frame_duration
+            frames = image.frame_duration
+
+        elif frames > 1:  # Not movie, but multiple frames -> image sequence
+            image.use_animation = True
+            image.source = 'SEQUENCE'
+
+        yield ImageSpec(image, size, frame_start, offset - 1, frames)
 
 
 # -----------------------------------------------------------------------------
-# Cycles utils.
-def get_input_nodes(node, nodes, links):
+# Position & Size Helpers
+
+def offset_planes(planes, gap, axis):
+    """Offset planes from each other by `gap` amount along a _local_ vector `axis`
+
+    For example, offset_planes([obj1, obj2], 0.5, Vector(0, 0, 1)) will place
+    obj2 0.5 blender units away from obj1 along the local positive Z axis.
+
+    This is in local space, not world space, so all planes should share
+    a common scale and rotation.
+    """
+    prior = planes[0]
+    offset = Vector()
+    for current in planes[1:]:
+
+        local_offset = abs((prior.dimensions + current.dimensions) * axis) / 2.0 + gap
+
+        offset += local_offset * axis
+        current.location = current.matrix_world * offset
+
+        prior = current
+
+
+def compute_camera_size(context, center, fill_mode, aspect):
+    """Determine how large an object needs to be to fit or fill the camera's field of view."""
+    scene = context.scene
+    camera = scene.camera
+    view_frame = camera.data.view_frame(scene=scene)
+    frame_size = \
+        Vector([max(v[i] for v in view_frame) for i in range(3)]) - \
+        Vector([min(v[i] for v in view_frame) for i in range(3)])
+    camera_aspect = frame_size.x / frame_size.y
+
+    # Convert the frame size to the correct sizing at a given distance
+    if camera.type == 'ORTHO':
+        frame_size = frame_size.xy
+    else:
+        # Perspective transform
+        distance = world_to_camera_view(scene, camera, center).z
+        frame_size = distance * frame_size.xy / (-view_frame[0].z)
+
+    # Determine what axis to match to the camera
+    match_axis = 0  # match the Y axis size
+    match_aspect = aspect
+    if (fill_mode == 'FILL' and aspect > camera_aspect) or \
+            (fill_mode == 'FIT' and 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list