Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2016-05-17 18:19:06 +0300
committerJoshua Leung <aligorith@gmail.com>2016-05-17 18:19:06 +0300
commit49aeee5a3dfa9fc0ae29e99f7c5c0cc0124e560e (patch)
tree49ace019e0509cd188f24d11c8f799ab676f6bbd /release
parent29a17d54da1f4b85a59487e032165bb44dc1b065 (diff)
Bendy Bones: Advanced B-Bones for Easier + Simple Rigging
This commit/patch/branch brings a bunch of powerful new options for B-Bones and for working with B-Bones, making it easier for animators to create their own rigs, using fewer bones (which also means hopefully lighter + faster rigs ;) This functionality was first demoed by Daniel at BConf15 Some highlights from this patch include: * You can now directly control the shape of B-Bones using a series of properties instead of being restricted to trying to indirectly control them through the neighbouring bones. See the "Bendy Bones" panel... * B-Bones can be shaped in EditMode to define a "curved rest pose" for the bone. This is useful for things like eyebrows and mouths/eyelids * You can now make B-Bones use custom bones as their reference bone handles, instead of only using the parent/child bones. To do so, enable the "Use Custom Reference Handles" toggle. If none are specified, then the BBone will only use the Bendy Bone properties. * Constraints Head/Tail option can now slide along the B-Bone shape, instead of just linearly interpolating between the endpoints of the bone. For more details, see: * http://aligorith.blogspot.co.nz/2016/05/bendy-bones-dev-update.html * http://aligorith.blogspot.co.nz/2016/05/an-in-depth-look-at-how-b-bones-work.html -- Credits -- Original Idea: Daniel M Lara (pepeland) Original Patch/Research: Jose Molina Additional Development + Polish: Joshua Leung (aligorith) Testing/Feedback: Daniel M Lara (pepeland), Juan Pablo Bouza (jpbouza)
Diffstat (limited to 'release')
-rw-r--r--release/scripts/modules/keyingsets_utils.py51
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py102
-rw-r--r--release/scripts/startup/keyingsets_builtins.py32
4 files changed, 168 insertions, 20 deletions
diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py
index 03400edc904..375ee3feebe 100644
--- a/release/scripts/modules/keyingsets_utils.py
+++ b/release/scripts/modules/keyingsets_utils.py
@@ -28,11 +28,14 @@ __all__ = (
"RKS_POLL_selected_objects",
"RKS_POLL_selected_bones",
"RKS_POLL_selected_items",
+ "RKS_ITER_selected_object",
+ "RKS_ITER_selected_bones",
"RKS_ITER_selected_item",
"RKS_GEN_available",
"RKS_GEN_location",
"RKS_GEN_rotation",
"RKS_GEN_scaling",
+ "RKS_GEN_bendy_bones",
)
import bpy
@@ -93,11 +96,17 @@ def RKS_ITER_selected_item(ksi, context, ks):
ksi.generate(context, ks, ob)
-# all select objects only
+# all selected objects only
def RKS_ITER_selected_objects(ksi, context, ks):
for ob in context.selected_objects:
ksi.generate(context, ks, ob)
+
+# all seelcted bones only
+def RKS_ITER_selected_bones(ksi, context, ks):
+ for bone in context.selected_pose_bones:
+ ksi.generate(context, ks, bone)
+
###########################
# Generate Callbacks
@@ -207,3 +216,43 @@ def RKS_GEN_scaling(ksi, context, ks, data):
ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
else:
ks.paths.add(id_block, path)
+
+# ------
+
+# Property identifiers for Bendy Bones
+bbone_property_ids = (
+ "bbone_curveinx",
+ "bbone_curveiny",
+ "bbone_curveoutx",
+ "bbone_curveouty",
+
+ "bbone_rollin",
+ "bbone_rollout",
+
+ "bbone_scalein",
+ "bbone_scaleout",
+
+ # NOTE: These are in the nested bone struct
+ # Do it this way to force them to be included
+ # in whatever actions are being keyed here
+ "bone.bbone_in",
+ "bone.bbone_out",
+)
+
+# Add Keying Set entries for bendy bones
+def RKS_GEN_bendy_bones(ksi, context, ks, data):
+ # get id-block and path info
+ # NOTE: This assumes that we're dealing with a bone here...
+ id_block, base_path, grouping = get_transform_generators_base_info(data)
+
+ # for each of the bendy bone properties, add a Keying Set entry for it...
+ for propname in bbone_property_ids:
+ # add the property name to the base path
+ path = path_add_property(base_path, propname)
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
+ else:
+ ks.paths.add(id_block, path)
+
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index ef0fc9c7c9f..4ca2f773dcc 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -65,9 +65,10 @@ class ConstraintButtonsPanel:
layout.prop_search(con, "subtarget", con.target.data, "bones", text="Bone")
if hasattr(con, "head_tail"):
- row = layout.row()
+ row = layout.row(align=True)
row.label(text="Head/Tail:")
row.prop(con, "head_tail", text="")
+ row.prop(con, "use_bbone_shape", text="", icon='IPO_BEZIER') # XXX icon, and only when bone has segments?
elif con.target.type in {'MESH', 'LATTICE'}:
layout.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 690c22c1440..99c0d7f37c1 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -146,6 +146,81 @@ class BONE_PT_transform_locks(BoneButtonsPanel, Panel):
sub.prop(pchan, "lock_rotation_w", text="W")
+class BONE_PT_curved(BoneButtonsPanel, Panel):
+ bl_label = "Bendy Bones"
+ #bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ ob = context.object
+ bone = context.bone
+ arm = context.armature
+ pchan = None
+
+ if ob and bone:
+ pchan = ob.pose.bones[bone.name]
+ bbone = pchan
+ elif bone is None:
+ bone = context.edit_bone
+ bbone = bone
+ else:
+ bbone = bone
+
+ layout = self.layout
+ layout.prop(bone, "bbone_segments", text="Segments")
+
+ col = layout.column()
+ col.active = bone.bbone_segments > 1
+
+ row = col.row()
+ sub = row.column(align=True)
+ sub.label(text="Curve XY Offsets:")
+ sub.prop(bbone, "bbone_curveinx", text="In X")
+ sub.prop(bbone, "bbone_curveiny", text="In Y")
+ sub.prop(bbone, "bbone_curveoutx", text="Out X")
+ sub.prop(bbone, "bbone_curveouty", text="Out Y")
+
+ sub = row.column(align=True)
+ sub.label("Roll:")
+ sub.prop(bbone, "bbone_rollin", text="In")
+ sub.prop(bbone, "bbone_rollout", text="Out")
+ sub.prop(bone, "use_endroll_as_inroll")
+
+ row = col.row()
+ sub = row.column(align=True)
+ sub.label(text="Scale:")
+ sub.prop(bbone, "bbone_scalein", text="Scale In")
+ sub.prop(bbone, "bbone_scaleout", text="Scale Out")
+
+ sub = row.column(align=True)
+ sub.label("Easing:")
+ if pchan:
+ # XXX: have these also be an overlay?
+ sub.prop(bbone.bone, "bbone_in", text="Ease In")
+ sub.prop(bbone.bone, "bbone_out", text="Ease Out")
+ else:
+ sub.prop(bone, "bbone_in", text="Ease In")
+ sub.prop(bone, "bbone_out", text="Ease Out")
+
+ if pchan:
+ layout.separator()
+
+ col = layout.column()
+ col.prop(pchan, "use_bbone_custom_handles")
+
+ row = col.row()
+ row.active = pchan.use_bbone_custom_handles
+
+ sub = row.column(align=True)
+ sub.label(text="In:")
+ sub.prop_search(pchan, "bbone_custom_handle_start", ob.pose, "bones", text="")
+ sub.prop(pchan, "use_bbone_relative_start_handle", text="Relative")
+
+ sub = row.column(align=True)
+ sub.label(text="Out:")
+ sub.prop_search(pchan, "bbone_custom_handle_end", ob.pose, "bones", text="")
+ sub.prop(pchan, "use_bbone_relative_end_handle", text="Relative")
+
+
class BONE_PT_relations(BoneButtonsPanel, Panel):
bl_label = "Relations"
@@ -193,6 +268,7 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
sub.prop(bone, "use_local_location")
+
class BONE_PT_display(BoneButtonsPanel, Panel):
bl_label = "Display"
@@ -348,28 +424,18 @@ class BONE_PT_deform(BoneButtonsPanel, Panel):
layout.active = bone.use_deform
- split = layout.split()
+ row = layout.row()
- col = split.column()
+ col = row.column(align=True)
col.label(text="Envelope:")
-
- sub = col.column(align=True)
- sub.prop(bone, "envelope_distance", text="Distance")
- sub.prop(bone, "envelope_weight", text="Weight")
+ col.prop(bone, "envelope_distance", text="Distance")
+ col.prop(bone, "envelope_weight", text="Weight")
col.prop(bone, "use_envelope_multiply", text="Multiply")
- sub = col.column(align=True)
- sub.label(text="Radius:")
- sub.prop(bone, "head_radius", text="Head")
- sub.prop(bone, "tail_radius", text="Tail")
-
- col = split.column()
- col.label(text="Curved Bones:")
-
- sub = col.column(align=True)
- sub.prop(bone, "bbone_segments", text="Segments")
- sub.prop(bone, "bbone_in", text="Ease In")
- sub.prop(bone, "bbone_out", text="Ease Out")
+ col = row.column(align=True)
+ col.label(text="Envelope Radius:")
+ col.prop(bone, "head_radius", text="Head")
+ col.prop(bone, "tail_radius", text="Tail")
class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 6d52a81456b..195eaf823f4 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -175,6 +175,22 @@ class BUILTIN_KSI_RotScale(KeyingSetInfo):
# ------------
+# Bendy Bones
+class BUILTIN_KSI_BendyBones(KeyingSetInfo):
+ """Insert a keyframe for each of the BBone shape properties"""
+ bl_label = "BBone Shape"
+
+ # poll - use callback for selected bones
+ poll = keyingsets_utils.RKS_POLL_selected_bones
+
+ # iterator - use callback for selected bones
+ iterator = keyingsets_utils.RKS_ITER_selected_bones
+
+ # generator - use generator for bendy bone properties
+ generate = keyingsets_utils.RKS_GEN_bendy_bones
+
+# ------------
+
# VisualLocation
class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
@@ -387,6 +403,9 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
ksi.doRot3d(ks, bone)
ksi.doScale(ks, bone)
+ # bbone properties?
+ ksi.doBBone(context, ks, bone)
+
# custom props?
ksi.doCustomProps(ks, bone)
@@ -466,6 +485,19 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
# ----------------
+ # bendy bone properties
+ def doBBone(ksi, context, ks, pchan):
+ bone = pchan.bone
+
+ # This check is crude, but is the best we can do for now
+ # It simply adds all of these if the bbone has segments
+ # (and the bone is a control bone). This may lead to some
+ # false positives...
+ if bone.bbone_segments > 1:
+ keyingsets_utils.RKS_GEN_bendy_bones(ksi, context, ks, pchan)
+
+ # ----------------
+
# custom properties
def doCustomProps(ksi, ks, bone):