[Bf-extensions-cvs] [e1a1159c] master: Proof of concept automatic face map creation

Campbell Barton noreply at git.blender.org
Wed Jul 26 00:56:20 CEST 2017


Commit: e1a1159c1466bcc0b42662436d4056628c087391
Author: Campbell Barton
Date:   Wed Jul 26 09:07:34 2017 +1000
Branches: master
https://developer.blender.org/rBACe1a1159c1466bcc0b42662436d4056628c087391

Proof of concept automatic face map creation

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

A	object_facemap_auto/__init__.py
A	object_facemap_auto/auto_fmap_ops.py
A	object_facemap_auto/auto_fmap_utils.py
A	object_facemap_auto/auto_fmap_widgets.py
A	object_facemap_auto/auto_fmap_widgets_xform.py

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

diff --git a/object_facemap_auto/__init__.py b/object_facemap_auto/__init__.py
new file mode 100644
index 00000000..d5e4ae34
--- /dev/null
+++ b/object_facemap_auto/__init__.py
@@ -0,0 +1,47 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+bl_info = {
+    "name": "Auto Face Map Widgets",
+    "author": "Campbell Barton",
+    "version": (1, 0),
+    "blender": (2, 80, 0),
+    "location": "View3D",
+    "description": "Use face-maps in the 3D view when rigged meshes are selected.",
+    "warning": "This is currently a proof of concept.",
+    "wiki_url": "",
+    "category": "Rigging",
+}
+
+submodules = (
+    "auto_fmap_widgets",
+    "auto_fmap_ops",
+)
+
+# reload at runtime, for development.
+USE_RELOAD = True
+USE_VERBOSE = False
+
+from bpy.utils import register_submodule_factory
+
+register, unregister = register_submodule_factory(__name__, submodules)
+
+if __name__ == "__main__":
+    register()
diff --git a/object_facemap_auto/auto_fmap_ops.py b/object_facemap_auto/auto_fmap_ops.py
new file mode 100644
index 00000000..d5a3eee5
--- /dev/null
+++ b/object_facemap_auto/auto_fmap_ops.py
@@ -0,0 +1,105 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import (
+    Operator,
+)
+from bpy.props import (
+    EnumProperty,
+)
+
+from . import USE_RELOAD
+
+
+class MyFaceMapClear(Operator):
+    """Clear face-map transform"""
+    bl_idname = "my_facemap.transform_clear"
+    bl_label = "My Face Map Clear Transform"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    clear_types = EnumProperty(
+        name="Clear Types",
+        options={'ENUM_FLAG'},
+        items=(
+            ('LOCATION', "Location", ""),
+            ('ROTATION', "Rotation", ""),
+            ('SCALE', "Scale", ""),
+        ),
+        description="Clear transform",
+        # default=set(),
+    )
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object is not None
+
+    def invoke(self, context, _event):
+        self._group = context.manipulator_group
+        return self.execute(context)
+
+    def execute(self, context):
+        # trick since redo wont have manipulator_group
+        group = self._group
+
+        from .auto_fmap_utils import import_reload_or_none
+        auto_fmap_widgets_xform = import_reload_or_none(
+            __package__ + "." + "auto_fmap_widgets_xform", reload=USE_RELOAD,
+        )
+
+        if auto_fmap_widgets_xform is None:
+            return {'CANCELED'}
+
+        for mpr in group.manipulators:
+            ob = mpr.fmap_mesh_object
+            fmap_target = mpr.fmap_target
+            fmap = mpr.fmap
+
+            if mpr.select:
+                if 'LOCATION' in self.clear_types:
+                    auto_fmap_widgets_xform.widget_clear_location(
+                        context, mpr, ob, fmap, fmap_target,
+                    )
+                if 'ROTATION' in self.clear_types:
+                    auto_fmap_widgets_xform.widget_clear_rotation(
+                        context, mpr, ob, fmap, fmap_target,
+                    )
+                if 'SCALE' in self.clear_types:
+                    auto_fmap_widgets_xform.widget_clear_scale(
+                        context, mpr, ob, fmap, fmap_target,
+                    )
+        return {'FINISHED'}
+
+
+classes = (
+    MyFaceMapClear,
+)
+
+
+def register():
+    from bpy.utils import register_class
+    for cls in classes:
+        register_class(cls)
+
+
+def unregister():
+    from bpy.utils import unregister_class
+    for cls in classes:
+        unregister_class(cls)
diff --git a/object_facemap_auto/auto_fmap_utils.py b/object_facemap_auto/auto_fmap_utils.py
new file mode 100644
index 00000000..0a02907f
--- /dev/null
+++ b/object_facemap_auto/auto_fmap_utils.py
@@ -0,0 +1,38 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+
+# Use so we can develop modules without reloading the add-on.
+
+def import_reload_or_none(name, reload=True):
+    """
+    Import and reload a module.
+    """
+    try:
+        mod = __import__(name)
+        if reload:
+            import importlib
+            mod = importlib.reload(mod)
+        import sys
+        return sys.modules[name]
+    except Exception:
+        import traceback
+        traceback.print_exc()
+        return None
diff --git a/object_facemap_auto/auto_fmap_widgets.py b/object_facemap_auto/auto_fmap_widgets.py
new file mode 100644
index 00000000..aa4f3dc8
--- /dev/null
+++ b/object_facemap_auto/auto_fmap_widgets.py
@@ -0,0 +1,458 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+'''
+Face map manipulator:
+
+- Automatic face-map to bone/shape mapping, so tweaking a face-map edits the underlying bone or shape
+  by matching names.
+- Bones will: Translates, Rotates, Scales (in that order based on locks)
+- Face-map selection can be used.
+- Transforming multiple face maps at once works (with selection).
+- Alt-G/R/S can be used to clear face-map transformation.
+- Dot-key can be used for view selected face-maps.
+- Face-map names can store key-values, formatted:
+  "some_name;foo=bar;baz=spam".
+  Currently this is used to set the face-map action if it cant be usefully guessed from locks.
+  eg "Bone;action=scale".
+- Shapes simply change their influence.
+- Face-map colors from bone groups are used when available.
+- Supports precision (Shift) and increment snap (Ctrl).
+- Keyframes after each edit, regardless of auto-key setting (unless its canceled).
+  Note: I did this because there is no easy way to manually key - if you don't want the keyframe you can undo :)
+'''
+
+import bpy
+
+from bpy.types import (
+    ManipulatorGroup,
+    Manipulator,
+)
+from bpy.props import (
+    IntProperty,
+)
+
+
+# USE_VERBOSE = True
+from . import USE_VERBOSE
+from . import USE_RELOAD
+
+
+# -----------------------------------------------------------------------------
+# Utility functions
+
+def object_armatures(ob):
+    for mod in ob.modifiers:
+        if mod.type == 'ARMATURE':
+            if mod.show_viewport:
+                ob_arm = mod.object
+                if ob_arm is not None:
+                    yield ob_arm
+
+
+def face_map_find_target(ob, fmap_name):
+    """
+    Returns pose-bone or shape-key.
+    """
+    # first pose-bone
+    for ob_arm in object_armatures(ob):
+        pbone = ob_arm.pose.bones.get(fmap_name)
+        if pbone is not None:
+            return pbone
+
+    # second shape-keys
+    if ob.type == 'MESH':
+        ob_data = ob.data
+        shape_keys = ob_data.shape_keys
+        if shape_keys is not None:
+            shape_key = ob_data.shape_keys.key_blocks.get(fmap_name)
+            if shape_key is not None:
+                return shape_key
+
+    # can't find target
+    return None
+
+
+def pose_bone_get_color(pose_bone):
+    bone_group = pose_bone.bone_group
+    if bone_group is not None:
+        return bone_group.colors.active
+    else:
+        return None
+
+
+# -----------------------------------------------------------------------------
+# Face-map manipulators
+
+
+#import IPython; IPython.embed()
+
+class Aut

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list