[Bf-blender-cvs] [ffb0ed3] multi_previews_id: Applied my work from temp-sybren-poselib branch.

Sybren A. Stüvel noreply at git.blender.org
Tue Nov 1 15:14:21 CET 2016


Commit: ffb0ed305d87d236787163abbe33a921d3eaecf6
Author: Sybren A. Stüvel
Date:   Tue Nov 1 15:14:15 2016 +0100
Branches: multi_previews_id
https://developer.blender.org/rBffb0ed305d87d236787163abbe33a921d3eaecf6

Applied my work from temp-sybren-poselib branch.

Still a bit rough. For example, the viewport used for OpenGL rendering is
more or less randomly chosen from the current screen.

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

M	release/scripts/startup/bl_operators/__init__.py
A	release/scripts/startup/bl_operators/poselib.py
M	release/scripts/startup/bl_ui/__init__.py
M	release/scripts/startup/bl_ui/properties_data_armature.py
M	source/blender/blenkernel/intern/anim_sys.c
M	source/blender/editors/armature/pose_lib.c
M	source/blender/editors/armature/pose_transform.c
M	source/blender/makesrna/intern/rna_timeline.c

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

diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index a696410..01c954d 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -39,6 +39,7 @@ _modules = [
     "object",
     "object_randomize_transform",
     "object_quick_effects",
+    "poselib",
     "presets",
     "rigidbody",
     "screen_play_rendered_anim",
diff --git a/release/scripts/startup/bl_operators/poselib.py b/release/scripts/startup/bl_operators/poselib.py
new file mode 100644
index 0000000..0579470
--- /dev/null
+++ b/release/scripts/startup/bl_operators/poselib.py
@@ -0,0 +1,129 @@
+# ##### 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 #####
+
+if "bpy" in locals():
+    from importlib import reload
+    if "anim_utils" in locals():
+        reload(anim_utils)
+    del reload
+
+
+import bpy
+from bpy.types import Operator
+from bpy.props import (
+        IntProperty,
+        BoolProperty,
+        EnumProperty,
+        StringProperty,
+        )
+
+
+class POSELIB_OT_render_previews(Operator):
+    """Renders a preview image for each pose in the pose library.
+
+    TODO: the viewport used for OpenGL rendering is more or less random.
+    """
+
+    import logging as __logging
+
+    bl_idname = "poselib.render_previews"
+    bl_label = "Render pose previews"
+    bl_description = "Renders a preview image for each pose in the pose library"
+
+    log = __logging.getLogger('bpy.ops.%s' % bl_idname)
+
+    render_method = EnumProperty(
+        items=[
+            ('OPENGL', 'OpenGL render', 'Use the OpenGL viewport render'),
+            ('FULL', 'Full render', 'Use the same render engine as the scene'),
+        ],
+        default='OPENGL'
+    )
+
+    plib_index = 0
+
+    @classmethod
+    def poll(cls, context):
+        """Running only makes sense if there are any poses in the library."""
+        plib = context.object and context.object.pose_library
+        return bool(plib and plib.pose_markers)
+
+    def execute(self, context):
+        return {'PASS_THROUGH'}
+
+    def modal(self, context, event):
+        if event.type == 'ESC':
+            self._finish(context)
+            self.report({'INFO'}, 'Canceled rendering pose library previews')
+            return {'CANCELLED'}
+
+        if event.type != 'TIMER':
+            return {'PASS_THROUGH'}
+
+        plib = context.object.pose_library
+
+        pose_count = len(plib.pose_markers)
+        if self.plib_index >= pose_count:
+            self._finish(context)
+            self.report({'INFO'}, 'Done rendering pose library previews')
+            return {'FINISHED'}
+
+        self.render_pose(context, plib, self.plib_index)
+        self.plib_index += 1
+
+        return {'RUNNING_MODAL'}
+
+    def render_pose(self, context, plib, plib_index):
+        import os.path
+
+        marker = plib.pose_markers[plib_index]
+        self.log.info('Rendering pose %s at frame %i', marker.name, marker.frame)
+
+        context.scene.frame_set(marker.frame)
+        switch_to = None
+        if marker.camera:
+            switch_to = marker.camera
+        else:
+            cams = [m.camera for m in context.scene.timeline_markers
+                    if m.frame == marker.frame and m.camera]
+            if cams:
+                switch_to = cams[0]
+        if switch_to is not None:
+            self.log.info('Switching camera to %s', switch_to)
+            context.scene.camera = switch_to
+
+        bpy.ops.poselib.apply_pose(pose_index=plib_index)
+
+        fname = '%s.png' % marker.name
+        context.scene.render.filepath = os.path.join(plib.pose_previews_dir, fname)
+        bpy.ops.render.opengl(write_still=True)
+
+    def invoke(self, context, event):
+        wm = context.window_manager
+        wm.modal_handler_add(self)
+
+        self.wm = context.window_manager
+        self.timer = self.wm.event_timer_add(0.01, context.window)
+        self.plib_index = 0
+        self.orig_filepath = context.scene.render.filepath
+
+        return {'RUNNING_MODAL'}
+
+    def _finish(self, context):
+        self.wm.event_timer_remove(self.timer)
+        context.scene.render.filepath = self.orig_filepath
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 2389be6..56d3ece 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -139,12 +139,32 @@ def register():
             default={'OFFICIAL', 'COMMUNITY'},
             options={'ENUM_FLAG'},
             )
+
+    # properties_data_armature.py
+    from . import properties_data_armature
+    bpy.types.Action.pose_previews = EnumProperty(
+        items=properties_data_armature.pose_preview_items,
+        update=properties_data_armature.update_pose)
+    bpy.types.Action.pose_previews_dir = StringProperty(
+        name='Thumbnail Path',
+        subtype='DIR_PATH',
+        default='',
+        # update=filepath_update
+    )
+
+
     # done...
 
 
 def unregister():
     bpy.utils.unregister_module(__name__)
 
+    from . import properties_data_armature
+
+    del bpy.types.Object.pose_previews
+    if properties_data_armature.previews:
+        bpy.utils.previews.remove(properties_data_armature.previews)
+
 
 # Define a default UIList, when a list does not need any custom drawing...
 # Keep in sync with its #defined name in UI_interface.h
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 8261f0c..b98eaf8 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -161,6 +161,56 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
         sub.operator("pose.group_deselect", text="Deselect")
 
 
+previews = None
+
+
+def pose_preview_items(poselib, context):
+    global previews
+    import os.path
+
+    if context is None or not poselib.pose_previews_dir:
+        return []
+
+    directory = bpy.path.abspath(poselib.pose_previews_dir)
+    if not os.path.isdir(directory):
+        return []
+
+    if previews is not None and directory == previews.get('pose_previews_dir', None):
+        return previews.pose_previews
+
+    if previews is None:
+        previews = bpy.utils.previews.new()
+    else:
+        previews.clear()
+
+    no_thumbnail = os.path.join(os.path.dirname(__file__),
+                                'thumbnails',
+                                'no_thumbnail.png')
+    no_thumb_thumb = previews.load('NO THUMBNAIL', no_thumbnail, 'IMAGE')
+
+    enum_items = []
+    for pose_idx, pose_marker in enumerate(poselib.pose_markers):
+        filepath = os.path.join(directory, '%s.png' % pose_marker.name)
+        if os.path.exists(filepath):
+            thumb = previews.load(pose_marker.name, filepath, 'IMAGE')
+        else:
+            print('Warning: "%s" does not exist' % filepath)
+            thumb = no_thumb_thumb
+
+        enum_items.append((pose_marker.name, pose_marker.name, pose_marker.name,
+                           thumb.icon_id, pose_idx))
+
+    previews.pose_previews = enum_items
+    previews['pose_previews_dir'] = directory
+    return previews.pose_previews
+
+
+def update_pose(poselib_action, context):
+    pose_name = poselib_action.pose_previews
+    poselib_action.pose_markers.active = poselib_action.pose_markers[pose_name]
+    bpy.ops.poselib.apply_pose(pose_index=poselib_action.pose_markers.active_index)
+
+
 class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
     bl_label = "Pose Library"
     bl_options = {'DEFAULT_CLOSED'}
@@ -177,33 +227,50 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
 
         layout.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
 
-        if poselib:
-            # list of poses in pose library
-            row = layout.row()
-            row.template_list("UI_UL_list", "pose_markers", poselib, "pose_markers",
-                              poselib.pose_markers, "active_index", rows=5)
+        if not poselib:
+            return
+
+        # layout.template_icon_view(
+        #     poselib, 'pose_markers',
+        #     show_labels=True,
+        # )
+        # list of poses in pose library
+        row = layout.row()
+        row.template_list("UI_UL_list", "pose_markers", poselib, "pose_markers",
+                          poselib.pose_markers, "active_index",
+                          rows=5)
+        # column of operators for active pose
+        # - goes beside list
+        col = row.column(align=True)
+
+        # invoke should still be used for 'add', as it is needed to allow
+        # add/replace options to be used properly
+        col.operator("poselib.pose_add", icon='ZOOMIN', text="")
+        pose_marker_active = poselib.pose_markers.active
 
-            # column of operators for active pose
-            # - goes beside list
-            col = row.column(align=True)
+        # The following operators just need to be executed, not invoked;
+        # otherwise they show a menu which we don't want.
+        col.operator_context = 'EXEC_DEFAULT'
 
-            # invoke should still be used for 'add', as it is needed to allow
-            # add/replace options to be used properly
-            col.operator("poselib.pose_add", icon='ZOOMIN', text="")
+        if pose_marker_active:
+        

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list