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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/armature/armature_select.c')
-rw-r--r--source/blender/editors/armature/armature_select.c3046
1 files changed, 1529 insertions, 1517 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 4aab80bcbdd..0c493672d9e 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -60,695 +60,713 @@
/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
-Base *ED_armature_base_and_ebone_from_select_buffer(
- Base **bases, uint bases_len, int hit, EditBone **r_ebone)
+Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
- Base *base = NULL;
- EditBone *ebone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
- base = bases[base_index];
- break;
- }
- }
- if (base != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bArmature *arm = base->object->data;
- ebone = BLI_findlink(arm->edbo, hit_bone);
- }
- *r_ebone = ebone;
- return base;
+ const uint hit_object = hit & 0xFFFF;
+ Base *base = NULL;
+ EditBone *ebone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ if (bases[base_index]->object->select_id == hit_object) {
+ base = bases[base_index];
+ break;
+ }
+ }
+ if (base != NULL) {
+ const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ bArmature *arm = base->object->data;
+ ebone = BLI_findlink(arm->edbo, hit_bone);
+ }
+ *r_ebone = ebone;
+ return base;
}
-Object *ED_armature_object_and_ebone_from_select_buffer(
- Object **objects, uint objects_len, int hit, EditBone **r_ebone)
+Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
+ uint objects_len,
+ int hit,
+ EditBone **r_ebone)
{
- const uint hit_object = hit & 0xFFFF;
- Object *ob = NULL;
- EditBone *ebone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (objects[ob_index]->select_id == hit_object) {
- ob = objects[ob_index];
- break;
- }
- }
- if (ob != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bArmature *arm = ob->data;
- ebone = BLI_findlink(arm->edbo, hit_bone);
- }
- *r_ebone = ebone;
- return ob;
+ const uint hit_object = hit & 0xFFFF;
+ Object *ob = NULL;
+ EditBone *ebone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ if (objects[ob_index]->select_id == hit_object) {
+ ob = objects[ob_index];
+ break;
+ }
+ }
+ if (ob != NULL) {
+ const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ bArmature *arm = ob->data;
+ ebone = BLI_findlink(arm->edbo, hit_bone);
+ }
+ *r_ebone = ebone;
+ return ob;
}
-Base *ED_armature_base_and_bone_from_select_buffer(
- Base **bases, uint bases_len, int hit, Bone **r_bone)
+Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
+ uint bases_len,
+ int hit,
+ Bone **r_bone)
{
- const uint hit_object = hit & 0xFFFF;
- Base *base = NULL;
- Bone *bone = NULL;
- /* TODO(campbell): optimize, eg: sort & binary search. */
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
- base = bases[base_index];
- break;
- }
- }
- if (base != NULL) {
- if (base->object->pose != NULL) {
- const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
- bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
- bone = pchan ? pchan->bone : NULL;
- }
- }
- *r_bone = bone;
- return base;
+ const uint hit_object = hit & 0xFFFF;
+ Base *base = NULL;
+ Bone *bone = NULL;
+ /* TODO(campbell): optimize, eg: sort & binary search. */
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ if (bases[base_index]->object->select_id == hit_object) {
+ base = bases[base_index];
+ break;
+ }
+ }
+ if (base != NULL) {
+ if (base->object->pose != NULL) {
+ const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
+ bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
+ bone = pchan ? pchan->bone : NULL;
+ }
+ }
+ *r_bone = bone;
+ return base;
}
/* See if there are any selected bones in this buffer */
/* only bones from base are checked on */
-void *get_bone_from_selectbuffer(
- Base **bases, uint bases_len, bool is_editmode, const unsigned int *buffer, short hits,
- bool findunsel, bool do_nearest, Base **r_base)
+void *get_bone_from_selectbuffer(Base **bases,
+ uint bases_len,
+ bool is_editmode,
+ const unsigned int *buffer,
+ short hits,
+ bool findunsel,
+ bool do_nearest,
+ Base **r_base)
{
- Bone *bone;
- EditBone *ebone;
- void *firstunSel = NULL, *firstSel = NULL, *data;
- Base *firstunSel_base = NULL, *firstSel_base = NULL;
- unsigned int hitresult;
- short i;
- bool takeNext = false;
- int minsel = 0xffffffff, minunsel = 0xffffffff;
-
- for (i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
-
- if (!(hitresult & BONESEL_NOSEL)) {
- if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
- Base *base = NULL;
- bool sel;
-
- hitresult &= ~(BONESEL_ANY);
- /* Determine what the current bone is */
- if (is_editmode == false) {
- base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
- if (bone != NULL) {
- if (findunsel)
- sel = (bone->flag & BONE_SELECTED);
- else
- sel = !(bone->flag & BONE_SELECTED);
-
- data = bone;
- }
- else {
- data = NULL;
- sel = 0;
- }
- }
- else {
- base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
- if (findunsel)
- sel = (ebone->flag & BONE_SELECTED);
- else
- sel = !(ebone->flag & BONE_SELECTED);
-
- data = ebone;
- }
-
- if (data) {
- if (sel) {
- if (do_nearest) {
- if (minsel > buffer[4 * i + 1]) {
- firstSel = data;
- firstSel_base = base;
- minsel = buffer[4 * i + 1];
- }
- }
- else {
- if (!firstSel) {
- firstSel = data;
- firstSel_base = base;
- }
- takeNext = 1;
- }
- }
- else {
- if (do_nearest) {
- if (minunsel > buffer[4 * i + 1]) {
- firstunSel = data;
- firstunSel_base = base;
- minunsel = buffer[4 * i + 1];
- }
- }
- else {
- if (!firstunSel) {
- firstunSel = data;
- firstunSel_base = base;
- }
- if (takeNext) {
- *r_base = base;
- return data;
- }
- }
- }
- }
- }
- }
- }
-
- if (firstunSel) {
- *r_base = firstunSel_base;
- return firstunSel;
- }
- else {
- *r_base = firstSel_base;
- return firstSel;
- }
+ Bone *bone;
+ EditBone *ebone;
+ void *firstunSel = NULL, *firstSel = NULL, *data;
+ Base *firstunSel_base = NULL, *firstSel_base = NULL;
+ unsigned int hitresult;
+ short i;
+ bool takeNext = false;
+ int minsel = 0xffffffff, minunsel = 0xffffffff;
+
+ for (i = 0; i < hits; i++) {
+ hitresult = buffer[3 + (i * 4)];
+
+ if (!(hitresult & BONESEL_NOSEL)) {
+ if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
+ Base *base = NULL;
+ bool sel;
+
+ hitresult &= ~(BONESEL_ANY);
+ /* Determine what the current bone is */
+ if (is_editmode == false) {
+ base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
+ if (bone != NULL) {
+ if (findunsel)
+ sel = (bone->flag & BONE_SELECTED);
+ else
+ sel = !(bone->flag & BONE_SELECTED);
+
+ data = bone;
+ }
+ else {
+ data = NULL;
+ sel = 0;
+ }
+ }
+ else {
+ base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, hitresult, &ebone);
+ if (findunsel)
+ sel = (ebone->flag & BONE_SELECTED);
+ else
+ sel = !(ebone->flag & BONE_SELECTED);
+
+ data = ebone;
+ }
+
+ if (data) {
+ if (sel) {
+ if (do_nearest) {
+ if (minsel > buffer[4 * i + 1]) {
+ firstSel = data;
+ firstSel_base = base;
+ minsel = buffer[4 * i + 1];
+ }
+ }
+ else {
+ if (!firstSel) {
+ firstSel = data;
+ firstSel_base = base;
+ }
+ takeNext = 1;
+ }
+ }
+ else {
+ if (do_nearest) {
+ if (minunsel > buffer[4 * i + 1]) {
+ firstunSel = data;
+ firstunSel_base = base;
+ minunsel = buffer[4 * i + 1];
+ }
+ }
+ else {
+ if (!firstunSel) {
+ firstunSel = data;
+ firstunSel_base = base;
+ }
+ if (takeNext) {
+ *r_base = base;
+ return data;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (firstunSel) {
+ *r_base = firstunSel_base;
+ return firstunSel;
+ }
+ else {
+ *r_base = firstSel_base;
+ return firstSel;
+ }
}
/* used by posemode as well editmode */
/* only checks scene->basact! */
/* x and y are mouse coords (area space) */
-void *get_nearest_bone(
- bContext *C, const int xy[2], bool findunsel,
- Base **r_base)
+void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
{
- ViewContext vc;
- rcti rect;
- unsigned int buffer[MAXPICKBUF];
- short hits;
-
- ED_view3d_viewcontext_init(C, &vc);
-
- // rect.xmin = ... mouseco!
- rect.xmin = rect.xmax = xy[0];
- rect.ymin = rect.ymax = xy[1];
-
- hits = view3d_opengl_select(
- &vc, buffer, MAXPICKBUF, &rect,
- VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
-
- *r_base = NULL;
-
- if (hits > 0) {
- uint bases_len = 0;
- Base **bases;
-
- if (vc.obedit != NULL) {
- bases = BKE_view_layer_array_from_bases_in_mode(
- vc.view_layer, vc.v3d, &bases_len, {
- .object_mode = OB_MODE_EDIT,
- });
- }
- else {
- bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len);
- }
-
- void *bone = get_bone_from_selectbuffer(
- bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
-
- MEM_freeN(bases);
- return bone;
- }
- return NULL;
+ ViewContext vc;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ short hits;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ // rect.xmin = ... mouseco!
+ rect.xmin = rect.xmax = xy[0];
+ rect.ymin = rect.ymax = xy[1];
+
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
+
+ *r_base = NULL;
+
+ if (hits > 0) {
+ uint bases_len = 0;
+ Base **bases;
+
+ if (vc.obedit != NULL) {
+ bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer,
+ vc.v3d,
+ &bases_len,
+ {
+ .object_mode = OB_MODE_EDIT,
+ });
+ }
+ else {
+ bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len);
+ }
+
+ void *bone = get_bone_from_selectbuffer(
+ bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
+
+ MEM_freeN(bases);
+ return bone;
+ }
+ return NULL;
}
/* **************** EditMode stuff ********************** */
static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bArmature *arm;
- EditBone *bone, *curBone, *next;
- const bool sel = !RNA_boolean_get(op->ptr, "deselect");
-
- view3d_operator_needs_opengl(C);
-
- Base *base = NULL;
- bone = get_nearest_bone(C, event->mval, true, &base);
-
- if (!bone)
- return OPERATOR_CANCELLED;
-
- arm = base->object->data;
-
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (sel) {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- if (curBone->flag & BONE_CONNECTED)
- next = curBone->parent;
- else
- next = NULL;
- }
-
- /* Select children */
- while (bone) {
- for (curBone = arm->edbo->first; curBone; curBone = next) {
- next = curBone->next;
- if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (curBone->flag & BONE_CONNECTED) {
- if (sel) {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- bone = curBone;
- break;
- }
- else {
- bone = NULL;
- break;
- }
- }
- }
- if (!curBone)
- bone = NULL;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
-
- return OPERATOR_FINISHED;
+ bArmature *arm;
+ EditBone *bone, *curBone, *next;
+ const bool sel = !RNA_boolean_get(op->ptr, "deselect");
+
+ view3d_operator_needs_opengl(C);
+
+ Base *base = NULL;
+ bone = get_nearest_bone(C, event->mval, true, &base);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ arm = base->object->data;
+
+ /* Select parents */
+ for (curBone = bone; curBone; curBone = next) {
+ if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (sel) {
+ curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ if (curBone->flag & BONE_CONNECTED)
+ next = curBone->parent;
+ else
+ next = NULL;
+ }
+
+ /* Select children */
+ while (bone) {
+ for (curBone = arm->edbo->first; curBone; curBone = next) {
+ next = curBone->next;
+ if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (curBone->flag & BONE_CONNECTED) {
+ if (sel) {
+ curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ bone = curBone;
+ break;
+ }
+ else {
+ bone = NULL;
+ break;
+ }
+ }
+ }
+ if (!curBone)
+ bone = NULL;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
+
+ return OPERATOR_FINISHED;
}
static bool armature_select_linked_poll(bContext *C)
{
- return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
+ return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
void ARMATURE_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Connected";
- ot->idname = "ARMATURE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "ARMATURE_OT_select_linked";
+ ot->description = "Select bones related to selected ones by parent/child relationships";
- /* api callbacks */
- /* leave 'exec' unset */
- ot->invoke = armature_select_linked_invoke;
- ot->poll = armature_select_linked_poll;
+ /* api callbacks */
+ /* leave 'exec' unset */
+ ot->invoke = armature_select_linked_invoke;
+ ot->poll = armature_select_linked_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
}
/* utility function for get_nearest_editbonepoint */
static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
{
- return hits12;
+ return hits12;
}
static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
{
- const int offs = 4 * hits12;
- memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
- return hits5;
+ const int offs = 4 * hits12;
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
+ return hits5;
}
/* does bones and points */
/* note that BONE ROOT only gets drawn for root bones (or without IK) */
static EditBone *get_nearest_editbonepoint(
- ViewContext *vc,
- bool findunsel, bool use_cycle,
- Base **r_base, int *r_selmask)
+ ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
{
- uint buffer[MAXPICKBUF];
- struct {
- uint hitresult;
- Base *base;
- EditBone *ebone;
- } best = {
- .hitresult = BONESEL_NOSEL,
- .base = NULL,
- .ebone = NULL,
- };
-
- /* find the bone after the current active bone, so as to bump up its chances in selection.
- * this way overlapping bones will cycle selection state as with objects. */
- EditBone *ebone_next_act = ((bArmature *)vc->obedit->data)->act_edbone;
- {
- bArmature *arm = (bArmature *)vc->obedit->data;
- if (ebone_next_act &&
- EBONE_VISIBLE(arm, ebone_next_act) &&
- ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))
- {
- ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
- }
- else {
- ebone_next_act = NULL;
- }
- }
-
- bool do_nearest = false;
-
- /* define if we use solid nearest select or not */
- if (use_cycle) {
- static int last_mval[2] = {-100, -100};
-
- if (!XRAY_ACTIVE(vc->v3d)) {
- do_nearest = true;
- if (len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
- do_nearest = false;
- }
- }
- copy_v2_v2_int(last_mval, vc->mval);
- }
- else {
- if (!XRAY_ACTIVE(vc->v3d)) {
- do_nearest = true;
- }
- }
-
- /* matching logic from 'mixed_bones_object_selectbuffer' */
- int hits = 0;
-
- /* we _must_ end cache before return, use 'goto cache_end' */
- view3d_opengl_select_cache_begin();
-
- {
- const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
- const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
-
- rcti rect;
- BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
- const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
- if (hits12 == 1) {
- hits = selectbuffer_ret_hits_12(buffer, hits12);
- goto cache_end;
- }
- else if (hits12 > 0) {
- int offs;
-
- offs = 4 * hits12;
- BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
- const int hits5 = view3d_opengl_select(
- vc, buffer + offs, MAXPICKBUF - offs, &rect,
- select_mode, select_filter);
-
- if (hits5 == 1) {
- hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
- goto cache_end;
- }
-
- if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); goto cache_end; }
- else { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; }
- }
- }
+ uint buffer[MAXPICKBUF];
+ struct {
+ uint hitresult;
+ Base *base;
+ EditBone *ebone;
+ } best = {
+ .hitresult = BONESEL_NOSEL,
+ .base = NULL,
+ .ebone = NULL,
+ };
+
+ /* find the bone after the current active bone, so as to bump up its chances in selection.
+ * this way overlapping bones will cycle selection state as with objects. */
+ EditBone *ebone_next_act = ((bArmature *)vc->obedit->data)->act_edbone;
+ {
+ bArmature *arm = (bArmature *)vc->obedit->data;
+ if (ebone_next_act && EBONE_VISIBLE(arm, ebone_next_act) &&
+ ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
+ ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
+ }
+ else {
+ ebone_next_act = NULL;
+ }
+ }
+
+ bool do_nearest = false;
+
+ /* define if we use solid nearest select or not */
+ if (use_cycle) {
+ static int last_mval[2] = {-100, -100};
+
+ if (!XRAY_ACTIVE(vc->v3d)) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, vc->mval);
+ }
+ else {
+ if (!XRAY_ACTIVE(vc->v3d)) {
+ do_nearest = true;
+ }
+ }
+
+ /* matching logic from 'mixed_bones_object_selectbuffer' */
+ int hits = 0;
+
+ /* we _must_ end cache before return, use 'goto cache_end' */
+ view3d_opengl_select_cache_begin();
+
+ {
+ const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
+
+ rcti rect;
+ BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
+ const int hits12 = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
+ if (hits12 == 1) {
+ hits = selectbuffer_ret_hits_12(buffer, hits12);
+ goto cache_end;
+ }
+ else if (hits12 > 0) {
+ int offs;
+
+ offs = 4 * hits12;
+ BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
+ const int hits5 = view3d_opengl_select(
+ vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
+
+ if (hits5 == 1) {
+ hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
+ goto cache_end;
+ }
+
+ if (hits5 > 0) {
+ hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
+ goto cache_end;
+ }
+ else {
+ hits = selectbuffer_ret_hits_12(buffer, hits12);
+ goto cache_end;
+ }
+ }
+ }
cache_end:
- view3d_opengl_select_cache_end();
-
- uint bases_len;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len);
-
- /* See if there are any selected bones in this group */
- if (hits > 0) {
- if (hits == 1) {
- if (!(buffer[3] & BONESEL_NOSEL)) {
- best.hitresult = buffer[3];
- best.base = ED_armature_base_and_ebone_from_select_buffer(
- bases, bases_len, best.hitresult, &best.ebone);
- }
- }
- else {
- int dep_min = 5;
- for (int i = 0; i < hits; i++) {
- const uint hitresult = buffer[3 + (i * 4)];
- if (!(hitresult & BONESEL_NOSEL)) {
- Base *base = NULL;
- EditBone *ebone;
- base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
- /* If this fails, selection code is setting the selection ID's incorrectly. */
- BLI_assert(base && ebone);
-
- int dep;
- /* clicks on bone points get advantage */
- if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
- /* but also the unselected one */
- if (findunsel) {
- if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
- dep = 1;
- else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
- dep = 1;
- else
- dep = 2;
- }
- else {
- dep = 1;
- }
- }
- else {
- /* bone found */
- if (findunsel) {
- if ((ebone->flag & BONE_SELECTED) == 0)
- dep = 3;
- else
- dep = 4;
- }
- else {
- dep = 3;
- }
- }
-
- if (ebone == ebone_next_act) {
- dep -= 1;
- }
-
- if (dep < dep_min) {
- dep_min = dep;
- best.hitresult = hitresult;
- best.base = base;
- best.ebone = ebone;
- }
- }
- }
- }
-
- if (!(best.hitresult & BONESEL_NOSEL)) {
- *r_base = best.base;
-
- *r_selmask = 0;
- if (best.hitresult & BONESEL_ROOT) {
- *r_selmask |= BONE_ROOTSEL;
- }
- if (best.hitresult & BONESEL_TIP) {
- *r_selmask |= BONE_TIPSEL;
- }
- if (best.hitresult & BONESEL_BONE) {
- *r_selmask |= BONE_SELECTED;
- }
- MEM_freeN(bases);
- return best.ebone;
- }
- }
- *r_selmask = 0;
- *r_base = NULL;
- MEM_freeN(bases);
- return NULL;
+ view3d_opengl_select_cache_end();
+
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc->view_layer, vc->v3d, &bases_len);
+
+ /* See if there are any selected bones in this group */
+ if (hits > 0) {
+ if (hits == 1) {
+ if (!(buffer[3] & BONESEL_NOSEL)) {
+ best.hitresult = buffer[3];
+ best.base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, best.hitresult, &best.ebone);
+ }
+ }
+ else {
+ int dep_min = 5;
+ for (int i = 0; i < hits; i++) {
+ const uint hitresult = buffer[3 + (i * 4)];
+ if (!(hitresult & BONESEL_NOSEL)) {
+ Base *base = NULL;
+ EditBone *ebone;
+ base = ED_armature_base_and_ebone_from_select_buffer(
+ bases, bases_len, hitresult, &ebone);
+ /* If this fails, selection code is setting the selection ID's incorrectly. */
+ BLI_assert(base && ebone);
+
+ int dep;
+ /* clicks on bone points get advantage */
+ if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
+ /* but also the unselected one */
+ if (findunsel) {
+ if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
+ dep = 1;
+ else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
+ dep = 1;
+ else
+ dep = 2;
+ }
+ else {
+ dep = 1;
+ }
+ }
+ else {
+ /* bone found */
+ if (findunsel) {
+ if ((ebone->flag & BONE_SELECTED) == 0)
+ dep = 3;
+ else
+ dep = 4;
+ }
+ else {
+ dep = 3;
+ }
+ }
+
+ if (ebone == ebone_next_act) {
+ dep -= 1;
+ }
+
+ if (dep < dep_min) {
+ dep_min = dep;
+ best.hitresult = hitresult;
+ best.base = base;
+ best.ebone = ebone;
+ }
+ }
+ }
+ }
+
+ if (!(best.hitresult & BONESEL_NOSEL)) {
+ *r_base = best.base;
+
+ *r_selmask = 0;
+ if (best.hitresult & BONESEL_ROOT) {
+ *r_selmask |= BONE_ROOTSEL;
+ }
+ if (best.hitresult & BONESEL_TIP) {
+ *r_selmask |= BONE_TIPSEL;
+ }
+ if (best.hitresult & BONESEL_BONE) {
+ *r_selmask |= BONE_SELECTED;
+ }
+ MEM_freeN(bases);
+ return best.ebone;
+ }
+ }
+ *r_selmask = 0;
+ *r_base = NULL;
+ MEM_freeN(bases);
+ return NULL;
}
bool ED_armature_edit_deselect_all(Object *obedit)
{
- bArmature *arm = obedit->data;
- bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- changed = true;
- }
- }
- return changed;
+ bArmature *arm = obedit->data;
+ bool changed = false;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ changed = true;
+ }
+ }
+ return changed;
}
bool ED_armature_edit_deselect_all_visible(Object *obedit)
{
- bArmature *arm = obedit->data;
- bool changed = false;
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- /* first and foremost, bone must be visible and selected */
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- changed = true;
- }
- }
- }
-
- if (changed) {
- ED_armature_edit_sync_selection(arm->edbo);
- }
- return changed;
+ bArmature *arm = obedit->data;
+ bool changed = false;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+ return changed;
}
-
bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- changed_multi |= ED_armature_edit_deselect_all(obedit);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ changed_multi |= ED_armature_edit_deselect_all(obedit);
+ }
+ return changed_multi;
}
bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len)
{
- bool changed_multi = false;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Object *obedit = bases[base_index]->object;
- changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
- }
- return changed_multi;
+ bool changed_multi = false;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *obedit = bases[base_index]->object;
+ changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
+ }
+ return changed_multi;
}
bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- return changed_multi;
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ return changed_multi;
}
/* accounts for connected parents */
static int ebone_select_flag(EditBone *ebone)
{
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
- }
- else {
- return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) |
+ (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
+ }
+ else {
+ return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
}
/* context: editmode armature in view3d */
-bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+bool ED_armature_edit_select_pick(
+ bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
- ViewContext vc;
- EditBone *nearBone = NULL;
- int selmask;
- Base *basact = NULL;
-
- ED_view3d_viewcontext_init(C, &vc);
- vc.mval[0] = mval[0];
- vc.mval[1] = mval[1];
-
- nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
- if (nearBone) {
- ED_view3d_viewcontext_init_object(&vc, basact->object);
- bArmature *arm = vc.obedit->data;
-
- if (!EBONE_SELECTABLE(arm, nearBone)) {
- return false;
- }
-
- if (!extend && !deselect && !toggle) {
- uint bases_len = 0;
- Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len);
- ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
- MEM_freeN(bases);
- }
-
- /* by definition the non-root connected bones have no root point drawn,
- * so a root selection needs to be delivered to the parent tip */
-
- if (selmask & BONE_SELECTED) {
- if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
- /* click in a chain */
- if (extend) {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- else if (deselect) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- if (extend) {
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (deselect) {
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED)
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- else {
- if (extend)
- nearBone->flag |= selmask;
- else if (deselect)
- nearBone->flag &= ~selmask;
- else if (toggle && (nearBone->flag & selmask))
- nearBone->flag &= ~selmask;
- else
- nearBone->flag |= selmask;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- /* then now check for active status */
- if (ebone_select_flag(nearBone)) {
- arm->act_edbone = nearBone;
- }
-
- if (vc.view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
- return true;
- }
-
- return false;
+ ViewContext vc;
+ EditBone *nearBone = NULL;
+ int selmask;
+ Base *basact = NULL;
+
+ ED_view3d_viewcontext_init(C, &vc);
+ vc.mval[0] = mval[0];
+ vc.mval[1] = mval[1];
+
+ nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
+ if (nearBone) {
+ ED_view3d_viewcontext_init_object(&vc, basact->object);
+ bArmature *arm = vc.obedit->data;
+
+ if (!EBONE_SELECTABLE(arm, nearBone)) {
+ return false;
+ }
+
+ if (!extend && !deselect && !toggle) {
+ uint bases_len = 0;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &bases_len);
+ ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
+ MEM_freeN(bases);
+ }
+
+ /* by definition the non-root connected bones have no root point drawn,
+ * so a root selection needs to be delivered to the parent tip */
+
+ if (selmask & BONE_SELECTED) {
+ if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
+ /* click in a chain */
+ if (extend) {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ else if (deselect) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if (extend) {
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (deselect) {
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED)
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ else {
+ if (extend)
+ nearBone->flag |= selmask;
+ else if (deselect)
+ nearBone->flag &= ~selmask;
+ else if (toggle && (nearBone->flag & selmask))
+ nearBone->flag &= ~selmask;
+ else
+ nearBone->flag |= selmask;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* then now check for active status */
+ if (ebone_select_flag(nearBone)) {
+ arm->act_edbone = nearBone;
+ }
+
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
+ return true;
+ }
+
+ return false;
}
/* -------------------------------------------------------------------- */
@@ -757,69 +775,73 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
* Implements #ED_armature_edit_select_op_from_tagged
* \{ */
-static bool armature_edit_select_op_apply(
- bArmature *arm, EditBone *ebone, const eSelectOp sel_op, int is_ignore_flag, int is_inside_flag)
+static bool armature_edit_select_op_apply(bArmature *arm,
+ EditBone *ebone,
+ const eSelectOp sel_op,
+ int is_ignore_flag,
+ int is_inside_flag)
{
- BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
- BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
- BLI_assert(EBONE_VISIBLE(arm, ebone));
- bool changed = false;
- bool is_point_done = false;
- int points_proj_tot = 0;
- BLI_assert(ebone->flag == ebone->temp.i);
- const int ebone_flag_prev = ebone->flag;
-
- if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
- points_proj_tot++;
- const bool is_select = ebone->flag & BONE_ROOTSEL;
- const bool is_inside = is_inside_flag & BONESEL_ROOT;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
- }
- }
- is_point_done |= is_inside;
- }
-
- if ((is_ignore_flag & BONE_TIPSEL) == 0) {
- points_proj_tot++;
- const bool is_select = ebone->flag & BONE_TIPSEL;
- const bool is_inside = is_inside_flag & BONESEL_TIP;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
- }
- }
- is_point_done |= is_inside;
- }
-
- /* if one of points selected, we skip the bone itself */
- if ((is_point_done == false) && (points_proj_tot == 2)) {
- const bool is_select = ebone->flag & BONE_SELECTED;
- {
- const bool is_inside = is_inside_flag & BONESEL_BONE;
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
- SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
- }
- }
-
- changed = true;
- }
- changed |= is_point_done;
-
- if (ebone_flag_prev != ebone->flag) {
- ebone->temp.i = ebone->flag;
- ebone->flag = ebone_flag_prev;
- ebone->flag = ebone_flag_prev | BONE_DONE;
- changed = true;
- }
-
- return changed;
+ BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
+ BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
+ BLI_assert(EBONE_VISIBLE(arm, ebone));
+ bool changed = false;
+ bool is_point_done = false;
+ int points_proj_tot = 0;
+ BLI_assert(ebone->flag == ebone->temp.i);
+ const int ebone_flag_prev = ebone->flag;
+
+ if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
+ points_proj_tot++;
+ const bool is_select = ebone->flag & BONE_ROOTSEL;
+ const bool is_inside = is_inside_flag & BONESEL_ROOT;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
+ }
+ }
+ is_point_done |= is_inside;
+ }
+
+ if ((is_ignore_flag & BONE_TIPSEL) == 0) {
+ points_proj_tot++;
+ const bool is_select = ebone->flag & BONE_TIPSEL;
+ const bool is_inside = is_inside_flag & BONESEL_TIP;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
+ }
+ }
+ is_point_done |= is_inside;
+ }
+
+ /* if one of points selected, we skip the bone itself */
+ if ((is_point_done == false) && (points_proj_tot == 2)) {
+ const bool is_select = ebone->flag & BONE_SELECTED;
+ {
+ const bool is_inside = is_inside_flag & BONESEL_BONE;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(
+ ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
+ }
+ }
+
+ changed = true;
+ }
+ changed |= is_point_done;
+
+ if (ebone_flag_prev != ebone->flag) {
+ ebone->temp.i = ebone->flag;
+ ebone->flag = ebone_flag_prev;
+ ebone->flag = ebone_flag_prev | BONE_DONE;
+ changed = true;
+ }
+
+ return changed;
}
/**
@@ -836,101 +858,97 @@ static bool armature_edit_select_op_apply(
*/
bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
{
- bool changed = false;
-
- /* Initialize flags. */
- {
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
-
- /* Flush the parent flag to this bone
- * so we don't need to check the parent when adjusting the selection. */
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- if (ebone->parent->flag & BONE_TIPSEL) {
- ebone->flag |= BONE_ROOTSEL;
- }
- else {
- ebone->flag &= ~BONE_ROOTSEL;
- }
-
- /* Flush the 'temp.i' flag. */
- if (ebone->parent->temp.i & BONESEL_TIP) {
- ebone->temp.i |= BONESEL_ROOT;
- }
- }
- ebone->flag &= ~BONE_DONE;
- }
- }
-
- /* Apply selection from bone selection flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->temp.i != 0) {
- int is_ignore_flag = ((ebone->temp.i << 16) & (BONESEL_ROOT | BONESEL_TIP));
- int is_inside_flag = (ebone->temp.i & (BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE));
-
- /* Use as previous bone flag from now on. */
- ebone->temp.i = ebone->flag;
-
- /* When there is a partial selection without both endpoints, only select an endpoint. */
- if ((is_inside_flag & BONESEL_BONE) &&
- (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
- ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP)))
- {
- is_inside_flag &= ~BONESEL_BONE;
- }
-
- changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
- }
- }
-
- if (changed) {
- /* Cleanup flags. */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->flag & BONE_DONE) {
- SWAP(int, ebone->temp.i, ebone->flag);
- ebone->flag |= BONE_DONE;
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- if ((ebone->parent->flag & BONE_DONE) == 0) {
- /* Checked below. */
- ebone->parent->temp.i = ebone->parent->flag;
- }
- }
- }
- }
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->flag & BONE_DONE) {
- if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
- bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) != (ebone->parent->temp.i & BONE_TIPSEL);
- if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
- if ((ebone->flag & BONE_ROOTSEL) != 0) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- if ((ebone->flag & BONE_ROOTSEL) == 0) {
- ebone->parent->flag &= ~BONE_TIPSEL;
-
- }
- }
-
-
- if (is_parent_tip_changed == false) {
- /* Keep tip selected if the parent remains selected. */
- if (ebone->parent->flag & BONE_SELECTED) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
- }
-
- }
- ebone->flag &= ~BONE_DONE;
- }
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
- ED_armature_edit_validate_active(arm);
- }
-
- return changed;
+ bool changed = false;
+
+ /* Initialize flags. */
+ {
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+
+ /* Flush the parent flag to this bone
+ * so we don't need to check the parent when adjusting the selection. */
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ if (ebone->parent->flag & BONE_TIPSEL) {
+ ebone->flag |= BONE_ROOTSEL;
+ }
+ else {
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+
+ /* Flush the 'temp.i' flag. */
+ if (ebone->parent->temp.i & BONESEL_TIP) {
+ ebone->temp.i |= BONESEL_ROOT;
+ }
+ }
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ /* Apply selection from bone selection flags. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.i != 0) {
+ int is_ignore_flag = ((ebone->temp.i << 16) & (BONESEL_ROOT | BONESEL_TIP));
+ int is_inside_flag = (ebone->temp.i & (BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE));
+
+ /* Use as previous bone flag from now on. */
+ ebone->temp.i = ebone->flag;
+
+ /* When there is a partial selection without both endpoints, only select an endpoint. */
+ if ((is_inside_flag & BONESEL_BONE) && (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
+ ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP))) {
+ is_inside_flag &= ~BONESEL_BONE;
+ }
+
+ changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
+ }
+ }
+
+ if (changed) {
+ /* Cleanup flags. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & BONE_DONE) {
+ SWAP(int, ebone->temp.i, ebone->flag);
+ ebone->flag |= BONE_DONE;
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ if ((ebone->parent->flag & BONE_DONE) == 0) {
+ /* Checked below. */
+ ebone->parent->temp.i = ebone->parent->flag;
+ }
+ }
+ }
+ }
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->flag & BONE_DONE) {
+ if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
+ bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) !=
+ (ebone->parent->temp.i & BONE_TIPSEL);
+ if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
+ if ((ebone->flag & BONE_ROOTSEL) != 0) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if ((ebone->flag & BONE_ROOTSEL) == 0) {
+ ebone->parent->flag &= ~BONE_TIPSEL;
+ }
+ }
+
+ if (is_parent_tip_changed == false) {
+ /* Keep tip selected if the parent remains selected. */
+ if (ebone->parent->flag & BONE_SELECTED) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ }
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_validate_active(arm);
+ }
+
+ return changed;
}
/** \} */
@@ -939,613 +957,612 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
{
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- /* Determine if there are any selected bones
- * And therefore whether we are selecting or deselecting */
- action = SEL_SELECT;
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
- action = SEL_DESELECT;
- break;
- }
- }
- CTX_DATA_END;
- }
-
- /* Set the flags */
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- /* ignore bone if selection can't change */
- switch (action) {
- case SEL_SELECT:
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent) {
- ebone->parent->flag |= (BONE_TIPSEL);
- }
- }
- break;
- case SEL_DESELECT:
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (ebone->flag & BONE_SELECTED) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent) {
- ebone->parent->flag |= (BONE_TIPSEL);
- }
- }
- }
- break;
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- return OPERATOR_FINISHED;
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ /* Determine if there are any selected bones
+ * And therefore whether we are selecting or deselecting */
+ action = SEL_SELECT;
+ CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
+ if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* Set the flags */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
+ /* ignore bone if selection can't change */
+ switch (action) {
+ case SEL_SELECT:
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent) {
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ }
+ break;
+ case SEL_DESELECT:
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (ebone->flag & BONE_SELECTED) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent) {
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ }
+ }
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "ARMATURE_OT_select_all";
- ot->description = "Toggle selection status of all bones";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "ARMATURE_OT_select_all";
+ ot->description = "Toggle selection status of all bones";
- /* api callbacks */
- ot->exec = armature_de_select_all_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_all_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/**************** Select more/less **************/
static void armature_select_more(bArmature *arm, EditBone *ebone)
{
- if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
-
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- /* to parent */
- if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
- if (EBONE_SELECTABLE(arm, ebone->parent)) {
- ED_armature_ebone_selectflag_enable(ebone->parent, (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
- }
- }
-
- /* from parent (difference from select less) */
- if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
- }
- }
- }
+ if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ /* to parent */
+ if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone->parent)) {
+ ED_armature_ebone_selectflag_enable(ebone->parent,
+ (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
+ }
+ }
+
+ /* from parent (difference from select less) */
+ if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
+ }
+ }
+ }
}
static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
{
- if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != (BONE_ROOTSEL | BONE_TIPSEL)) {
- ED_armature_ebone_select_set(ebone, false);
- }
-
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- /* to parent */
- if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
- ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
- }
-
- /* from parent (difference from select more) */
- if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
- ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
- }
- }
+ if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) !=
+ (BONE_ROOTSEL | BONE_TIPSEL)) {
+ ED_armature_ebone_select_set(ebone, false);
+ }
+
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ /* to parent */
+ if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
+ ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
+ }
+
+ /* from parent (difference from select more) */
+ if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
+ ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
+ }
+ }
}
static void armature_select_more_less(Object *ob, bool more)
{
- bArmature *arm = (bArmature *)ob->data;
- EditBone *ebone;
-
- /* XXX, eventually we shouldn't need this - campbell */
- ED_armature_edit_sync_selection(arm->edbo);
-
- /* count bones & store selection state */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
- }
-
- /* do selection */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (more) {
- armature_select_more(arm, ebone);
- }
- else {
- armature_select_less(arm, ebone);
- }
- }
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (more == false) {
- if (ebone->flag & BONE_SELECTED) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
- }
- ebone->temp.p = NULL;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *ebone;
+
+ /* XXX, eventually we shouldn't need this - campbell */
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* count bones & store selection state */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
+ }
+
+ /* do selection */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (more) {
+ armature_select_more(arm, ebone);
+ }
+ else {
+ armature_select_less(arm, ebone);
+ }
+ }
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (more == false) {
+ if (ebone->flag & BONE_SELECTED) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+ }
+ ebone->temp.p = NULL;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
}
static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- armature_select_more_less(ob, true);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ armature_select_more_less(ob, true);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "ARMATURE_OT_select_more";
- ot->description = "Select those bones connected to the initial selection";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "ARMATURE_OT_select_more";
+ ot->description = "Select those bones connected to the initial selection";
- /* api callbacks */
- ot->exec = armature_de_select_more_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_more_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- armature_select_more_less(ob, false);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ armature_select_more_less(ob, false);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "ARMATURE_OT_select_less";
- ot->description = "Deselect those bones at the boundary of each selection region";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "ARMATURE_OT_select_less";
+ ot->description = "Deselect those bones at the boundary of each selection region";
- /* api callbacks */
- ot->exec = armature_de_select_less_exec;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->exec = armature_de_select_less_exec;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
enum {
- SIMEDBONE_CHILDREN = 1,
- SIMEDBONE_CHILDREN_IMMEDIATE,
- SIMEDBONE_SIBLINGS,
- SIMEDBONE_LENGTH,
- SIMEDBONE_DIRECTION,
- SIMEDBONE_PREFIX,
- SIMEDBONE_SUFFIX,
- SIMEDBONE_LAYER,
- SIMEDBONE_GROUP,
- SIMEDBONE_SHAPE,
+ SIMEDBONE_CHILDREN = 1,
+ SIMEDBONE_CHILDREN_IMMEDIATE,
+ SIMEDBONE_SIBLINGS,
+ SIMEDBONE_LENGTH,
+ SIMEDBONE_DIRECTION,
+ SIMEDBONE_PREFIX,
+ SIMEDBONE_SUFFIX,
+ SIMEDBONE_LAYER,
+ SIMEDBONE_GROUP,
+ SIMEDBONE_SHAPE,
};
static const EnumPropertyItem prop_similar_types[] = {
- {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
- {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
- {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
- {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
- {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
- {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
- {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
- {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
- {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
- {0, NULL, 0, NULL, NULL},
+ {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
+ {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
+ {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
+ {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
+ {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
+ {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
+ {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
+ {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
+ {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
+ {0, NULL, 0, NULL, NULL},
};
static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone)
{
- float v1[3], v2[3];
- mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
- mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
- return len_squared_v3v3(v1, v2);
+ float v1[3], v2[3];
+ mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
+ mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
+ return len_squared_v3v3(v1, v2);
}
static void select_similar_length(bContext *C, const float thresh)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_act = CTX_data_edit_object(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- /* Thresh is always relative to current length. */
- const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
- const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
- const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bool changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- const float len_iter = bone_length_squared_worldspace_get(ob, ebone);
- if ((len_iter > len_min) &&
- (len_iter < len_max))
- {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_act = CTX_data_edit_object(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ /* Thresh is always relative to current length. */
+ const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
+ const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
+ const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bool changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ const float len_iter = bone_length_squared_worldspace_get(ob, ebone);
+ if ((len_iter > len_min) && (len_iter < len_max)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_dir)
{
- float v1[3], v2[3];
- copy_v3_v3(v1, ebone->head);
- copy_v3_v3(v2, ebone->tail);
+ float v1[3], v2[3];
+ copy_v3_v3(v1, ebone->head);
+ copy_v3_v3(v2, ebone->tail);
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
- sub_v3_v3v3(r_dir, v1, v2);
- normalize_v3(r_dir);
+ sub_v3_v3v3(r_dir, v1, v2);
+ normalize_v3(r_dir);
}
static void select_similar_direction(bContext *C, const float thresh)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_act = CTX_data_edit_object(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- float dir_act[3];
- bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bool changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- float dir[3];
- bone_direction_worldspace_get(ob, ebone, dir);
-
- if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_act = CTX_data_edit_object(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ float dir_act[3];
+ bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bool changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ float dir[3];
+ bone_direction_worldspace_get(ob, ebone, dir);
+
+ if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_layer(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bool changed = false;
-
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- if (ebone->layer & ebone_act->layer) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bool changed = false;
+
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ if (ebone->layer & ebone_act->layer) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_prefix(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- char body_tmp[MAXBONENAME];
- char prefix_act[MAXBONENAME];
-
- BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
-
- if (prefix_act[0] == '\0') {
- return;
- }
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bool changed = false;
-
- /* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char prefix_other[MAXBONENAME];
- BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
- if (STREQ(prefix_act, prefix_other)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ char body_tmp[MAXBONENAME];
+ char prefix_act[MAXBONENAME];
+
+ BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
+
+ if (prefix_act[0] == '\0') {
+ return;
+ }
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bool changed = false;
+
+ /* Find matches */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char prefix_other[MAXBONENAME];
+ BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
+ if (STREQ(prefix_act, prefix_other)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
static void select_similar_suffix(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- char body_tmp[MAXBONENAME];
- char suffix_act[MAXBONENAME];
-
- BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
-
- if (suffix_act[0] == '\0')
- return;
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
- bool changed = false;
-
- /* Find matches */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char suffix_other[MAXBONENAME];
- BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
- if (STREQ(suffix_act, suffix_other)) {
- ED_armature_ebone_select_set(ebone, true);
- changed = true;
- }
- }
- }
-
- if (changed) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- }
- MEM_freeN(objects);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ char body_tmp[MAXBONENAME];
+ char suffix_act[MAXBONENAME];
+
+ BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
+
+ if (suffix_act[0] == '\0')
+ return;
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+ bool changed = false;
+
+ /* Find matches */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char suffix_other[MAXBONENAME];
+ BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
+ if (STREQ(suffix_act, suffix_other)) {
+ ED_armature_ebone_select_set(ebone, true);
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ }
+ MEM_freeN(objects);
}
/** Use for matching any pose channel data. */
-static void select_similar_data_pchan(
- bContext *C,
- const size_t bytes_size, const int offset)
+static void select_similar_data_pchan(bContext *C, const size_t bytes_size, const int offset)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
- const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
- if (pchan) {
- const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
- if (memcmp(data_active, data_test, bytes_size) == 0) {
- ED_armature_ebone_select_set(ebone, true);
- }
- }
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
+ const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
+ if (pchan) {
+ const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
+ if (memcmp(data_active, data_test, bytes_size) == 0) {
+ ED_armature_ebone_select_set(ebone, true);
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void is_ancestor(EditBone *bone, EditBone *ancestor)
{
- if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
- return;
+ if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
+ return;
- if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
- is_ancestor(bone->temp.ebone, ancestor);
+ if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
+ is_ancestor(bone->temp.ebone, ancestor);
- bone->temp.ebone = bone->temp.ebone->temp.ebone;
+ bone->temp.ebone = bone->temp.ebone->temp.ebone;
}
static void select_similar_children(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- ebone_iter->temp.ebone = ebone_iter->parent;
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ ebone_iter->temp.ebone = ebone_iter->parent;
+ }
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- is_ancestor(ebone_iter, ebone_act);
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ is_ancestor(ebone_iter, ebone_act);
- if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
- ED_armature_ebone_select_set(ebone_iter, true);
- }
+ if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void select_similar_children_immediate(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
- ED_armature_ebone_select_set(ebone_iter, true);
- }
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static void select_similar_siblings(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
- if (ebone_act->parent == NULL) {
- return;
- }
+ if (ebone_act->parent == NULL) {
+ return;
+ }
- for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
- ED_armature_ebone_select_set(ebone_iter, true);
- }
- }
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
+ ED_armature_ebone_select_set(ebone_iter, true);
+ }
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
static int armature_select_similar_exec(bContext *C, wmOperator *op)
{
- /* Get props */
- int type = RNA_enum_get(op->ptr, "type");
- float thresh = RNA_float_get(op->ptr, "threshold");
+ /* Get props */
+ int type = RNA_enum_get(op->ptr, "type");
+ float thresh = RNA_float_get(op->ptr, "threshold");
- /* Check for active bone */
- if (CTX_data_active_bone(C) == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
+ /* Check for active bone */
+ if (CTX_data_active_bone(C) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
#define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
- sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
-
- switch (type) {
- case SIMEDBONE_CHILDREN:
- select_similar_children(C);
- break;
- case SIMEDBONE_CHILDREN_IMMEDIATE:
- select_similar_children_immediate(C);
- break;
- case SIMEDBONE_SIBLINGS:
- select_similar_siblings(C);
- break;
- case SIMEDBONE_LENGTH:
- select_similar_length(C, thresh);
- break;
- case SIMEDBONE_DIRECTION:
- select_similar_direction(C, thresh);
- break;
- case SIMEDBONE_PREFIX:
- select_similar_prefix(C);
- break;
- case SIMEDBONE_SUFFIX:
- select_similar_suffix(C);
- break;
- case SIMEDBONE_LAYER:
- select_similar_layer(C);
- break;
- case SIMEDBONE_GROUP:
- select_similar_data_pchan(
- C,
- STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
- break;
- case SIMEDBONE_SHAPE:
- select_similar_data_pchan(
- C,
- STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
- break;
- }
+ sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
+
+ switch (type) {
+ case SIMEDBONE_CHILDREN:
+ select_similar_children(C);
+ break;
+ case SIMEDBONE_CHILDREN_IMMEDIATE:
+ select_similar_children_immediate(C);
+ break;
+ case SIMEDBONE_SIBLINGS:
+ select_similar_siblings(C);
+ break;
+ case SIMEDBONE_LENGTH:
+ select_similar_length(C, thresh);
+ break;
+ case SIMEDBONE_DIRECTION:
+ select_similar_direction(C, thresh);
+ break;
+ case SIMEDBONE_PREFIX:
+ select_similar_prefix(C);
+ break;
+ case SIMEDBONE_SUFFIX:
+ select_similar_suffix(C);
+ break;
+ case SIMEDBONE_LAYER:
+ select_similar_layer(C);
+ break;
+ case SIMEDBONE_GROUP:
+ select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
+ break;
+ case SIMEDBONE_SHAPE:
+ select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
+ break;
+ }
#undef STRUCT_SIZE_AND_OFFSET
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_similar(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "ARMATURE_OT_select_similar";
-
- /* callback functions */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_select_similar_exec;
- ot->poll = ED_operator_editarmature;
- ot->description = "Select similar bones by property types";
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
- RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "ARMATURE_OT_select_similar";
+
+ /* callback functions */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_select_similar_exec;
+ ot->poll = ED_operator_editarmature;
+ ot->description = "Select similar bones by property types";
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
+ RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
/* ********************* select hierarchy operator ************** */
@@ -1554,103 +1571,101 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
* selected we then keep the non-active objects untouched (selected/unselected). */
static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- EditBone *ebone_active;
- int direction = RNA_enum_get(op->ptr, "direction");
- const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
- bool changed = false;
- bArmature *arm = (bArmature *)ob->data;
-
- ebone_active = arm->act_edbone;
- if (ebone_active == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (direction == BONE_SELECT_PARENT) {
- if (ebone_active->parent) {
- EditBone *ebone_parent;
-
- ebone_parent = ebone_active->parent;
-
- if (EBONE_SELECTABLE(arm, ebone_parent)) {
- arm->act_edbone = ebone_parent;
-
- if (!add_to_sel) {
- ED_armature_ebone_select_set(ebone_active, false);
- }
- ED_armature_ebone_select_set(ebone_parent, true);
-
- changed = true;
- }
- }
-
- }
- else { /* BONE_SELECT_CHILD */
- EditBone *ebone_iter, *ebone_child = NULL;
- int pass;
-
- /* first pass, only connected bones (the logical direct child) */
- for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
- for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
- /* possible we have multiple children, some invisible */
- if (EBONE_SELECTABLE(arm, ebone_iter)) {
- if (ebone_iter->parent == ebone_active) {
- if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
- ebone_child = ebone_iter;
- break;
- }
- }
- }
- }
- }
-
- if (ebone_child) {
- arm->act_edbone = ebone_child;
-
- if (!add_to_sel) {
- ED_armature_ebone_select_set(ebone_active, false);
- }
- ED_armature_ebone_select_set(ebone_child, true);
-
- changed = true;
- }
- }
-
- if (changed == false) {
- return OPERATOR_CANCELLED;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ EditBone *ebone_active;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
+ bArmature *arm = (bArmature *)ob->data;
+
+ ebone_active = arm->act_edbone;
+ if (ebone_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (direction == BONE_SELECT_PARENT) {
+ if (ebone_active->parent) {
+ EditBone *ebone_parent;
+
+ ebone_parent = ebone_active->parent;
+
+ if (EBONE_SELECTABLE(arm, ebone_parent)) {
+ arm->act_edbone = ebone_parent;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_parent, true);
+
+ changed = true;
+ }
+ }
+ }
+ else { /* BONE_SELECT_CHILD */
+ EditBone *ebone_iter, *ebone_child = NULL;
+ int pass;
+
+ /* first pass, only connected bones (the logical direct child) */
+ for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
+ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ /* possible we have multiple children, some invisible */
+ if (EBONE_SELECTABLE(arm, ebone_iter)) {
+ if (ebone_iter->parent == ebone_active) {
+ if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
+ ebone_child = ebone_iter;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (ebone_child) {
+ arm->act_edbone = ebone_child;
+
+ if (!add_to_sel) {
+ ED_armature_ebone_select_set(ebone_active, false);
+ }
+ ED_armature_ebone_select_set(ebone_child, true);
+
+ changed = true;
+ }
+ }
+
+ if (changed == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
{
- static const EnumPropertyItem direction_items[] = {
- {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
- {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Select Hierarchy";
- ot->idname = "ARMATURE_OT_select_hierarchy";
- ot->description = "Select immediate parent/children of selected bones";
-
- /* api callbacks */
- ot->exec = armature_select_hierarchy_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items,
- BONE_SELECT_PARENT, "Direction", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ static const EnumPropertyItem direction_items[] = {
+ {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Select Hierarchy";
+ ot->idname = "ARMATURE_OT_select_hierarchy";
+ ot->description = "Select immediate parent/children of selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_select_hierarchy_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/****************** Mirror Select ****************/
@@ -1660,202 +1675,199 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
*/
static int armature_select_mirror_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool active_only = RNA_boolean_get(op->ptr, "only_active");
- const bool extend = RNA_boolean_get(op->ptr, "extend");
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
- bArmature *arm = ob->data;
-
- EditBone *ebone, *ebone_mirror_act = NULL;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- const int flag = ED_armature_ebone_selectflag_get(ebone);
- EBONE_PREV_FLAG_SET(ebone, flag);
- }
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- EditBone *ebone_mirror;
- int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
-
- if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
- (EBONE_VISIBLE(arm, ebone_mirror)))
- {
- const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
- flag_new |= flag_mirror;
-
- if (ebone == arm->act_edbone) {
- ebone_mirror_act = ebone_mirror;
- }
-
- /* skip all but the active or its mirror */
- if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
- continue;
- }
- }
-
- ED_armature_ebone_selectflag_set(ebone, flag_new);
- }
- }
-
- if (ebone_mirror_act) {
- arm->act_edbone = ebone_mirror_act;
- }
-
- ED_armature_edit_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool active_only = RNA_boolean_get(op->ptr, "only_active");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+
+ EditBone *ebone, *ebone_mirror_act = NULL;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ const int flag = ED_armature_ebone_selectflag_get(ebone);
+ EBONE_PREV_FLAG_SET(ebone, flag);
+ }
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ EditBone *ebone_mirror;
+ int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
+
+ if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
+ (EBONE_VISIBLE(arm, ebone_mirror))) {
+ const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
+ flag_new |= flag_mirror;
+
+ if (ebone == arm->act_edbone) {
+ ebone_mirror_act = ebone_mirror;
+ }
+
+ /* skip all but the active or its mirror */
+ if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
+ continue;
+ }
+ }
+
+ ED_armature_ebone_selectflag_set(ebone, flag_new);
+ }
+ }
+
+ if (ebone_mirror_act) {
+ arm->act_edbone = ebone_mirror_act;
+ }
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void ARMATURE_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Flip Active/Selected Bone";
- ot->idname = "ARMATURE_OT_select_mirror";
- ot->description = "Mirror the bone selection";
-
- /* api callbacks */
- ot->exec = armature_select_mirror_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+ /* identifiers */
+ ot->name = "Flip Active/Selected Bone";
+ ot->idname = "ARMATURE_OT_select_mirror";
+ ot->description = "Mirror the bone selection";
+
+ /* api callbacks */
+ ot->exec = armature_select_mirror_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-
/****************** Select Path ****************/
-static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child,
- bool use_parent, bool is_test)
+static bool armature_shortest_path_select(
+ bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
{
- do {
+ do {
- if (!use_parent && (ebone_child == ebone_parent))
- break;
+ if (!use_parent && (ebone_child == ebone_parent))
+ break;
- if (is_test) {
- if (!EBONE_SELECTABLE(arm, ebone_child)) {
- return false;
- }
- }
- else {
- ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
- }
+ if (is_test) {
+ if (!EBONE_SELECTABLE(arm, ebone_child)) {
+ return false;
+ }
+ }
+ else {
+ ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
+ }
- if (ebone_child == ebone_parent)
- break;
+ if (ebone_child == ebone_parent)
+ break;
- ebone_child = ebone_child->parent;
- } while (true);
+ ebone_child = ebone_child->parent;
+ } while (true);
- return true;
+ return true;
}
static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_src, *ebone_dst;
- EditBone *ebone_isect_parent = NULL;
- EditBone *ebone_isect_child[2];
- bool changed;
- Base *base_dst = NULL;
-
- view3d_operator_needs_opengl(C);
-
- ebone_src = arm->act_edbone;
- ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
-
- /* fallback to object selection */
- if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (base_dst && base_dst->object != obedit) {
- /* Disconnected, ignore. */
- return OPERATOR_CANCELLED;
- }
-
- ebone_isect_child[0] = ebone_src;
- ebone_isect_child[1] = ebone_dst;
-
-
- /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
- if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
- /* pass */
- }
- else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
- SWAP(EditBone *, ebone_src, ebone_dst);
- }
- else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
- /* pass */
- }
- else {
- /* disconnected bones */
- return OPERATOR_CANCELLED;
- }
-
-
- if (ebone_isect_parent) {
- if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true))
- {
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
- armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
- changed = true;
- }
- else {
- /* unselectable */
- changed = false;
- }
- }
- else {
- if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
- armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
- changed = true;
- }
- else {
- /* unselectable */
- changed = false;
- }
- }
-
- if (changed) {
- arm->act_edbone = ebone_dst;
- ED_armature_edit_sync_selection(arm->edbo);
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
- return OPERATOR_CANCELLED;
- }
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_src, *ebone_dst;
+ EditBone *ebone_isect_parent = NULL;
+ EditBone *ebone_isect_child[2];
+ bool changed;
+ Base *base_dst = NULL;
+
+ view3d_operator_needs_opengl(C);
+
+ ebone_src = arm->act_edbone;
+ ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
+
+ /* fallback to object selection */
+ if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (base_dst && base_dst->object != obedit) {
+ /* Disconnected, ignore. */
+ return OPERATOR_CANCELLED;
+ }
+
+ ebone_isect_child[0] = ebone_src;
+ ebone_isect_child[1] = ebone_dst;
+
+ /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
+ if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
+ /* pass */
+ }
+ else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
+ SWAP(EditBone *, ebone_src, ebone_dst);
+ }
+ else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
+ /* pass */
+ }
+ else {
+ /* disconnected bones */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ebone_isect_parent) {
+ if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true)) {
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+ else {
+ if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
+ armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+
+ if (changed) {
+ arm->act_edbone = ebone_dst;
+ ED_armature_edit_sync_selection(arm->edbo);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
+ return OPERATOR_CANCELLED;
+ }
}
void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Pick Shortest Path";
- ot->idname = "ARMATURE_OT_shortest_path_pick";
- ot->description = "Select shortest path between two bones";
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "ARMATURE_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two bones";
- /* api callbacks */
- ot->invoke = armature_shortest_path_pick_invoke;
- ot->poll = ED_operator_editarmature;
+ /* api callbacks */
+ ot->invoke = armature_shortest_path_pick_invoke;
+ ot->poll = ED_operator_editarmature;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}