Move the selection flag for pose bones, from the (edit)bone to the pose bone. Previously having multiple instances of armatures in pose mode at the same time caused issues because selecting a pose bone on one armature would automatically select it on all instances of it. This is now fixed since the selection state is stored on the pose bone (Object level) Doing so breaks API compatibility with 4.5 since the RNA property on the Bone no longer affects the pose bone. Instead, there is a new property on the pose bone for that. Due to this change, some runtime flags for the transform system also had to be moved to the pose bone. This is due to the fact that these flags are used by the transform system to pass information between functions. If we keep the flag at the bone level, this wouldn't work with armature instances. See `bPoseChannelRuntimeFlag` Fixes #117892 Pull Request: https://projects.blender.org/blender/blender/pulls/146102
86 lines
2.8 KiB
C++
86 lines
2.8 KiB
C++
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup animrig
|
|
*
|
|
* \brief Functions to deal with Armatures.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "ANIM_bone_collections.hh"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
namespace blender::animrig {
|
|
|
|
/**
|
|
* Returns true if the given Bone is visible. This includes bone collection visibility.
|
|
*/
|
|
inline bool bone_is_visible(const bArmature *armature, const Bone *bone)
|
|
{
|
|
const bool bone_itself_visible = (bone->flag & BONE_HIDDEN_P) == 0;
|
|
return bone_itself_visible && ANIM_bone_in_visible_collection(armature, bone);
|
|
}
|
|
|
|
inline bool bone_is_visible(const bArmature *armature, const bPoseChannel *pchan)
|
|
{
|
|
const bool bone_itself_visible = (pchan->drawflag & PCHAN_DRAW_HIDDEN) == 0;
|
|
return bone_itself_visible && ANIM_bone_in_visible_collection(armature, pchan->bone);
|
|
}
|
|
|
|
inline bool bone_is_visible(const bArmature *armature, const EditBone *ebone)
|
|
{
|
|
const bool bone_itself_visible = (ebone->flag & BONE_HIDDEN_A) == 0;
|
|
return bone_itself_visible && ANIM_bonecoll_is_visible_editbone(armature, ebone);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the bone is selected. This includes a visibility check
|
|
* because invisible bones cannot be selected, no matter their flag.
|
|
*/
|
|
inline bool bone_is_selected(const bArmature *armature, const Bone *bone)
|
|
{
|
|
return (bone->flag & BONE_SELECTED) && bone_is_visible(armature, bone);
|
|
}
|
|
|
|
inline bool bone_is_selected(const bArmature *armature, const bPoseChannel *pchan)
|
|
{
|
|
return (pchan->flag & POSE_SELECTED) && bone_is_visible(armature, pchan);
|
|
}
|
|
|
|
inline bool bone_is_selected(const bArmature *armature, const EditBone *ebone)
|
|
{
|
|
return (ebone->flag & BONE_SELECTED) && bone_is_visible(armature, ebone);
|
|
}
|
|
|
|
inline bool bone_is_selectable(const bArmature *armature, const bPoseChannel *pchan)
|
|
{
|
|
return bone_is_visible(armature, pchan) && !(pchan->bone->flag & BONE_UNSELECTABLE);
|
|
}
|
|
|
|
inline bool bone_is_selectable(const bArmature *armature, const Bone *bone)
|
|
{
|
|
return bone_is_visible(armature, bone) && !(bone->flag & BONE_UNSELECTABLE);
|
|
}
|
|
|
|
/**
|
|
* Iterates all descendents of the given pose bone including the bone itself. Iterates breadth
|
|
* first.
|
|
*/
|
|
void pose_bone_descendent_iterator(bPose &pose,
|
|
bPoseChannel &pose_bone,
|
|
FunctionRef<void(bPoseChannel &child_bone)> callback);
|
|
|
|
/**
|
|
* Iterates all descendents of the given pose bone depth first. The traversal for a branch is
|
|
* stopped if the callback returns false. Returns true if the iteration completed or false if it
|
|
* was stopped before visiting all bones.
|
|
*/
|
|
bool pose_bone_descendent_depth_iterator(bPose &pose,
|
|
bPoseChannel &pose_bone,
|
|
FunctionRef<bool(bPoseChannel &child_bone)> callback);
|
|
} // namespace blender::animrig
|