Merge branch 'blender-v4.1-release'
This commit is contained in:
@@ -529,6 +529,15 @@ class ARMATURE_OT_copy_bone_color_to_selected(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def _armature_from_context(context):
|
||||
pin_armature = getattr(context, 'armature', None)
|
||||
if pin_armature:
|
||||
return pin_armature
|
||||
if context.object and context.object.type == 'ARMATURE':
|
||||
return context.object.data
|
||||
return None
|
||||
|
||||
|
||||
class ARMATURE_OT_collection_show_all(Operator):
|
||||
"""Show all bone collections"""
|
||||
bl_idname = "armature.collection_show_all"
|
||||
@@ -537,10 +546,10 @@ class ARMATURE_OT_collection_show_all(Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'ARMATURE' and context.object.data
|
||||
return _armature_from_context(context) is not None
|
||||
|
||||
def execute(self, context):
|
||||
arm = context.object.data
|
||||
arm = _armature_from_context(context)
|
||||
for bcoll in arm.collections_all:
|
||||
bcoll.is_visible = True
|
||||
return {'FINISHED'}
|
||||
@@ -554,15 +563,16 @@ class ARMATURE_OT_collection_unsolo_all(Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not (context.object and context.object.type == 'ARMATURE' and context.object.data):
|
||||
armature = _armature_from_context(context)
|
||||
if not armature:
|
||||
return False
|
||||
if not context.object.data.collections.is_solo_active:
|
||||
if not armature.collections.is_solo_active:
|
||||
cls.poll_message_set("None of the bone collections is marked 'solo'")
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
arm = context.object.data
|
||||
arm = _armature_from_context(context)
|
||||
for bcoll in arm.collections_all:
|
||||
bcoll.is_solo = False
|
||||
return {'FINISHED'}
|
||||
@@ -578,16 +588,16 @@ class ARMATURE_OT_collection_remove_unused(Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.object or context.object.type != 'ARMATURE':
|
||||
armature = _armature_from_context(context)
|
||||
if not armature:
|
||||
return False
|
||||
arm = context.object.data
|
||||
return len(arm.collections) > 0
|
||||
return len(armature.collections) > 0
|
||||
|
||||
def execute(self, context):
|
||||
if context.object.mode == 'EDIT':
|
||||
if context.mode == 'EDIT_ARMATURE':
|
||||
return self.execute_edit_mode(context)
|
||||
|
||||
armature = context.object.data
|
||||
armature = _armature_from_context(context)
|
||||
|
||||
# Build a set of bone collections that don't contain any bones, and
|
||||
# whose children also don't contain any bones.
|
||||
@@ -608,7 +618,7 @@ class ARMATURE_OT_collection_remove_unused(Operator):
|
||||
# edit mode, because that has a completely separate list of edit bones.
|
||||
# This is why edit mode needs separate handling.
|
||||
|
||||
armature = context.object.data
|
||||
armature = _armature_from_context(context)
|
||||
bcolls_with_bones = {
|
||||
bcoll
|
||||
for ebone in armature.edit_bones
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface_icons.hh"
|
||||
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "ED_armature.hh"
|
||||
#include "ED_object.hh"
|
||||
#include "ED_outliner.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_view3d.hh"
|
||||
@@ -58,6 +60,21 @@ using blender::Vector;
|
||||
/** \name Object Tools Public API
|
||||
* \{ */
|
||||
|
||||
bArmature *ED_armature_context(const bContext *C)
|
||||
{
|
||||
bArmature *armature = static_cast<bArmature *>(
|
||||
CTX_data_pointer_get_type(C, "armature", &RNA_Armature).data);
|
||||
|
||||
if (armature == nullptr) {
|
||||
Object *object = ED_object_active_context(C);
|
||||
if (object && object->type == OB_ARMATURE) {
|
||||
armature = static_cast<bArmature *>(object->data);
|
||||
}
|
||||
}
|
||||
|
||||
return armature;
|
||||
}
|
||||
|
||||
/* NOTE: these functions are exported to the Object module to be called from the tools there */
|
||||
|
||||
void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], const bool do_props)
|
||||
|
||||
@@ -45,23 +45,18 @@ struct wmOperator;
|
||||
|
||||
static bool bone_collection_add_poll(bContext *C)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
if (armature == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ob->type != OB_ARMATURE) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Bone collections can only be added to an Armature");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ID_IS_LINKED(ob->data)) {
|
||||
if (ID_IS_LINKED(&armature->id)) {
|
||||
CTX_wm_operator_poll_msg_set(
|
||||
C, "Cannot add bone collections to a linked Armature without an override");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BKE_lib_override_library_is_system_defined(nullptr, reinterpret_cast<ID *>(ob->data))) {
|
||||
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
|
||||
CTX_wm_operator_poll_msg_set(C,
|
||||
"Cannot add bone collections to a linked Armature with a system "
|
||||
"override; explicitly create an override on the Armature");
|
||||
@@ -74,17 +69,11 @@ static bool bone_collection_add_poll(bContext *C)
|
||||
/** Allow edits of local bone collection only (full local or local override). */
|
||||
static bool active_bone_collection_poll(bContext *C)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
if (armature == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ob->type != OB_ARMATURE) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Bone collections can only be edited on an Armature");
|
||||
return false;
|
||||
}
|
||||
|
||||
bArmature *armature = static_cast<bArmature *>(ob->data);
|
||||
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
|
||||
CTX_wm_operator_poll_msg_set(C,
|
||||
"Cannot update a linked Armature with a system override; "
|
||||
@@ -110,12 +99,7 @@ static int bone_collection_add_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
using namespace blender::animrig;
|
||||
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
bArmature *armature = static_cast<bArmature *>(ob->data);
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
|
||||
/* If there is an active bone collection, create the new one as a sibling. */
|
||||
const int parent_index = armature_bonecoll_find_parent_index(
|
||||
@@ -132,7 +116,7 @@ static int bone_collection_add_exec(bContext *C, wmOperator * /*op*/)
|
||||
ANIM_armature_bonecoll_active_set(armature, bcoll);
|
||||
/* TODO: ensure the ancestors of the new bone collection are all expanded. */
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
@@ -153,17 +137,12 @@ void ARMATURE_OT_collection_add(wmOperatorType *ot)
|
||||
|
||||
static int bone_collection_remove_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* The poll function ensures armature->active_collection is not NULL. */
|
||||
bArmature *armature = static_cast<bArmature *>(ob->data);
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
ANIM_armature_bonecoll_remove(armature, armature->runtime.active_collection);
|
||||
|
||||
/* notifiers for updates */
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
|
||||
DEG_id_tag_update(&armature->id, ID_RECALC_SELECT);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -186,14 +165,10 @@ void ARMATURE_OT_collection_remove(wmOperatorType *ot)
|
||||
|
||||
static int bone_collection_move_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
const int direction = RNA_enum_get(op->ptr, "direction");
|
||||
|
||||
/* Poll function makes sure this is valid. */
|
||||
bArmature *armature = static_cast<bArmature *>(ob->data);
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
|
||||
const bool ok = ANIM_armature_bonecoll_move(
|
||||
armature, armature->runtime.active_collection, direction);
|
||||
@@ -203,7 +178,7 @@ static int bone_collection_move_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ANIM_armature_bonecoll_active_runtime_refresh(armature);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_COLLECTION, ob);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_COLLECTION, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ Object *ED_pose_object_from_context(bContext *C)
|
||||
/* Since this call may also be used from the buttons window,
|
||||
* we need to check for where to get the object. */
|
||||
if (area && area->spacetype == SPACE_PROPERTIES) {
|
||||
ob = ED_object_context(C);
|
||||
ob = ED_object_active_context(C);
|
||||
}
|
||||
else {
|
||||
ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
|
||||
|
||||
@@ -65,7 +65,10 @@ EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool
|
||||
|
||||
void ED_armature_ebone_copy(EditBone *dest, const EditBone *source);
|
||||
|
||||
/* `armature_edit.cc` */
|
||||
/**
|
||||
* Get current armature from the context, including properties editor pinning.
|
||||
**/
|
||||
bArmature *ED_armature_context(const bContext *C);
|
||||
|
||||
/**
|
||||
* Adjust bone roll to align Z axis with vector `align_axis` is in local space and is normalized.
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "ED_armature.hh"
|
||||
#include "ED_undo.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
@@ -460,20 +461,18 @@ void uiTemplateBoneCollectionTree(uiLayout *layout, bContext *C)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
Object *object = CTX_data_active_object(C);
|
||||
if (!object || object->type != OB_ARMATURE) {
|
||||
bArmature *armature = ED_armature_context(C);
|
||||
if (armature == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bArmature *arm = static_cast<bArmature *>(object->data);
|
||||
BLI_assert(GS(arm->id.name) == ID_AR);
|
||||
BLI_assert(GS(armature->id.name) == ID_AR);
|
||||
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
|
||||
ui::AbstractTreeView *tree_view = UI_block_add_view(
|
||||
*block,
|
||||
"Bone Collection Tree View",
|
||||
std::make_unique<blender::ui::bonecollections::BoneCollectionTreeView>(*arm));
|
||||
std::make_unique<blender::ui::bonecollections::BoneCollectionTreeView>(*armature));
|
||||
tree_view->set_min_rows(3);
|
||||
|
||||
ui::TreeViewBuilder::build_tree_view(*tree_view, *layout);
|
||||
|
||||
@@ -292,11 +292,12 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum WarnFlag
|
||||
|
||||
static bool dyntopo_supports_layer(const CustomDataLayer &layer)
|
||||
{
|
||||
if (layer.type == CD_PROP_FLOAT && STREQ(layer.name, ".sculpt_mask")) {
|
||||
return true;
|
||||
}
|
||||
if (CD_TYPE_AS_MASK(layer.type) & CD_MASK_PROP_ALL) {
|
||||
/* Some data is stored as generic attributes on #Mesh but in flags or fields on #BMesh. */
|
||||
return BM_attribute_stored_in_bmesh_builtin(layer.name);
|
||||
}
|
||||
/* Some layers just encode #Mesh topology or are handled as special cases for dyntopo. */
|
||||
return ELEM(layer.type, CD_ORIGINDEX);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user