This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/armature/armature_utils.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

964 lines
29 KiB
C
Raw Normal View History

/*
* 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.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
/** \file
* \ingroup edarmature
*/
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_string_utils.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "DEG_depsgraph.h"
#include "ED_armature.h"
#include "ED_util.h"
#include "armature_intern.h"
/* *************************************************************** */
/* Validation */
/* Sync selection to parent for connected children */
void ED_armature_edit_sync_selection(ListBase *edbo)
{
EditBone *ebo;
for (ebo = edbo->first; ebo; ebo = ebo->next) {
/* if bone is not selectable, we shouldn't alter this setting... */
if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
2019-04-22 09:19:45 +10:00
if (ebo->parent->flag & BONE_TIPSEL) {
ebo->flag |= BONE_ROOTSEL;
2019-04-22 09:19:45 +10:00
}
else {
ebo->flag &= ~BONE_ROOTSEL;
2019-04-22 09:19:45 +10:00
}
}
2019-04-22 09:19:45 +10:00
if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) {
ebo->flag |= BONE_SELECTED;
2019-04-22 09:19:45 +10:00
}
else {
ebo->flag &= ~BONE_SELECTED;
2019-04-22 09:19:45 +10:00
}
}
}
}
void ED_armature_edit_validate_active(struct bArmature *arm)
{
EditBone *ebone = arm->act_edbone;
if (ebone) {
2019-04-22 09:19:45 +10:00
if (ebone->flag & BONE_HIDDEN_A) {
arm->act_edbone = NULL;
2019-04-22 09:19:45 +10:00
}
}
}
/* Update the layers_used variable after bones are moved between layer
* NOTE: Used to be done in drawing code in 2.7, but that won't work with
* Copy-on-Write, as drawing uses evaluated copies.
*/
void ED_armature_edit_refresh_layer_used(bArmature *arm)
{
arm->layer_used = 0;
LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
arm->layer_used |= ebo->layer;
}
}
/* *************************************************************** */
/* Bone Operations */
/* XXX bone_looper is only to be used when we want to access settings
* (i.e. editability/visibility/selected) that context doesn't offer */
int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *))
{
/* We want to apply the function bone_func to every bone
* in an armature -- feed bone_looper the first bone and
* a pointer to the bone_func and watch it go!. The int count
* can be useful for counting bones with a certain property
* (e.g. skinnable)
*/
int count = 0;
if (bone) {
/* only do bone_func if the bone is non null */
count += bone_func(ob, bone, data);
/* try to execute bone_func for the first child */
count += bone_looper(ob, bone->childbase.first, data, bone_func);
/* try to execute bone_func for the next bone at this
* depth of the recursion.
*/
count += bone_looper(ob, bone->next, data, bone_func);
}
return count;
}
/* *************************************************************** */
/* Bone Removal */
void bone_free(bArmature *arm, EditBone *bone)
{
2019-04-22 09:19:45 +10:00
if (arm->act_edbone == bone) {
arm->act_edbone = NULL;
2019-04-22 09:19:45 +10:00
}
if (bone->prop) {
IDP_FreeProperty(bone->prop);
}
/* Clear references from other edit bones. */
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->bbone_next == bone) {
ebone->bbone_next = NULL;
}
if (ebone->bbone_prev == bone) {
ebone->bbone_prev = NULL;
}
}
BLI_freelinkN(arm->edbo, bone);
}
/**
* \param clear_connected: When false caller is responsible for keeping the flag in a valid state.
*/
void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
{
EditBone *curBone;
/* Find any bones that refer to this bone */
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (curBone->parent == exBone) {
curBone->parent = exBone->parent;
if (clear_connected) {
curBone->flag &= ~BONE_CONNECTED;
}
}
}
bone_free(arm, exBone);
}
void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone)
{
ED_armature_ebone_remove_ex(arm, exBone, true);
}
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
{
for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
2019-04-22 09:19:45 +10:00
if (ebone_child == ebone_parent) {
return true;
2019-04-22 09:19:45 +10:00
}
}
return false;
}
/**
* Finds the first parent shared by \a ebone_child
*
* \param ebone_child: Children bones to search
* \param ebone_child_tot: Size of the ebone_child array
* \return The shared parent or NULL.
*/
EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
{
#define EBONE_TEMP_UINT(ebone) (*((uint *)(&((ebone)->temp))))
/* clear all */
2020-09-09 18:41:07 +02:00
for (uint i = 0; i < ebone_child_tot; i++) {
for (EditBone *ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
EBONE_TEMP_UINT(ebone_iter) = 0;
}
}
/* accumulate */
2020-09-09 18:41:07 +02:00
for (uint i = 0; i < ebone_child_tot; i++) {
for (EditBone *ebone_iter = ebone_child[i]->parent; ebone_iter;
ebone_iter = ebone_iter->parent) {
EBONE_TEMP_UINT(ebone_iter) += 1;
}
}
/* only need search the first chain */
2020-09-09 18:41:07 +02:00
for (EditBone *ebone_iter = ebone_child[0]->parent; ebone_iter;
ebone_iter = ebone_iter->parent) {
if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
return ebone_iter;
}
}
#undef EBONE_TEMP_UINT
return NULL;
}
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
{
float delta[3], roll;
/* Find the current bone matrix */
sub_v3_v3v3(delta, ebone->tail, ebone->head);
roll = ebone->roll;
if (!normalize_v3(delta)) {
/* Use the orientation of the parent bone if any. */
const EditBone *ebone_parent = ebone->parent;
if (ebone_parent) {
sub_v3_v3v3(delta, ebone_parent->tail, ebone_parent->head);
normalize_v3(delta);
roll = ebone_parent->roll;
}
}
vec_roll_to_mat3_normalized(delta, roll, r_mat);
}
void ED_armature_ebone_to_mat4(EditBone *ebone, float r_mat[4][4])
{
float m3[3][3];
ED_armature_ebone_to_mat3(ebone, m3);
copy_m4_m3(r_mat, m3);
copy_v3_v3(r_mat[3], ebone->head);
}
void ED_armature_ebone_from_mat3(EditBone *ebone, const float mat[3][3])
{
float vec[3], roll;
const float len = len_v3v3(ebone->head, ebone->tail);
mat3_to_vec_roll(mat, vec, &roll);
madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len);
ebone->roll = roll;
}
void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4])
{
float mat3[3][3];
copy_m3_m4(mat3, mat);
/* We want normalized matrix here, to be consistent with ebone_to_mat. */
BLI_ASSERT_UNIT_M3(mat3);
sub_v3_v3(ebone->tail, ebone->head);
copy_v3_v3(ebone->head, mat[3]);
add_v3_v3(ebone->tail, mat[3]);
ED_armature_ebone_from_mat3(ebone, mat3);
}
/**
* Return a pointer to the bone of the given name
*/
EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
{
return BLI_findstring(edbo, name, offsetof(EditBone, name));
}
/* *************************************************************** */
/* Mirroring */
/**
* \see #BKE_pose_channel_get_mirrored (pose-mode, matching function)
*/
EditBone *ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
{
char name_flip[MAXBONENAME];
2019-04-22 09:19:45 +10:00
if (ebo == NULL) {
return NULL;
2019-04-22 09:19:45 +10:00
}
BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
if (!STREQ(name_flip, ebo->name)) {
return ED_armature_ebone_find_name(edbo, name_flip);
}
return NULL;
}
/* ------------------------------------- */
/* helper function for tools to work on mirrored parts.
* it leaves mirrored bones selected then too, which is a good indication of what happened */
void armature_select_mirrored_ex(bArmature *arm, const int flag)
{
BLI_assert((flag & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0);
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
EditBone *curBone, *ebone_mirr;
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (arm->layer & curBone->layer) {
if (curBone->flag & flag) {
ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
2019-04-22 09:19:45 +10:00
if (ebone_mirr) {
ebone_mirr->flag |= (curBone->flag & flag);
2019-04-22 09:19:45 +10:00
}
}
}
}
}
}
void armature_select_mirrored(bArmature *arm)
{
armature_select_mirrored_ex(arm, BONE_SELECTED);
}
void armature_tag_select_mirrored(bArmature *arm)
{
EditBone *curBone;
/* always untag */
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
curBone->flag &= ~BONE_DONE;
}
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (arm->layer & curBone->layer) {
if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
ebone_mirr->flag |= BONE_DONE;
}
}
}
}
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (curBone->flag & BONE_DONE) {
EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
}
}
}
}
/* only works when tagged */
void armature_tag_unselect(bArmature *arm)
{
EditBone *curBone;
for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
if (curBone->flag & BONE_DONE) {
curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
}
}
}
/* ------------------------------------- */
void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select)
{
2019-08-22 04:36:04 +10:00
/* TODO When this function is called by property updates,
2020-06-16 16:50:23 +10:00
* canceling the value change will not restore mirrored bone correctly. */
2019-08-22 04:36:04 +10:00
/* Currently check_select==true when this function is called from a transform operator,
* eg. from 3d viewport. */
/* no layer check, correct mirror is more important */
if (!check_select || ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
if (eboflip) {
/* We assume X-axis flipping for now. */
/* Always mirror roll, since it can be changed by moving either head or tail. */
eboflip->roll = -ebo->roll;
if (!check_select || ebo->flag & BONE_TIPSEL) {
/* Mirror tail properties. */
eboflip->tail[0] = -ebo->tail[0];
eboflip->tail[1] = ebo->tail[1];
eboflip->tail[2] = ebo->tail[2];
eboflip->rad_tail = ebo->rad_tail;
eboflip->curve_out_x = -ebo->curve_out_x;
eboflip->curve_out_y = ebo->curve_out_y;
eboflip->scale_out_x = ebo->scale_out_x;
eboflip->scale_out_y = ebo->scale_out_y;
eboflip->ease2 = ebo->ease2;
eboflip->roll2 = -ebo->roll2;
/* Also move connected children, in case children's name aren't mirrored properly. */
EditBone *children;
for (children = arm->edbo->first; children; children = children->next) {
if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
copy_v3_v3(children->head, eboflip->tail);
children->rad_head = ebo->rad_tail;
}
}
}
if (!check_select || ebo->flag & BONE_ROOTSEL) {
/* Mirror head properties. */
eboflip->head[0] = -ebo->head[0];
eboflip->head[1] = ebo->head[1];
eboflip->head[2] = ebo->head[2];
eboflip->rad_head = ebo->rad_head;
eboflip->curve_in_x = -ebo->curve_in_x;
eboflip->curve_in_y = ebo->curve_in_y;
eboflip->scale_in_x = ebo->scale_in_x;
eboflip->scale_in_y = ebo->scale_in_y;
eboflip->ease1 = ebo->ease1;
eboflip->roll1 = -ebo->roll1;
/* Also move connected parent, in case parent's name isn't mirrored properly. */
if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
EditBone *parent = eboflip->parent;
copy_v3_v3(parent->tail, eboflip->head);
parent->rad_tail = ebo->rad_head;
}
}
if (!check_select || ebo->flag & BONE_SELECTED) {
/* Mirror bone body properties (both head and tail are selected). */
2019-08-22 04:36:04 +10:00
/* TODO: These values can also be changed from pose mode,
* so only mirroring them in edit mode is not ideal. */
eboflip->dist = ebo->dist;
eboflip->weight = ebo->weight;
eboflip->segments = ebo->segments;
eboflip->xwidth = ebo->xwidth;
eboflip->zwidth = ebo->zwidth;
}
}
}
}
/* if editbone (partial) selected, copy data */
/* context; editmode armature, with mirror editing enabled */
void ED_armature_edit_transform_mirror_update(Object *obedit)
{
bArmature *arm = obedit->data;
LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
ED_armature_ebone_transform_mirror_update(arm, ebo, true);
}
}
/* *************************************************************** */
/* Armature EditMode Conversions */
/* converts Bones to EditBone list, used for tools as well */
static EditBone *make_boneList_recursive(ListBase *edbo,
ListBase *bones,
EditBone *parent,
Bone *actBone)
{
EditBone *eBone;
EditBone *eBoneAct = NULL;
EditBone *eBoneTest = NULL;
Bone *curBone;
for (curBone = bones->first; curBone; curBone = curBone->next) {
eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
eBone->temp.bone = curBone;
/* Copy relevant data from bone to eBone
* Keep selection logic in sync with ED_armature_edit_sync_selection.
*/
eBone->parent = parent;
BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
eBone->flag = curBone->flag;
Armature: add Inherit Scale options to remove shear or average the scale. As an inherent property of matrix-based transformation math, non- uniform scaling of a parent bone induces shear into the transform matrix of any rotated child. Such matrices cannot be cleanly decomposed into a combination of location/rotation/scale, which causes issues for rigging and animation tools. Blender bones have options to exclude rotation and/or scale from the inherited transformation, but don't have any support for removing the often undesired shear component. That goal requires replacing simple parenting with a combination of multiple bones and constraints. The same is true about the goal of inheriting some scale, but completely avoiding shear. This patch replaces the old Inherit Scale checkbox with a enum that supports multiple options: * Full: inherit all effects of scale, like with enabled Inherit Scale. * Fix Shear: removes shear from the final inherited transformation. The cleanup math is specifically designed to preserve the main axis of the bone, its length and total volume, and minimally affect roll on average. It however will not prevent reappearance of shear due to local rotation of the child or its children. * Average: inherit uniform scale that represents the parent volume. This is the simplest foolproof solution that will inherit some scale without ever causing shear. * None: completely remove scale and shear. * None (Legacy): old disabled Inherit Scale checkbox. This mode does not handle parent shear in any way, so the child is likely to end up having both scale and shear. It is retained for backward compatibility. Since many rigging-related addons access the use_inherit_scale property from Python, it is retained as a backward compatibility stub that provides the old functionality. As a side effect of reworking the code, this also fixes a matrix multiplication order bug in the Inherit Rotation code, which caused the parent local scale to be applied in world space. In rigger opinion this option is useless in production rigs, so this fix should not be a problem. Reviewers: brecht Differential Revision: https://developer.blender.org/D5588
2019-09-04 10:10:27 +03:00
eBone->inherit_scale_mode = curBone->inherit_scale_mode;
/* fix selection flags */
if (eBone->flag & BONE_SELECTED) {
/* if the bone is selected the copy its root selection to the parents tip */
eBone->flag |= BONE_TIPSEL;
if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
eBone->parent->flag |= BONE_TIPSEL;
}
/* For connected bones, take care when changing the selection when we have a
* connected parent, this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
eBone->flag |= BONE_ROOTSEL;
}
else {
/* if the bone is not selected, but connected to its parent
* always use the parents tip selection state */
if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
eBone->flag &= ~BONE_ROOTSEL;
}
}
copy_v3_v3(eBone->head, curBone->arm_head);
copy_v3_v3(eBone->tail, curBone->arm_tail);
eBone->roll = curBone->arm_roll;
/* rest of stuff copy */
eBone->length = curBone->length;
eBone->dist = curBone->dist;
eBone->weight = curBone->weight;
eBone->xwidth = curBone->xwidth;
eBone->zwidth = curBone->zwidth;
eBone->rad_head = curBone->rad_head;
eBone->rad_tail = curBone->rad_tail;
eBone->segments = curBone->segments;
eBone->layer = curBone->layer;
/* Bendy-Bone parameters */
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)
2016-05-18 03:19:06 +12:00
eBone->roll1 = curBone->roll1;
eBone->roll2 = curBone->roll2;
eBone->curve_in_x = curBone->curve_in_x;
eBone->curve_in_y = curBone->curve_in_y;
eBone->curve_out_x = curBone->curve_out_x;
eBone->curve_out_y = curBone->curve_out_y;
eBone->ease1 = curBone->ease1;
eBone->ease2 = curBone->ease2;
eBone->scale_in_x = curBone->scale_in_x;
eBone->scale_in_y = curBone->scale_in_y;
eBone->scale_out_x = curBone->scale_out_x;
eBone->scale_out_y = curBone->scale_out_y;
eBone->bbone_prev_type = curBone->bbone_prev_type;
eBone->bbone_next_type = curBone->bbone_next_type;
2019-04-22 09:19:45 +10:00
if (curBone->prop) {
eBone->prop = IDP_CopyProperty(curBone->prop);
2019-04-22 09:19:45 +10:00
}
BLI_addtail(edbo, eBone);
2020-03-29 16:33:51 +11:00
/* Add children if necessary. */
if (curBone->childbase.first) {
eBoneTest = make_boneList_recursive(edbo, &curBone->childbase, eBone, actBone);
2019-04-22 09:19:45 +10:00
if (eBoneTest) {
eBoneAct = eBoneTest;
2019-04-22 09:19:45 +10:00
}
}
2019-04-22 09:19:45 +10:00
if (curBone == actBone) {
eBoneAct = eBone;
2019-04-22 09:19:45 +10:00
}
}
return eBoneAct;
}
static EditBone *find_ebone_link(ListBase *edbo, Bone *link)
{
if (link != NULL) {
LISTBASE_FOREACH (EditBone *, ebone, edbo) {
if (ebone->temp.bone == link) {
return ebone;
}
}
}
return NULL;
}
EditBone *make_boneList(ListBase *edbo, ListBase *bones, struct Bone *actBone)
{
BLI_assert(!edbo->first && !edbo->last);
EditBone *active = make_boneList_recursive(edbo, bones, NULL, actBone);
LISTBASE_FOREACH (EditBone *, ebone, edbo) {
Bone *bone = ebone->temp.bone;
/* Convert custom B-Bone handle links. */
ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
}
return active;
}
/**
* This function:
* - Sets local head/tail rest locations using parent bone's arm_mat.
* - Calls #BKE_armature_where_is_bone() which uses parent's transform (arm_mat)
* to define this bone's transform.
* - Fixes (converts) EditBone roll into Bone roll.
* - Calls again #BKE_armature_where_is_bone(),
* since roll fiddling may have changed things for our bone.
*
* \note The order is crucial here, we can only handle child
* if all its parents in chain have already been handled (this is ensured by recursive process).
*/
static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
{
Bone *curBone;
EditBone *ebone;
for (curBone = bonelist->first; curBone; curBone = curBone->next) {
/* Set bone's local head/tail.
* Note that it's important to use final parent's restpose (arm_mat) here,
* instead of setting those values from editbone's matrix (see T46010). */
if (curBone->parent) {
float parmat_inv[4][4];
invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
/* Get the new head and tail */
sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
mul_mat3_m4_v3(parmat_inv, curBone->head);
mul_mat3_m4_v3(parmat_inv, curBone->tail);
}
else {
copy_v3_v3(curBone->head, curBone->arm_head);
copy_v3_v3(curBone->tail, curBone->arm_tail);
}
/* Set local matrix and arm_mat (restpose).
* Do not recurse into children here, armature_finalize_restpose() is already recursive. */
BKE_armature_where_is_bone(curBone, curBone->parent, false);
/* Find the associated editbone */
for (ebone = editbonelist->first; ebone; ebone = ebone->next) {
if (ebone->temp.bone == curBone) {
float premat[3][3];
float postmat[3][3];
float difmat[3][3];
float imat[3][3];
/* Get the ebone premat and its inverse. */
ED_armature_ebone_to_mat3(ebone, premat);
invert_m3_m3(imat, premat);
/* Get the bone postmat. */
copy_m3_m4(postmat, curBone->arm_mat);
mul_m3_m3m3(difmat, imat, postmat);
#if 0
printf("Bone %s\n", curBone->name);
print_m4("premat", premat);
print_m4("postmat", postmat);
print_m4("difmat", difmat);
printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
#endif
curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
2020-03-06 11:40:37 +11:00
/* And set rest-position again. */
BKE_armature_where_is_bone(curBone, curBone->parent, false);
break;
}
}
/* Recurse into children... */
armature_finalize_restpose(&curBone->childbase, editbonelist);
}
}
/* put EditMode back in Object */
2018-06-06 15:50:24 +02:00
void ED_armature_from_edit(Main *bmain, bArmature *arm)
{
EditBone *eBone, *neBone;
Bone *newBone;
Object *obt;
/* armature bones */
BKE_armature_bone_hash_free(arm);
BKE_armature_bonelist_free(&arm->bonebase, true);
arm->act_bone = NULL;
2013-10-31 14:10:01 +00:00
/* remove zero sized bones, this gives unstable restposes */
for (eBone = arm->edbo->first; eBone; eBone = neBone) {
2015-09-07 00:48:26 +10:00
float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
neBone = eBone->next;
/* TODO(sergey): How to ensure this is a constexpr? */
if (len_sq <= square_f(0.000001f)) { /* FLT_EPSILON is too large? */
EditBone *fBone;
/* Find any bones that refer to this bone */
for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
2019-04-22 09:19:45 +10:00
if (fBone->parent == eBone) {
fBone->parent = eBone->parent;
2019-04-22 09:19:45 +10:00
}
}
2019-04-22 09:19:45 +10:00
if (G.debug & G_DEBUG) {
printf("Warning: removed zero sized bone: %s\n", eBone->name);
2019-04-22 09:19:45 +10:00
}
bone_free(arm, eBone);
}
}
2020-03-29 16:33:51 +11:00
/* Copy the bones from the edit-data into the armature. */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = MEM_callocN(sizeof(Bone), "bone");
eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
copy_v3_v3(newBone->arm_head, eBone->head);
copy_v3_v3(newBone->arm_tail, eBone->tail);
newBone->arm_roll = eBone->roll;
newBone->flag = eBone->flag;
Armature: add Inherit Scale options to remove shear or average the scale. As an inherent property of matrix-based transformation math, non- uniform scaling of a parent bone induces shear into the transform matrix of any rotated child. Such matrices cannot be cleanly decomposed into a combination of location/rotation/scale, which causes issues for rigging and animation tools. Blender bones have options to exclude rotation and/or scale from the inherited transformation, but don't have any support for removing the often undesired shear component. That goal requires replacing simple parenting with a combination of multiple bones and constraints. The same is true about the goal of inheriting some scale, but completely avoiding shear. This patch replaces the old Inherit Scale checkbox with a enum that supports multiple options: * Full: inherit all effects of scale, like with enabled Inherit Scale. * Fix Shear: removes shear from the final inherited transformation. The cleanup math is specifically designed to preserve the main axis of the bone, its length and total volume, and minimally affect roll on average. It however will not prevent reappearance of shear due to local rotation of the child or its children. * Average: inherit uniform scale that represents the parent volume. This is the simplest foolproof solution that will inherit some scale without ever causing shear. * None: completely remove scale and shear. * None (Legacy): old disabled Inherit Scale checkbox. This mode does not handle parent shear in any way, so the child is likely to end up having both scale and shear. It is retained for backward compatibility. Since many rigging-related addons access the use_inherit_scale property from Python, it is retained as a backward compatibility stub that provides the old functionality. As a side effect of reworking the code, this also fixes a matrix multiplication order bug in the Inherit Rotation code, which caused the parent local scale to be applied in world space. In rigger opinion this option is useless in production rigs, so this fix should not be a problem. Reviewers: brecht Differential Revision: https://developer.blender.org/D5588
2019-09-04 10:10:27 +03:00
newBone->inherit_scale_mode = eBone->inherit_scale_mode;
if (eBone == arm->act_edbone) {
/* don't change active selection, this messes up separate which uses
* editmode toggle and can separate active bone which is de-selected originally */
/* important, editbones can be active with only 1 point selected */
/* newBone->flag |= BONE_SELECTED; */
arm->act_bone = newBone;
}
newBone->roll = 0.0f;
newBone->weight = eBone->weight;
newBone->dist = eBone->dist;
newBone->xwidth = eBone->xwidth;
newBone->zwidth = eBone->zwidth;
newBone->rad_head = eBone->rad_head;
newBone->rad_tail = eBone->rad_tail;
newBone->segments = eBone->segments;
newBone->layer = eBone->layer;
/* Bendy-Bone parameters */
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)
2016-05-18 03:19:06 +12:00
newBone->roll1 = eBone->roll1;
newBone->roll2 = eBone->roll2;
newBone->curve_in_x = eBone->curve_in_x;
newBone->curve_in_y = eBone->curve_in_y;
newBone->curve_out_x = eBone->curve_out_x;
newBone->curve_out_y = eBone->curve_out_y;
newBone->ease1 = eBone->ease1;
newBone->ease2 = eBone->ease2;
newBone->scale_in_x = eBone->scale_in_x;
newBone->scale_in_y = eBone->scale_in_y;
newBone->scale_out_x = eBone->scale_out_x;
newBone->scale_out_y = eBone->scale_out_y;
newBone->bbone_prev_type = eBone->bbone_prev_type;
newBone->bbone_next_type = eBone->bbone_next_type;
2019-04-22 09:19:45 +10:00
if (eBone->prop) {
newBone->prop = IDP_CopyProperty(eBone->prop);
2019-04-22 09:19:45 +10:00
}
}
/* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
* Do not set bone->head/tail here anymore,
* using EditBone data for that is not OK since our later fiddling with parent's arm_mat
* (for roll conversion) may have some small but visible impact on locations (T46010). */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = eBone->temp.bone;
if (eBone->parent) {
newBone->parent = eBone->parent->temp.bone;
BLI_addtail(&newBone->parent->childbase, newBone);
}
/* ...otherwise add this bone to the armature's bonebase */
else {
BLI_addtail(&arm->bonebase, newBone);
}
/* Also transfer B-Bone custom handles. */
if (eBone->bbone_prev) {
newBone->bbone_prev = eBone->bbone_prev->temp.bone;
}
if (eBone->bbone_next) {
newBone->bbone_next = eBone->bbone_next->temp.bone;
}
}
/* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
armature_finalize_restpose(&arm->bonebase, arm->edbo);
BKE_armature_bone_hash_make(arm);
/* so all users of this armature should get rebuilt */
for (obt = bmain->objects.first; obt; obt = obt->id.next) {
if (obt->data == arm) {
BKE_pose_rebuild(bmain, obt, arm, true);
}
}
DEG_id_tag_update(&arm->id, 0);
}
void ED_armature_edit_free(struct bArmature *arm)
{
EditBone *eBone;
2020-03-29 16:33:51 +11:00
/* Clear the edit-bones list. */
if (arm->edbo) {
if (arm->edbo->first) {
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->prop) {
IDP_FreeProperty(eBone->prop);
}
}
BLI_freelistN(arm->edbo);
}
MEM_freeN(arm->edbo);
arm->edbo = NULL;
arm->act_edbone = NULL;
}
}
/* Put armature in EditMode */
void ED_armature_to_edit(bArmature *arm)
{
ED_armature_edit_free(arm);
arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
}
/* *************************************************************** */
/* Used by Undo for Armature EditMode*/
/* free's bones and their properties */
void ED_armature_ebone_listbase_free(ListBase *lb, const bool do_id_user)
{
EditBone *ebone, *ebone_next;
for (ebone = lb->first; ebone; ebone = ebone_next) {
ebone_next = ebone->next;
if (ebone->prop) {
IDP_FreeProperty_ex(ebone->prop, do_id_user);
}
MEM_freeN(ebone);
}
BLI_listbase_clear(lb);
}
void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src, const bool do_id_user)
{
EditBone *ebone_src;
EditBone *ebone_dst;
BLI_assert(BLI_listbase_is_empty(lb_dst));
for (ebone_src = lb_src->first; ebone_src; ebone_src = ebone_src->next) {
ebone_dst = MEM_dupallocN(ebone_src);
if (ebone_dst->prop) {
ebone_dst->prop = IDP_CopyProperty_ex(ebone_dst->prop,
do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
}
ebone_src->temp.ebone = ebone_dst;
BLI_addtail(lb_dst, ebone_dst);
}
/* set pointers */
for (ebone_dst = lb_dst->first; ebone_dst; ebone_dst = ebone_dst->next) {
if (ebone_dst->parent) {
ebone_dst->parent = ebone_dst->parent->temp.ebone;
}
if (ebone_dst->bbone_next) {
ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone;
}
if (ebone_dst->bbone_prev) {
ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone;
}
}
}
void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
{
EditBone *ebone;
/* be sure they don't hang ever */
for (ebone = lb->first; ebone; ebone = ebone->next) {
ebone->temp.p = NULL;
}
}
/* *************************************************************** */
/* Low level selection functions which hide connected-parent
* flag behavior which gets tricky to handle in selection operators.
* (no flushing in ED_armature_ebone_select.*, that should be explicit) */
int ED_armature_ebone_selectflag_get(const EditBone *ebone)
{
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) |
((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0));
}
return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
}
void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag)
{
flag = flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
ebone->parent->flag &= ~BONE_TIPSEL;
ebone->flag |= flag;
ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0;
}
else {
ebone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
ebone->flag |= flag;
}
}
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag)
{
BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
ED_armature_ebone_selectflag_set(ebone, ebone->flag | flag);
}
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag)
{
BLI_assert((flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0);
ED_armature_ebone_selectflag_set(ebone, ebone->flag & ~flag);
}
/* could be used in more places */
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
{
int flag;
if (select) {
BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
flag = (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
else {
flag = 0;
}
ED_armature_ebone_selectflag_set(ebone, flag);
}