forked from bartvdbraak/blender
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)
This commit is contained in:
parent
29a17d54da
commit
49aeee5a3d
@ -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)
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
||||
|
@ -79,12 +79,15 @@ typedef enum eAction_TransformFlags {
|
||||
ACT_TRANS_ROT = (1 << 1),
|
||||
/* scaling */
|
||||
ACT_TRANS_SCALE = (1 << 2),
|
||||
|
||||
|
||||
/* bbone shape - for all the parameters, provided one is set */
|
||||
ACT_TRANS_BBONE = (1 << 3),
|
||||
|
||||
/* strictly not a transform, but custom properties are also
|
||||
* quite often used in modern rigs
|
||||
*/
|
||||
ACT_TRANS_PROP = (1 << 3),
|
||||
|
||||
ACT_TRANS_PROP = (1 << 4),
|
||||
|
||||
/* all flags */
|
||||
ACT_TRANS_ONLY = (ACT_TRANS_LOC | ACT_TRANS_ROT | ACT_TRANS_SCALE),
|
||||
ACT_TRANS_ALL = (ACT_TRANS_ONLY | ACT_TRANS_PROP)
|
||||
|
@ -135,6 +135,7 @@ typedef struct Mat4 {
|
||||
float mat[4][4];
|
||||
} Mat4;
|
||||
|
||||
void equalize_bbone_bezier(float *data, int desired);
|
||||
void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
|
||||
|
||||
/* like EBONE_VISIBLE */
|
||||
|
@ -493,6 +493,8 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
|
||||
unit_axis_angle(chan->rotAxis, &chan->rotAngle);
|
||||
chan->size[0] = chan->size[1] = chan->size[2] = 1.0f;
|
||||
|
||||
chan->scaleIn = chan->scaleOut = 1.0f;
|
||||
|
||||
chan->limitmin[0] = chan->limitmin[1] = chan->limitmin[2] = -180.0f;
|
||||
chan->limitmax[0] = chan->limitmax[1] = chan->limitmax[2] = 180.0f;
|
||||
chan->stiffness[0] = chan->stiffness[1] = chan->stiffness[2] = 0.0f;
|
||||
@ -1280,6 +1282,18 @@ short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan,
|
||||
}
|
||||
}
|
||||
|
||||
if ((curves) || (flags & ACT_TRANS_BBONE) == 0) {
|
||||
/* bbone shape properties */
|
||||
pPtr = strstr(bPtr, "bbone_");
|
||||
if (pPtr) {
|
||||
flags |= ACT_TRANS_BBONE;
|
||||
|
||||
if (curves)
|
||||
BLI_addtail(curves, BLI_genericNodeN(fcu));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((curves) || (flags & ACT_TRANS_PROP) == 0) {
|
||||
/* custom properties only */
|
||||
pPtr = strstr(bPtr, "[\""); /* extra '"' comment here to keep my texteditor functionlist working :) */
|
||||
|
@ -429,7 +429,7 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
|
||||
/* ************* B-Bone support ******************* */
|
||||
|
||||
/* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */
|
||||
static void equalize_bezier(float *data, int desired)
|
||||
void equalize_bbone_bezier(float *data, int desired)
|
||||
{
|
||||
float *fp, totdist, ddist, dist, fac1, fac2;
|
||||
float pdist[MAX_BBONE_SUBDIV + 1];
|
||||
@ -499,13 +499,21 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
hlength1 = bone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
|
||||
hlength2 = bone->ease2 * length * 0.390464f;
|
||||
|
||||
/* evaluate next and prev bones */
|
||||
if (bone->flag & BONE_CONNECTED)
|
||||
prev = pchan->parent;
|
||||
else
|
||||
prev = NULL;
|
||||
/* get "next" and "prev" bones - these are used for handle calculations */
|
||||
if (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) {
|
||||
/* use the provided bones as the next/prev - leave blank to eliminate this effect altogether */
|
||||
prev = pchan->bbone_prev;
|
||||
next = pchan->bbone_next;
|
||||
}
|
||||
else {
|
||||
/* evaluate next and prev bones */
|
||||
if (bone->flag & BONE_CONNECTED)
|
||||
prev = pchan->parent;
|
||||
else
|
||||
prev = NULL;
|
||||
|
||||
next = pchan->child;
|
||||
next = pchan->child;
|
||||
}
|
||||
|
||||
/* find the handle points, since this is inside bone space, the
|
||||
* first point = (0, 0, 0)
|
||||
@ -525,10 +533,27 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
float difmat[4][4], result[3][3], imat3[3][3];
|
||||
|
||||
/* transform previous point inside this bone space */
|
||||
if (rest)
|
||||
copy_v3_v3(h1, prev->bone->arm_head);
|
||||
else
|
||||
copy_v3_v3(h1, prev->pose_head);
|
||||
if ((pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) &&
|
||||
(pchan->bboneflag & PCHAN_BBONE_CUSTOM_START_REL))
|
||||
{
|
||||
/* Use delta movement (from restpose), and apply this relative to the current bone's head */
|
||||
if (rest) {
|
||||
/* in restpose, arm_head == pose_head */
|
||||
h1[0] = h1[1] = h1[2] = 0.0f;
|
||||
}
|
||||
else {
|
||||
float delta[3];
|
||||
sub_v3_v3v3(delta, prev->pose_head, prev->bone->arm_head);
|
||||
sub_v3_v3v3(h1, pchan->pose_head, delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Use bone head as absolute position */
|
||||
if (rest)
|
||||
copy_v3_v3(h1, prev->bone->arm_head);
|
||||
else
|
||||
copy_v3_v3(h1, prev->pose_head);
|
||||
}
|
||||
mul_m4_v3(imat, h1);
|
||||
|
||||
if (prev->bone->segments > 1) {
|
||||
@ -564,10 +589,27 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
float difmat[4][4], result[3][3], imat3[3][3];
|
||||
|
||||
/* transform next point inside this bone space */
|
||||
if (rest)
|
||||
copy_v3_v3(h2, next->bone->arm_tail);
|
||||
else
|
||||
copy_v3_v3(h2, next->pose_tail);
|
||||
if ((pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES) &&
|
||||
(pchan->bboneflag & PCHAN_BBONE_CUSTOM_END_REL))
|
||||
{
|
||||
/* Use delta movement (from restpose), and apply this relative to the current bone's tail */
|
||||
if (rest) {
|
||||
/* in restpose, arm_tail == pose_tail */
|
||||
h2[0] = h2[1] = h2[2] = 0.0f;
|
||||
}
|
||||
else {
|
||||
float delta[3];
|
||||
sub_v3_v3v3(delta, next->pose_tail, next->bone->arm_tail);
|
||||
add_v3_v3v3(h2, pchan->pose_tail, delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Use bone tail as absolute position */
|
||||
if (rest)
|
||||
copy_v3_v3(h2, next->bone->arm_tail);
|
||||
else
|
||||
copy_v3_v3(h2, next->pose_tail);
|
||||
}
|
||||
mul_m4_v3(imat, h2);
|
||||
|
||||
/* if next bone is B-bone too, use average handle direction */
|
||||
@ -601,6 +643,50 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
roll2 = 0.0;
|
||||
}
|
||||
|
||||
/* Add effects from bbone properties over the top
|
||||
* - These properties allow users to hand-animate the
|
||||
* bone curve/shape, without having to resort to using
|
||||
* extra bones
|
||||
* - The "bone" level offsets are for defining the restpose
|
||||
* shape of the bone (e.g. for curved eyebrows for example).
|
||||
* -> In the viewport, it's needed to define what the rest pose
|
||||
* looks like
|
||||
* -> For "rest == 0", we also still need to have it present
|
||||
* so that we can "cancel out" this restpose when it comes
|
||||
* time to deform some geometry, it won't cause double transforms.
|
||||
* - The "pchan" level offsets are the ones that animators actually
|
||||
* end up animating
|
||||
*/
|
||||
{
|
||||
/* add extra rolls */
|
||||
roll1 += bone->roll1 + (!rest ? pchan->roll1 : 0.0f);
|
||||
roll2 += bone->roll2 + (!rest ? pchan->roll2 : 0.0f);
|
||||
|
||||
if (bone->flag & BONE_ADD_PARENT_END_ROLL) {
|
||||
if (prev) {
|
||||
if (prev->bone)
|
||||
roll1 += prev->bone->roll2;
|
||||
|
||||
if (!rest)
|
||||
roll1 += prev->roll2;
|
||||
}
|
||||
}
|
||||
|
||||
/* extra curve x / y */
|
||||
/* NOTE: Scale correction factors here are to compensate for some random floating-point glitches
|
||||
* when scaling up the bone or it's parent by a factor of approximately 8.15/6, which results
|
||||
* in the bone length getting scaled up too (from 1 to 8), causing the curve to flatten out.
|
||||
*/
|
||||
const float xscale_correction = (do_scale) ? scale[0] : 1.0f;
|
||||
const float yscale_correction = (do_scale) ? scale[2] : 1.0f;
|
||||
|
||||
h1[0] += (bone->curveInX + (!rest ? pchan->curveInX : 0.0f)) * xscale_correction;
|
||||
h1[2] += (bone->curveInY + (!rest ? pchan->curveInY : 0.0f)) * yscale_correction;
|
||||
|
||||
h2[0] += (bone->curveOutX + (!rest ? pchan->curveOutX : 0.0f)) * xscale_correction;
|
||||
h2[2] += (bone->curveOutY + (!rest ? pchan->curveOutY : 0.0f)) * yscale_correction;
|
||||
}
|
||||
|
||||
/* make curve */
|
||||
if (bone->segments > MAX_BBONE_SUBDIV)
|
||||
bone->segments = MAX_BBONE_SUBDIV;
|
||||
@ -610,20 +696,45 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
|
||||
equalize_bezier(data[0], bone->segments); /* note: does stride 4! */
|
||||
equalize_bbone_bezier(data[0], bone->segments); /* note: does stride 4! */
|
||||
|
||||
/* make transformation matrices for the segments for drawing */
|
||||
for (a = 0, fp = data[0]; a < bone->segments; a++, fp += 4) {
|
||||
sub_v3_v3v3(h1, fp + 4, fp);
|
||||
vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
|
||||
|
||||
|
||||
copy_m4_m3(result_array[a].mat, mat3);
|
||||
copy_v3_v3(result_array[a].mat[3], fp);
|
||||
|
||||
|
||||
if (do_scale) {
|
||||
/* correct for scaling when this matrix is used in scaled space */
|
||||
mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat);
|
||||
}
|
||||
|
||||
/* BBone scale... */
|
||||
{
|
||||
const int num_segments = bone->segments;
|
||||
|
||||
const float scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f);
|
||||
const float scaleFactorIn = 1.0f + (scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
|
||||
|
||||
const float scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 1.0f);
|
||||
const float scaleFactorOut = 1.0f + (scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments);
|
||||
|
||||
const float scalefac = scaleFactorIn * scaleFactorOut;
|
||||
float bscalemat[4][4], bscale[3];
|
||||
|
||||
bscale[0] = scalefac;
|
||||
bscale[1] = 1.0f;
|
||||
bscale[2] = scalefac;
|
||||
|
||||
size_to_mat4(bscalemat, bscale);
|
||||
|
||||
/* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
|
||||
/*mul_m4_series(result_array[a].mat, ibscalemat, result_array[a].mat, bscalemat);*/
|
||||
mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -669,7 +780,6 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
|
||||
float tmat[4][4];
|
||||
|
||||
invert_m4_m4(tmat, b_bone_rest[a].mat);
|
||||
|
||||
mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat);
|
||||
|
||||
if (use_quaternion)
|
||||
@ -683,10 +793,10 @@ static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float co[3], D
|
||||
float (*mat)[4] = b_bone[0].mat;
|
||||
float segment, y;
|
||||
int a;
|
||||
|
||||
|
||||
/* need to transform co back to bonespace, only need y */
|
||||
y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
|
||||
|
||||
|
||||
/* now calculate which of the b_bones are deforming this */
|
||||
segment = bone->length / ((float)bone->segments);
|
||||
a = (int)(y / segment);
|
||||
|
@ -535,7 +535,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
|
||||
|
||||
/* generic function to get the appropriate matrix for most target cases */
|
||||
/* The cases where the target can be object data have not been implemented */
|
||||
static void constraint_target_to_mat4(Object *ob, const char *substring, float mat[4][4], short from, short to, float headtail)
|
||||
static void constraint_target_to_mat4(Object *ob, const char *substring, float mat[4][4], short from, short to, short flag, float headtail)
|
||||
{
|
||||
/* Case OBJECT */
|
||||
if (substring[0] == '\0') {
|
||||
@ -573,6 +573,58 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m
|
||||
/* skip length interpolation if set to head */
|
||||
mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
|
||||
}
|
||||
else if ((pchan->bone) && (pchan->bone->segments > 1) && (flag & CONSTRAINT_BBONE_SHAPE)) {
|
||||
/* use point along bbone */
|
||||
Mat4 bbone[MAX_BBONE_SUBDIV];
|
||||
float tempmat[4][4];
|
||||
float loc[3], fac;
|
||||
|
||||
/* get bbone segments */
|
||||
b_bone_spline_setup(pchan, 0, bbone);
|
||||
|
||||
/* figure out which segment(s) the headtail value falls in */
|
||||
fac = (float)pchan->bone->segments * headtail;
|
||||
|
||||
if (fac >= pchan->bone->segments - 1) {
|
||||
/* special case: end segment doesn't get created properly... */
|
||||
float pt[3], sfac;
|
||||
int index;
|
||||
|
||||
/* bbone points are in bonespace, so need to move to posespace first */
|
||||
index = pchan->bone->segments - 1;
|
||||
mul_v3_m4v3(pt, pchan->pose_mat, bbone[index].mat[3]);
|
||||
|
||||
/* interpolate between last segment point and the endpoint */
|
||||
sfac = fac - (float)(pchan->bone->segments - 1); /* fac is just the "leftover" between penultimate and last points */
|
||||
interp_v3_v3v3(loc, pt, pchan->pose_tail, sfac);
|
||||
}
|
||||
else {
|
||||
/* get indices for finding interpolating between points along the bbone */
|
||||
float pt_a[3], pt_b[3], pt[3];
|
||||
int index_a, index_b;
|
||||
|
||||
index_a = floorf(fac);
|
||||
CLAMP(index_a, 0, MAX_BBONE_SUBDIV - 1);
|
||||
|
||||
index_b = ceilf(fac);
|
||||
CLAMP(index_b, 0, MAX_BBONE_SUBDIV - 1);
|
||||
|
||||
/* interpolate between these points */
|
||||
copy_v3_v3(pt_a, bbone[index_a].mat[3]);
|
||||
copy_v3_v3(pt_b, bbone[index_b].mat[3]);
|
||||
|
||||
interp_v3_v3v3(pt, pt_a, pt_b, fac - floorf(fac));
|
||||
|
||||
/* move the point from bone local space to pose space... */
|
||||
mul_v3_m4v3(loc, pchan->pose_mat, pt);
|
||||
}
|
||||
|
||||
/* use interpolated distance for subtarget */
|
||||
copy_m4_m4(tempmat, pchan->pose_mat);
|
||||
copy_v3_v3(tempmat[3], loc);
|
||||
|
||||
mul_m4_m4m4(mat, ob->obmat, tempmat);
|
||||
}
|
||||
else {
|
||||
float tempmat[4][4], loc[3];
|
||||
|
||||
@ -634,7 +686,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = {
|
||||
static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
|
||||
{
|
||||
if (VALID_CONS_TARGET(ct))
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
|
||||
else if (ct)
|
||||
unit_m4(ct->matrix);
|
||||
}
|
||||
@ -1102,7 +1154,7 @@ static void kinematic_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstrai
|
||||
bKinematicConstraint *data = con->data;
|
||||
|
||||
if (VALID_CONS_TARGET(ct))
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
|
||||
else if (ct) {
|
||||
if (data->flag & CONSTRAINT_IK_AUTO) {
|
||||
Object *ob = cob->ob;
|
||||
@ -1985,7 +2037,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
|
||||
/* firstly calculate the matrix the normal way, then let the py-function override
|
||||
* this matrix if it needs to do so
|
||||
*/
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
|
||||
|
||||
/* only execute target calculation if allowed */
|
||||
#ifdef WITH_PYTHON
|
||||
@ -2097,7 +2149,7 @@ static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintT
|
||||
unit_m4(ct->matrix);
|
||||
|
||||
/* get the transform matrix of the target */
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
|
||||
constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
|
||||
|
||||
/* determine where in transform range target is */
|
||||
/* data->type is mapped as follows for backwards compatibility:
|
||||
|
@ -4926,6 +4926,9 @@ static void direct_link_pose(FileData *fd, bPose *pose)
|
||||
pchan->child = newdataadr(fd, pchan->child);
|
||||
pchan->custom_tx = newdataadr(fd, pchan->custom_tx);
|
||||
|
||||
pchan->bbone_prev = newdataadr(fd, pchan->bbone_prev);
|
||||
pchan->bbone_next = newdataadr(fd, pchan->bbone_next);
|
||||
|
||||
direct_link_constraints(fd, &pchan->constraints);
|
||||
|
||||
pchan->prop = newdataadr(fd, pchan->prop);
|
||||
|
@ -34,6 +34,7 @@
|
||||
/* allow readfile to use deprecated functionality */
|
||||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
@ -161,6 +162,16 @@ static void do_version_action_editor_properties_region(ListBase *regionbase)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_version_bones_super_bbone(ListBase *lb)
|
||||
{
|
||||
for (Bone *bone = lb->first; bone; bone = bone->next) {
|
||||
bone->scaleIn = 1.0f;
|
||||
bone->scaleOut = 1.0f;
|
||||
|
||||
do_version_bones_super_bbone(&bone->childbase);
|
||||
}
|
||||
}
|
||||
|
||||
void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
{
|
||||
if (!MAIN_VERSION_ATLEAST(main, 270, 0)) {
|
||||
@ -1151,4 +1162,32 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(main, 277, 2)) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Bone", "float", "scaleIn")) {
|
||||
for (bArmature *arm = main->armature.first; arm; arm = arm->id.next) {
|
||||
do_version_bones_super_bbone(&arm->bonebase);
|
||||
}
|
||||
}
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "scaleIn")) {
|
||||
for (Object *ob = main->object.first; ob; ob = ob->id.next) {
|
||||
if (ob->pose) {
|
||||
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
/* see do_version_bones_super_bbone()... */
|
||||
pchan->scaleIn = 1.0f;
|
||||
pchan->scaleOut = 1.0f;
|
||||
|
||||
/* also make sure some legacy (unused for over a decade) flags are unset,
|
||||
* so that we can reuse them for stuff that matters now...
|
||||
* (i.e. POSE_IK_MAT, (unknown/unused x 4), POSE_HAS_IK)
|
||||
*
|
||||
* These seem to have been runtime flags used by the IK solver, but that stuff
|
||||
* should be able to be recalculated automatically anyway, so it should be fine.
|
||||
*/
|
||||
pchan->flag &= ~((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,15 @@ EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
|
||||
bone->segments = 1;
|
||||
bone->layer = arm->layer;
|
||||
|
||||
bone->roll1 = 0.0f;
|
||||
bone->roll2 = 0.0f;
|
||||
bone->curveInX = 0.0f;
|
||||
bone->curveInY = 0.0f;
|
||||
bone->curveOutX = 0.0f;
|
||||
bone->curveOutY = 0.0f;
|
||||
bone->scaleIn = 1.0f;
|
||||
bone->scaleOut = 1.0f;
|
||||
|
||||
return bone;
|
||||
}
|
||||
|
||||
@ -890,6 +899,16 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
|
||||
newbone->segments = 1;
|
||||
newbone->layer = ebone->layer;
|
||||
|
||||
newbone->roll1 = ebone->roll1;
|
||||
newbone->roll2 = ebone->roll2;
|
||||
newbone->curveInX = ebone->curveInX;
|
||||
newbone->curveInY = ebone->curveInY;
|
||||
newbone->curveOutX = ebone->curveOutX;
|
||||
newbone->curveOutY = ebone->curveOutY;
|
||||
newbone->scaleIn = ebone->scaleIn;
|
||||
newbone->scaleOut = ebone->scaleOut;
|
||||
|
||||
|
||||
BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
|
||||
|
||||
if (flipbone && forked) { // only set if mirror edit
|
||||
|
@ -170,6 +170,11 @@ typedef struct tPChanFCurveLink {
|
||||
float oldangle;
|
||||
float oldaxis[3];
|
||||
|
||||
float roll1, roll2; /* old bbone values (to be restored along with the transform properties) */
|
||||
float curveInX, curveInY; /* (NOTE: we haven't renamed these this time, as their names are already long enough) */
|
||||
float curveOutX, curveOutY;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
struct IDProperty *oldprops; /* copy of custom properties at start of operator (to be restored before each modal step) */
|
||||
} tPChanFCurveLink;
|
||||
|
||||
|
@ -456,7 +456,16 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
|
||||
eBone->rad_tail = curBone->rad_tail;
|
||||
eBone->segments = curBone->segments;
|
||||
eBone->layer = curBone->layer;
|
||||
|
||||
|
||||
eBone->roll1 = curBone->roll1;
|
||||
eBone->roll2 = curBone->roll2;
|
||||
eBone->curveInX = curBone->curveInX;
|
||||
eBone->curveInY = curBone->curveInY;
|
||||
eBone->curveOutX = curBone->curveOutX;
|
||||
eBone->curveOutY = curBone->curveOutY;
|
||||
eBone->scaleIn = curBone->scaleIn;
|
||||
eBone->scaleOut = curBone->scaleOut;
|
||||
|
||||
if (curBone->prop)
|
||||
eBone->prop = IDP_CopyProperty(curBone->prop);
|
||||
|
||||
@ -611,7 +620,17 @@ void ED_armature_from_edit(bArmature *arm)
|
||||
newBone->rad_tail = eBone->rad_tail;
|
||||
newBone->segments = eBone->segments;
|
||||
newBone->layer = eBone->layer;
|
||||
|
||||
|
||||
newBone->roll1 = eBone->roll1;
|
||||
newBone->roll2 = eBone->roll2;
|
||||
newBone->curveInX = eBone->curveInX;
|
||||
newBone->curveInY = eBone->curveInY;
|
||||
newBone->curveOutX = eBone->curveOutX;
|
||||
newBone->curveOutY = eBone->curveOutY;
|
||||
newBone->scaleIn = eBone->scaleIn;
|
||||
newBone->scaleOut = eBone->scaleOut;
|
||||
|
||||
|
||||
if (eBone->prop)
|
||||
newBone->prop = IDP_CopyProperty(eBone->prop);
|
||||
}
|
||||
|
@ -1451,6 +1451,15 @@ static EditBone *add_editbonetolist(char *name, ListBase *list)
|
||||
bone->segments = 1;
|
||||
bone->layer = 1; //arm->layer;
|
||||
|
||||
bone->roll1 = 0.0f;
|
||||
bone->roll2 = 0.0f;
|
||||
bone->curveInX = 0.0f;
|
||||
bone->curveInY = 0.0f;
|
||||
bone->curveOutX = 0.0f;
|
||||
bone->curveOutY = 0.0f;
|
||||
bone->scaleIn = 1.0f;
|
||||
bone->scaleOut = 1.0f;
|
||||
|
||||
return bone;
|
||||
}
|
||||
#endif
|
||||
|
@ -303,8 +303,8 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa
|
||||
MEM_freeN(path);
|
||||
}
|
||||
|
||||
/* helper for apply() - perform sliding for custom properties */
|
||||
static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
|
||||
/* helper for apply() - perform sliding for custom properties or bbone properties */
|
||||
static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[])
|
||||
{
|
||||
PointerRNA ptr = {{NULL}};
|
||||
LinkData *ld;
|
||||
@ -313,8 +313,10 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
|
||||
/* setup pointer RNA for resolving paths */
|
||||
RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr);
|
||||
|
||||
/* custom properties are just denoted using ["..."][etc.] after the end of the base path,
|
||||
* so just check for opening pair after the end of the path
|
||||
/* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
|
||||
* so just check for opening pair after the end of the path
|
||||
* - bbone properties are similar, but they always start with a prefix "bbone_*",
|
||||
* so a similar method should work here for those too
|
||||
*/
|
||||
for (ld = pfl->fcurves.first; ld; ld = ld->next) {
|
||||
FCurve *fcu = (FCurve *)ld->data;
|
||||
@ -328,7 +330,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
|
||||
* - pPtr is the chunk of the path which is left over
|
||||
*/
|
||||
bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
|
||||
pPtr = strstr(bPtr, "[\""); /* dummy " for texteditor bugs */
|
||||
pPtr = strstr(bPtr, prop_prefix);
|
||||
|
||||
if (pPtr) {
|
||||
/* use RNA to try and get a handle on this property, then, assuming that it is just
|
||||
@ -517,9 +519,16 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
|
||||
}
|
||||
}
|
||||
|
||||
if (pchan->flag & POSE_BBONE_SHAPE) {
|
||||
/* bbone properties - they all start a "bbone_" prefix */
|
||||
pose_slide_apply_props(pso, pfl, "bbone_");
|
||||
}
|
||||
|
||||
if (pfl->oldprops) {
|
||||
/* not strictly a transform, but contributes to the pose produced in many rigs */
|
||||
pose_slide_apply_props(pso, pfl);
|
||||
/* not strictly a transform, but custom properties contribute to the pose produced in many rigs
|
||||
* (e.g. the facial rigs used in Sintel)
|
||||
*/
|
||||
pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,10 +367,26 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
|
||||
axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
|
||||
}
|
||||
|
||||
/* B-Bone posing options should also be included... */
|
||||
pchan->curveInX = chan->curveInX;
|
||||
pchan->curveInY = chan->curveInY;
|
||||
pchan->curveOutX = chan->curveOutX;
|
||||
pchan->curveOutY = chan->curveOutY;
|
||||
|
||||
pchan->roll1 = chan->roll1;
|
||||
pchan->roll2 = chan->roll2;
|
||||
pchan->scaleIn = chan->scaleIn;
|
||||
pchan->scaleOut = chan->scaleOut;
|
||||
|
||||
/* paste flipped pose? */
|
||||
if (flip) {
|
||||
pchan->loc[0] *= -1;
|
||||
|
||||
pchan->curveInX *= -1;
|
||||
pchan->curveOutX *= -1;
|
||||
pchan->roll1 *= -1; // XXX?
|
||||
pchan->roll2 *= -1; // XXX?
|
||||
|
||||
/* has to be done as eulers... */
|
||||
if (pchan->rotmode > 0) {
|
||||
pchan->eul[1] *= -1;
|
||||
@ -540,6 +556,9 @@ static void pchan_clear_scale(bPoseChannel *pchan)
|
||||
pchan->size[1] = 1.0f;
|
||||
if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
|
||||
pchan->size[2] = 1.0f;
|
||||
|
||||
pchan->scaleIn = 1.0f;
|
||||
pchan->scaleOut = 1.0f;
|
||||
}
|
||||
|
||||
/* clear location of pose-channel */
|
||||
@ -650,6 +669,15 @@ static void pchan_clear_rot(bPoseChannel *pchan)
|
||||
zero_v3(pchan->eul);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear also Bendy Bone stuff - Roll is obvious, but Curve X/Y stuff is also kindof rotational in nature... */
|
||||
pchan->roll1 = 0.0f;
|
||||
pchan->roll2 = 0.0f;
|
||||
|
||||
pchan->curveInX = 0.0f;
|
||||
pchan->curveInY = 0.0f;
|
||||
pchan->curveOutX = 0.0f;
|
||||
pchan->curveOutY = 0.0f;
|
||||
}
|
||||
|
||||
/* clear loc/rot/scale of pose-channel */
|
||||
|
@ -71,7 +71,7 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
|
||||
ListBase curves = {NULL, NULL};
|
||||
int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
|
||||
|
||||
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE);
|
||||
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
|
||||
|
||||
/* check if any transforms found... */
|
||||
if (transFlags) {
|
||||
@ -96,6 +96,8 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
|
||||
pchan->flag |= POSE_ROT;
|
||||
if (transFlags & ACT_TRANS_SCALE)
|
||||
pchan->flag |= POSE_SIZE;
|
||||
if (transFlags & ACT_TRANS_BBONE)
|
||||
pchan->flag |= POSE_BBONE_SHAPE;
|
||||
|
||||
/* store current transforms */
|
||||
copy_v3_v3(pfl->oldloc, pchan->loc);
|
||||
@ -105,6 +107,16 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
|
||||
copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
|
||||
pfl->oldangle = pchan->rotAngle;
|
||||
|
||||
/* store current bbone values */
|
||||
pfl->roll1 = pchan->roll1;
|
||||
pfl->roll2 = pchan->roll2;
|
||||
pfl->curveInX = pchan->curveInX;
|
||||
pfl->curveInY = pchan->curveInY;
|
||||
pfl->curveOutX = pchan->curveOutX;
|
||||
pfl->curveOutY = pchan->curveOutY;
|
||||
pfl->scaleIn = pchan->scaleIn;
|
||||
pfl->scaleOut = pchan->scaleOut;
|
||||
|
||||
/* make copy of custom properties */
|
||||
if (pchan->prop && (transFlags & ACT_TRANS_PROP))
|
||||
pfl->oldprops = IDP_CopyProperty(pchan->prop);
|
||||
@ -133,6 +145,7 @@ void poseAnim_mapping_get(bContext *C, ListBase *pfLinks, Object *ob, bAction *a
|
||||
fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,6 +212,16 @@ void poseAnim_mapping_reset(ListBase *pfLinks)
|
||||
copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
|
||||
pchan->rotAngle = pfl->oldangle;
|
||||
|
||||
/* store current bbone values */
|
||||
pchan->roll1 = pfl->roll1;
|
||||
pchan->roll2 = pfl->roll2;
|
||||
pchan->curveInX = pfl->curveInX;
|
||||
pchan->curveInY = pfl->curveInY;
|
||||
pchan->curveOutX = pfl->curveOutX;
|
||||
pchan->curveOutY = pfl->curveOutY;
|
||||
pchan->scaleIn = pfl->scaleIn;
|
||||
pchan->scaleOut = pfl->scaleOut;
|
||||
|
||||
/* just overwrite values of properties from the stored copies (there should be some) */
|
||||
if (pfl->oldprops)
|
||||
IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
|
||||
|
@ -74,7 +74,10 @@ typedef struct EditBone {
|
||||
float xwidth, length, zwidth; /* put them in order! transform uses this as scale */
|
||||
float ease1, ease2;
|
||||
float rad_head, rad_tail;
|
||||
|
||||
float roll1, roll2;
|
||||
float curveOutX, curveOutY;
|
||||
float curveInX, curveInY;
|
||||
float scaleIn, scaleOut;
|
||||
float oldlength; /* for envelope scaling */
|
||||
|
||||
short segments;
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_curve.h"
|
||||
|
||||
|
||||
#include "BIF_gl.h"
|
||||
@ -1093,20 +1094,101 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
|
||||
/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
|
||||
*
|
||||
* This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
|
||||
* position here anyway), and that we can simply apply the bbone settings to get the desired effect...
|
||||
*/
|
||||
static void ebone_spline_preview(EditBone *ebone, Mat4 result_array[MAX_BBONE_SUBDIV])
|
||||
{
|
||||
float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
|
||||
float mat3[3][3];
|
||||
float data[MAX_BBONE_SUBDIV + 1][4], *fp;
|
||||
int a;
|
||||
|
||||
length = ebone->length;
|
||||
|
||||
hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
|
||||
hlength2 = ebone->ease2 * length * 0.390464f;
|
||||
|
||||
/* find the handle points, since this is inside bone space, the
|
||||
* first point = (0, 0, 0)
|
||||
* last point = (0, length, 0)
|
||||
*
|
||||
* we also just apply all the "extra effects", since they're the whole reason we're doing this...
|
||||
*/
|
||||
h1[0] = ebone->curveInX;
|
||||
h1[1] = hlength1;
|
||||
h1[2] = ebone->curveInY;
|
||||
roll1 = ebone->roll1;
|
||||
|
||||
h2[0] = ebone->curveOutX;
|
||||
h2[1] = -hlength2;
|
||||
h2[2] = ebone->curveOutY;
|
||||
roll2 = ebone->roll2;
|
||||
|
||||
/* make curve */
|
||||
if (ebone->segments > MAX_BBONE_SUBDIV)
|
||||
ebone->segments = MAX_BBONE_SUBDIV;
|
||||
|
||||
BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
|
||||
|
||||
equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
|
||||
|
||||
/* make transformation matrices for the segments for drawing */
|
||||
for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
|
||||
sub_v3_v3v3(h1, fp + 4, fp);
|
||||
vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
|
||||
|
||||
copy_m4_m3(result_array[a].mat, mat3);
|
||||
copy_v3_v3(result_array[a].mat[3], fp);
|
||||
|
||||
/* "extra" scale facs... */
|
||||
{
|
||||
const int num_segments = ebone->segments;
|
||||
|
||||
const float scaleFactorIn = 1.0f + (ebone->scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
|
||||
const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments);
|
||||
|
||||
const float scalefac = scaleFactorIn * scaleFactorOut;
|
||||
float bscalemat[4][4], bscale[3];
|
||||
|
||||
bscale[0] = scalefac;
|
||||
bscale[1] = 1.0f;
|
||||
bscale[2] = scalefac;
|
||||
|
||||
size_to_mat4(bscalemat, bscale);
|
||||
|
||||
/* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
|
||||
mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebone, float xwidth, float length, float zwidth)
|
||||
{
|
||||
int segments = 0;
|
||||
|
||||
if (pchan)
|
||||
segments = pchan->bone->segments;
|
||||
else if (ebone)
|
||||
segments = ebone->segments;
|
||||
|
||||
if ((segments > 1) && (pchan)) {
|
||||
if (segments > 1) {
|
||||
float dlen = length / (float)segments;
|
||||
Mat4 bbone[MAX_BBONE_SUBDIV];
|
||||
int a;
|
||||
|
||||
b_bone_spline_setup(pchan, 0, bbone);
|
||||
|
||||
|
||||
if (pchan) {
|
||||
b_bone_spline_setup(pchan, 0, bbone);
|
||||
}
|
||||
else if (ebone) {
|
||||
ebone_spline_preview(ebone, bbone);
|
||||
}
|
||||
|
||||
for (a = 0; a < segments; a++) {
|
||||
glPushMatrix();
|
||||
glMultMatrixf(bbone[a].mat);
|
||||
@ -1177,7 +1259,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
|
||||
else
|
||||
UI_ThemeColor(TH_BONE_SOLID);
|
||||
|
||||
draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
|
||||
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
|
||||
|
||||
/* disable solid drawing */
|
||||
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
|
||||
@ -1190,7 +1272,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
|
||||
if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
|
||||
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
@ -1200,7 +1282,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
|
||||
}
|
||||
}
|
||||
|
||||
draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);
|
||||
draw_b_bone_boxes(OB_WIRE, pchan, ebone, xwidth, length, zwidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,8 @@ typedef struct bPoseChannel {
|
||||
char constflag; /* for quick detecting which constraints affect this channel */
|
||||
char selectflag; /* copy of bone flag, so you can work with library armatures, not for runtime use */
|
||||
char drawflag;
|
||||
char pad0[5];
|
||||
char bboneflag;
|
||||
char pad0[4];
|
||||
|
||||
struct Bone *bone; /* set on read file or rebuild pose */
|
||||
struct bPoseChannel *parent; /* set on read file or rebuild pose */
|
||||
@ -242,7 +243,16 @@ typedef struct bPoseChannel {
|
||||
float ikstretch;
|
||||
float ikrotweight; /* weight of joint rotation constraint */
|
||||
float iklinweight; /* weight of joint stretch constraint */
|
||||
|
||||
|
||||
/* curved bones settings - these are for animating, and are applied on top of the copies in pchan->bone */
|
||||
float roll1, roll2;
|
||||
float curveInX, curveInY;
|
||||
float curveOutX, curveOutY;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
struct bPoseChannel *bbone_prev; /* next/prev bones to use as handle references when calculating bbones (optional) */
|
||||
struct bPoseChannel *bbone_next;
|
||||
|
||||
void *temp; /* use for outliner */
|
||||
} bPoseChannel;
|
||||
|
||||
@ -253,17 +263,17 @@ typedef enum ePchan_Flag {
|
||||
POSE_LOC = (1 << 0),
|
||||
POSE_ROT = (1 << 1),
|
||||
POSE_SIZE = (1 << 2),
|
||||
/* old IK/cache stuff... */
|
||||
#if 0
|
||||
POSE_IK_MAT = (1 << 3),
|
||||
POSE_UNUSED2 = (1 << 4),
|
||||
POSE_UNUSED3 = (1 << 5),
|
||||
POSE_UNUSED4 = (1 << 6),
|
||||
POSE_UNUSED5 = (1 << 7),
|
||||
/* has Standard IK */
|
||||
POSE_HAS_IK = (1 << 8),
|
||||
#endif
|
||||
/* IK/Pose solving*/
|
||||
|
||||
/* old IK/cache stuff
|
||||
* - used to be here from (1 << 3) to (1 << 8)
|
||||
* but has been repurposed since 2.77.2
|
||||
* as they haven't been used in over 10 years
|
||||
*/
|
||||
|
||||
/* has BBone deforms */
|
||||
POSE_BBONE_SHAPE = (1 << 3),
|
||||
|
||||
/* IK/Pose solving */
|
||||
POSE_CHAIN = (1 << 9),
|
||||
POSE_DONE = (1 << 10),
|
||||
/* visualization */
|
||||
@ -318,6 +328,16 @@ typedef enum ePchan_DrawFlag {
|
||||
#define PCHAN_CUSTOM_DRAW_SIZE(pchan) \
|
||||
(pchan)->custom_scale * (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length)
|
||||
|
||||
/* PoseChannel->bboneflag */
|
||||
typedef enum ePchan_BBoneFlag {
|
||||
/* Use custom reference bones (for roll and handle alignment), instead of immediate neighbours */
|
||||
PCHAN_BBONE_CUSTOM_HANDLES = (1 << 1),
|
||||
/* Evaluate start handle as being "relative" */
|
||||
PCHAN_BBONE_CUSTOM_START_REL = (1 << 2),
|
||||
/* Evaluate end handle as being "relative" */
|
||||
PCHAN_BBONE_CUSTOM_END_REL = (1 << 3),
|
||||
} ePchan_BBoneFlag;
|
||||
|
||||
/* PoseChannel->rotmode and Object->rotmode */
|
||||
typedef enum eRotationModes {
|
||||
/* quaternion rotations (default, and for older Blender versions) */
|
||||
|
@ -68,11 +68,18 @@ typedef struct Bone {
|
||||
float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */
|
||||
float ease1, ease2; /* length of bezier handles */
|
||||
float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well, parent->rad_tip overrides rad_head */
|
||||
|
||||
|
||||
float roll1, roll2; /* curved bones settings - these define the "restpose" for a curved bone */
|
||||
float curveInX, curveInY;
|
||||
float curveOutX, curveOutY;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
float size[3]; /* patch for upward compat, UNUSED! */
|
||||
int layer; /* layers that bone appears on */
|
||||
short segments; /* for B-bones */
|
||||
short pad[1];
|
||||
|
||||
short pad1;
|
||||
|
||||
} Bone;
|
||||
|
||||
typedef struct bArmature {
|
||||
@ -204,7 +211,8 @@ typedef enum eBone_Flag {
|
||||
BONE_TRANSFORM_CHILD = (1 << 20), /* Indicates that a parent is also being transformed */
|
||||
BONE_UNSELECTABLE = (1 << 21), /* bone cannot be selected */
|
||||
BONE_NO_LOCAL_LOCATION = (1 << 22), /* bone location is in armature space */
|
||||
BONE_RELATIVE_PARENTING = (1 << 23) /* object child will use relative transform (like deform) */
|
||||
BONE_RELATIVE_PARENTING = (1 << 23), /* object child will use relative transform (like deform) */
|
||||
BONE_ADD_PARENT_END_ROLL = (1 << 24) /* it will add the parent end roll to the inroll */
|
||||
|
||||
} eBone_Flag;
|
||||
|
||||
|
@ -516,7 +516,9 @@ typedef enum eBConstraint_Flags {
|
||||
/* indicates that constraint was added locally (i.e. didn't come from the proxy-lib) */
|
||||
CONSTRAINT_PROXY_LOCAL = (1<<8),
|
||||
/* indicates that constraint is temporarily disabled (only used in GE) */
|
||||
CONSTRAINT_OFF = (1<<9)
|
||||
CONSTRAINT_OFF = (1<<9),
|
||||
/* use bbone curve shape when calculating headtail values */
|
||||
CONSTRAINT_BBONE_SHAPE = (1<<10),
|
||||
} eBConstraint_Flags;
|
||||
|
||||
/* bConstraint->ownspace/tarspace */
|
||||
|
@ -482,6 +482,82 @@ static void rna_Armature_transform(struct bArmature *arm, float *mat)
|
||||
|
||||
#else
|
||||
|
||||
/* Settings for curved bbone settings - The posemode values get applied over the top of the editmode ones */
|
||||
void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
|
||||
{
|
||||
#define RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone) \
|
||||
{ \
|
||||
if (is_posebone) \
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); \
|
||||
else \
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data"); \
|
||||
} (void)0;
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* Roll In/Out */
|
||||
prop = RNA_def_property(srna, "bbone_rollin", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "roll1");
|
||||
RNA_def_property_range(prop, -M_PI * 2.0f, M_PI * 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Roll In", "Roll offset for the start of the B-Bone, adjusts twist");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_rollout", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "roll2");
|
||||
RNA_def_property_range(prop, -M_PI * 2.0f, M_PI * 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Roll Out", "Roll offset for the end of the B-Bone, adjusts twist");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
if (is_posebone == false) {
|
||||
prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Inherit End Roll", "Use Roll Out of parent bone as Roll In of its children");
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ADD_PARENT_END_ROLL);
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
|
||||
}
|
||||
|
||||
/* Curve X/Y Offsets */
|
||||
prop = RNA_def_property(srna, "bbone_curveinx", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curveInX");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_ui_text(prop, "In X", "X-axis handle offset for start of the B-Bone's curve, adjusts curvature");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_curveiny", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curveInY");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_ui_text(prop, "In Y", "Y-axis handle offset for start of the B-Bone's curve, adjusts curvature");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_curveoutx", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curveOutX");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_ui_text(prop, "Out X", "X-axis handle offset for end of the B-Bone's curve, adjusts curvature");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_curveouty", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curveOutY");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_ui_text(prop, "Out Y", "Y-axis handle offset for end of the B-Bone's curve, adjusts curvature");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
/* Scale In/Out */
|
||||
prop = RNA_def_property(srna, "bbone_scalein", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scaleIn");
|
||||
RNA_def_property_range(prop, 0.0f, 5.0f);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Scale In", "Scale factor for start of the B-Bone, adjusts thickness (for tapering effects)");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_scaleout", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scaleOut");
|
||||
RNA_def_property_range(prop, 0.0f, 5.0f);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Scale Out", "Scale factor for end of the B-Bone, adjusts thickness (for tapering effects)");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
#undef RNA_DEF_CURVEBONE_UPDATE
|
||||
}
|
||||
|
||||
static void rna_def_bone_common(StructRNA *srna, int editbone)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
@ -653,6 +729,7 @@ static void rna_def_bone(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Children", "Bones which are children of this bone");
|
||||
|
||||
rna_def_bone_common(srna, 0);
|
||||
rna_def_bone_curved_common(srna, 0);
|
||||
|
||||
/* XXX should we define this in PoseChannel wrapping code instead?
|
||||
* But PoseChannels directly get some of their flags from here... */
|
||||
@ -766,6 +843,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
|
||||
|
||||
rna_def_bone_common(srna, 1);
|
||||
rna_def_bone_curved_common(srna, 0);
|
||||
|
||||
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_A);
|
||||
|
@ -483,6 +483,21 @@ static EnumPropertyItem constraint_distance_items[] = {
|
||||
};
|
||||
|
||||
|
||||
static void rna_def_constraint_headtail_common(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_bbone_shape", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "bConstraint", "flag", CONSTRAINT_BBONE_SHAPE);
|
||||
RNA_def_property_ui_text(prop, "Follow B-Bone", "Follow shape of B-Bone segments when calculating Head/Tail position");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
}
|
||||
|
||||
static void rna_def_constrainttarget(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@ -787,10 +802,7 @@ static void rna_def_constraint_track_to(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "TrackToConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Track To Constraint", "Aim the constrained object toward the target");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bTrackToConstraint", "data");
|
||||
|
||||
@ -831,10 +843,7 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "CopyLocationConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copy the location of the target");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bLocateLikeConstraint", "data");
|
||||
|
||||
@ -1022,10 +1031,7 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "CopyTransformsConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Copy Transforms Constraint", "Copy all the transforms of the target");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bTransLikeConstraint", "data");
|
||||
|
||||
@ -1200,10 +1206,7 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(srna, "Locked Track Constraint",
|
||||
"Point toward the target along the track axis, while locking the other axis");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bLockTrackConstraint", "data");
|
||||
|
||||
@ -1327,10 +1330,7 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "StretchToConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Stretch To Constraint", "Stretch to meet the target object");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bStretchToConstraint", "data");
|
||||
|
||||
@ -2122,10 +2122,7 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "LimitDistanceConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Limit Distance Constraint", "Limit the distance from target object");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bDistLimitConstraint", "data");
|
||||
|
||||
@ -2236,10 +2233,7 @@ static void rna_def_constraint_damped_track(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(srna, "Damped Track Constraint",
|
||||
"Point toward target by taking the shortest rotation path");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bDampTrackConstraint", "data");
|
||||
|
||||
@ -2396,10 +2390,7 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "PivotConstraint", "Constraint");
|
||||
RNA_def_struct_ui_text(srna, "Pivot Constraint", "Rotate around a different point");
|
||||
|
||||
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
|
||||
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
rna_def_constraint_headtail_common(srna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bPivotConstraint", "data");
|
||||
|
||||
|
@ -197,6 +197,8 @@ void rna_def_animdata_common(struct StructRNA *srna);
|
||||
void rna_def_animviz_common(struct StructRNA *srna);
|
||||
void rna_def_motionpath_common(struct StructRNA *srna);
|
||||
|
||||
void rna_def_bone_curved_common(struct StructRNA *srna, bool is_posebone);
|
||||
|
||||
void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable);
|
||||
void rna_def_mtex_common(struct BlenderRNA *brna, struct StructRNA *srna, const char *begin, const char *activeget,
|
||||
const char *activeset, const char *activeeditable, const char *structname,
|
||||
|
@ -872,6 +872,50 @@ static void rna_def_pose_channel(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Rotation Mode", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
/* Curved bones settings - Applied on top of restpose values */
|
||||
rna_def_bone_curved_common(srna, true);
|
||||
|
||||
/* Custom BBone next/prev sources */
|
||||
prop = RNA_def_property(srna, "use_bbone_custom_handles", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_HANDLES);
|
||||
RNA_def_property_ui_text(prop, "Use Custom Handle References",
|
||||
"Use custom reference bones as handles for B-Bones instead of next/previous bones, "
|
||||
"leave these blank to use only B-Bone offset properties to control the shape");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "bbone_prev");
|
||||
RNA_def_property_struct_type(prop, "PoseBone");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Start Handle",
|
||||
"Bone that serves as the start handle for the B-Bone curve");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL);
|
||||
RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle",
|
||||
"Use treat custom start handle position as a relative value");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_custom_handle_end", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "bbone_next");
|
||||
RNA_def_property_struct_type(prop, "PoseBone");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "B-Bone End Handle",
|
||||
"Bone that serves as the end handle for the B-Bone curve");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL);
|
||||
RNA_def_property_ui_text(prop, "Relative B-Bone End Handle",
|
||||
"Use treat custom end handle position as a relative value");
|
||||
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
|
||||
|
||||
/* transform matrices - should be read-only since these are set directly by AnimSys evaluation */
|
||||
prop = RNA_def_property(srna, "matrix_channel", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "chan_mat");
|
||||
|
Loading…
Reference in New Issue
Block a user