|
|
|
@ -313,7 +313,64 @@ void ANIM_set_active_channel(bAnimContext *ac,
|
|
|
|
|
ANIM_animdata_freelist(&anim_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, bAnimListElem *ale)
|
|
|
|
|
bool ANIM_is_active_channel(bAnimListElem *ale)
|
|
|
|
|
{
|
|
|
|
|
switch (ale->type) {
|
|
|
|
|
case ANIMTYPE_FILLACTD: /* Action Expander */
|
|
|
|
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
|
|
|
|
case ANIMTYPE_DSLAM:
|
|
|
|
|
case ANIMTYPE_DSCAM:
|
|
|
|
|
case ANIMTYPE_DSCACHEFILE:
|
|
|
|
|
case ANIMTYPE_DSCUR:
|
|
|
|
|
case ANIMTYPE_DSSKEY:
|
|
|
|
|
case ANIMTYPE_DSWOR:
|
|
|
|
|
case ANIMTYPE_DSPART:
|
|
|
|
|
case ANIMTYPE_DSMBALL:
|
|
|
|
|
case ANIMTYPE_DSARM:
|
|
|
|
|
case ANIMTYPE_DSMESH:
|
|
|
|
|
case ANIMTYPE_DSNTREE:
|
|
|
|
|
case ANIMTYPE_DSTEX:
|
|
|
|
|
case ANIMTYPE_DSLAT:
|
|
|
|
|
case ANIMTYPE_DSLINESTYLE:
|
|
|
|
|
case ANIMTYPE_DSSPK:
|
|
|
|
|
case ANIMTYPE_DSGPENCIL:
|
|
|
|
|
case ANIMTYPE_DSMCLIP:
|
|
|
|
|
case ANIMTYPE_DSHAIR:
|
|
|
|
|
case ANIMTYPE_DSPOINTCLOUD:
|
|
|
|
|
case ANIMTYPE_DSVOLUME:
|
|
|
|
|
case ANIMTYPE_NLAACTION:
|
|
|
|
|
case ANIMTYPE_DSSIMULATION: {
|
|
|
|
|
if (ale->adt) {
|
|
|
|
|
return ale->adt->flag & ADT_UI_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case ANIMTYPE_GROUP: {
|
|
|
|
|
bActionGroup *argp = (bActionGroup *)ale->data;
|
|
|
|
|
return argp->flag & AGRP_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
case ANIMTYPE_FCURVE:
|
|
|
|
|
case ANIMTYPE_NLACURVE: {
|
|
|
|
|
FCurve *fcu = (FCurve *)ale->data;
|
|
|
|
|
return fcu->flag & FCURVE_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
case ANIMTYPE_GPLAYER: {
|
|
|
|
|
bGPDlayer *gpl = (bGPDlayer *)ale->data;
|
|
|
|
|
return gpl->flag & GP_LAYER_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
/* These channel types do not have active flags. */
|
|
|
|
|
case ANIMTYPE_MASKLAYER:
|
|
|
|
|
case ANIMTYPE_SHAPEKEY:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* change_active determines whether to change the active bone of the armature when selecting pose
|
|
|
|
|
* channels. It is false during range selection otherwise true. */
|
|
|
|
|
static void select_pchan_for_action_group(bAnimContext *ac,
|
|
|
|
|
bActionGroup *agrp,
|
|
|
|
|
bAnimListElem *ale,
|
|
|
|
|
const bool change_active)
|
|
|
|
|
{
|
|
|
|
|
/* Armatures-Specific Feature:
|
|
|
|
|
* See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (#38737)
|
|
|
|
@ -329,11 +386,12 @@ static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp,
|
|
|
|
|
* TODO: check the first F-Curve or so to be sure...
|
|
|
|
|
*/
|
|
|
|
|
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
|
|
|
|
|
|
|
|
|
|
if (agrp->flag & AGRP_SELECTED) {
|
|
|
|
|
ED_pose_bone_select(ob, pchan, true);
|
|
|
|
|
ED_pose_bone_select(ob, pchan, true, change_active);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ED_pose_bone_select(ob, pchan, false);
|
|
|
|
|
ED_pose_bone_select(ob, pchan, false, change_active);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -441,10 +499,15 @@ static void anim_channels_select_set(bAnimContext *ac,
|
|
|
|
|
eAnimChannels_SetFlag sel)
|
|
|
|
|
{
|
|
|
|
|
bAnimListElem *ale;
|
|
|
|
|
/* Boolean to keep active channel status during range selection. */
|
|
|
|
|
const bool change_active = (sel != ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
|
|
|
|
|
for (ale = anim_data.first; ale; ale = ale->next) {
|
|
|
|
|
switch (ale->type) {
|
|
|
|
|
case ANIMTYPE_SCENE: {
|
|
|
|
|
if (change_active) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
Scene *scene = (Scene *)ale->data;
|
|
|
|
|
|
|
|
|
|
ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
|
|
|
|
@ -471,8 +534,10 @@ static void anim_channels_select_set(bAnimContext *ac,
|
|
|
|
|
case ANIMTYPE_GROUP: {
|
|
|
|
|
bActionGroup *agrp = (bActionGroup *)ale->data;
|
|
|
|
|
ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
|
|
|
|
|
select_pchan_for_action_group(ac, agrp, ale);
|
|
|
|
|
select_pchan_for_action_group(ac, agrp, ale, change_active);
|
|
|
|
|
if (change_active) {
|
|
|
|
|
agrp->flag &= ~AGRP_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ANIMTYPE_FCURVE:
|
|
|
|
@ -480,7 +545,7 @@ static void anim_channels_select_set(bAnimContext *ac,
|
|
|
|
|
FCurve *fcu = (FCurve *)ale->data;
|
|
|
|
|
|
|
|
|
|
ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
|
|
|
|
|
if ((fcu->flag & FCURVE_SELECTED) == 0) {
|
|
|
|
|
if (!(fcu->flag & FCURVE_SELECTED) && change_active) {
|
|
|
|
|
/* Only erase the ACTIVE flag when deselecting. This ensures that "select all curves"
|
|
|
|
|
* retains the currently active curve. */
|
|
|
|
|
fcu->flag &= ~FCURVE_ACTIVE;
|
|
|
|
@ -527,8 +592,10 @@ static void anim_channels_select_set(bAnimContext *ac,
|
|
|
|
|
/* need to verify that this data is valid for now */
|
|
|
|
|
if (ale->adt) {
|
|
|
|
|
ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
|
|
|
|
|
if (change_active) {
|
|
|
|
|
ale->adt->flag &= ~ADT_UI_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ANIMTYPE_GPLAYER: {
|
|
|
|
@ -2891,7 +2958,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
|
|
|
|
|
switch (ale->type) {
|
|
|
|
|
case ANIMTYPE_GROUP: {
|
|
|
|
|
bActionGroup *agrp = (bActionGroup *)ale->data;
|
|
|
|
|
select_pchan_for_action_group(ac, agrp, ale);
|
|
|
|
|
select_pchan_for_action_group(ac, agrp, ale, true);
|
|
|
|
|
/* always clear active flag after doing this */
|
|
|
|
|
agrp->flag &= ~AGRP_ACTIVE;
|
|
|
|
|
break;
|
|
|
|
@ -3172,6 +3239,70 @@ static int click_select_channel_scene(bAnimListElem *ale,
|
|
|
|
|
return (ND_ANIMCHAN | NA_SELECTED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return whether active channel of given type is present. */
|
|
|
|
|
static bool animchannel_has_active_of_type(bAnimContext *ac, const eAnim_ChannelType type)
|
|
|
|
|
{
|
|
|
|
|
ListBase anim_data = anim_channels_for_selection(ac);
|
|
|
|
|
bool is_active_found = false;
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
|
|
|
|
if (ale->type != type) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
is_active_found = ANIM_is_active_channel(ale);
|
|
|
|
|
if (is_active_found) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ANIM_animdata_freelist(&anim_data);
|
|
|
|
|
return is_active_found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Select channels that lies between active channel and cursor_elem. */
|
|
|
|
|
static void animchannel_select_range(bAnimContext *ac, bAnimListElem *cursor_elem)
|
|
|
|
|
{
|
|
|
|
|
ListBase anim_data = anim_channels_for_selection(ac);
|
|
|
|
|
bool in_selection_range = false;
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
|
|
|
|
|
|
|
|
|
/* Allow selection when active channel and `cursor_elem` are of same type. */
|
|
|
|
|
if (ale->type != cursor_elem->type) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool is_cursor_elem = (ale->data == cursor_elem->data);
|
|
|
|
|
const bool is_active_elem = ANIM_is_active_channel(ale);
|
|
|
|
|
|
|
|
|
|
/* Restrict selection when active element is not found and group-channels are excluded from the
|
|
|
|
|
* selection. */
|
|
|
|
|
if (is_active_elem || is_cursor_elem) {
|
|
|
|
|
/* Select first and last element from the range. Reverse selection status on extremes. */
|
|
|
|
|
ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
|
|
|
|
|
in_selection_range = !in_selection_range;
|
|
|
|
|
if (ale->type == ANIMTYPE_GROUP) {
|
|
|
|
|
select_pchan_for_action_group(ac, (bActionGroup *)ale->data, ale, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (in_selection_range) {
|
|
|
|
|
/* Select elements between the range. */
|
|
|
|
|
ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD);
|
|
|
|
|
if (ale->type == ANIMTYPE_GROUP) {
|
|
|
|
|
select_pchan_for_action_group(ac, (bActionGroup *)ale->data, ale, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_active_elem && is_cursor_elem) {
|
|
|
|
|
/* Selection range is only one element when active channel and clicked channel are same. So
|
|
|
|
|
* exit out of the loop when this condition is hit. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ANIM_animdata_freelist(&anim_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int click_select_channel_object(bContext *C,
|
|
|
|
|
bAnimContext *ac,
|
|
|
|
|
bAnimListElem *ale,
|
|
|
|
@ -3195,8 +3326,13 @@ static int click_select_channel_object(bContext *C,
|
|
|
|
|
adt->flag ^= ADT_UI_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
animchannel_select_range(ac, ale);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* deselect all */
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
|
|
|
|
BKE_view_layer_synced_ensure(scene, view_layer);
|
|
|
|
|
/* TODO: should this deselect all other types of channels too? */
|
|
|
|
|
LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) {
|
|
|
|
@ -3219,7 +3355,8 @@ static int click_select_channel_object(bContext *C,
|
|
|
|
|
* to avoid getting stuck there, see: #48747. */
|
|
|
|
|
ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
|
|
|
|
|
|
|
|
|
|
if ((adt) && (adt->flag & ADT_UI_SELECTED)) {
|
|
|
|
|
/* Similar to outliner, do not change active element when selecting elements in range.*/
|
|
|
|
|
if ((adt) && (adt->flag & ADT_UI_SELECTED) && (selectmode != SELECT_EXTEND_RANGE)) {
|
|
|
|
|
adt->flag |= ADT_UI_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3239,14 +3376,18 @@ static int click_select_channel_dummy(bAnimContext *ac,
|
|
|
|
|
/* inverse selection status of this AnimData block only */
|
|
|
|
|
ale->adt->flag ^= ADT_UI_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
animchannel_select_range(ac, ale);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* select AnimData block by itself */
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
|
|
|
|
ale->adt->flag |= ADT_UI_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set active? */
|
|
|
|
|
if (ale->adt->flag & ADT_UI_SELECTED) {
|
|
|
|
|
/* Similar to outliner, do not change active element when selecting elements in range. */
|
|
|
|
|
if ((ale->adt->flag & ADT_UI_SELECTED) && (selectmode != SELECT_EXTEND_RANGE)) {
|
|
|
|
|
ale->adt->flag |= ADT_UI_ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3292,6 +3433,10 @@ static int click_select_channel_group(bAnimContext *ac,
|
|
|
|
|
/* inverse selection status of this group only */
|
|
|
|
|
agrp->flag ^= AGRP_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
animchannel_select_range(ac, ale);
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == -1) {
|
|
|
|
|
/* select all in group (and deselect everything else) */
|
|
|
|
|
FCurve *fcu;
|
|
|
|
@ -3318,17 +3463,22 @@ static int click_select_channel_group(bAnimContext *ac,
|
|
|
|
|
agrp->flag |= AGRP_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if group is selected now, make group the 'active' one in the visible list */
|
|
|
|
|
/* if group is selected now, make group the 'active' one in the visible list.
|
|
|
|
|
* Similar to outliner, do not change active element when selecting elements in range. */
|
|
|
|
|
if (agrp->flag & AGRP_SELECTED) {
|
|
|
|
|
if (selectmode != SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
|
|
|
|
|
if (pchan) {
|
|
|
|
|
ED_pose_bone_select(ob, pchan, true);
|
|
|
|
|
ED_pose_bone_select(ob, pchan, true, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (selectmode != SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP);
|
|
|
|
|
if (pchan) {
|
|
|
|
|
ED_pose_bone_select(ob, pchan, false);
|
|
|
|
|
ED_pose_bone_select(ob, pchan, false, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3347,14 +3497,19 @@ static int click_select_channel_fcurve(bAnimContext *ac,
|
|
|
|
|
/* inverse selection status of this F-Curve only */
|
|
|
|
|
fcu->flag ^= FCURVE_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
animchannel_select_range(ac, ale);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* select F-Curve by itself */
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
|
|
|
|
fcu->flag |= FCURVE_SELECTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
|
|
|
|
|
if (fcu->flag & FCURVE_SELECTED) {
|
|
|
|
|
/* if F-Curve is selected now, make F-Curve the 'active' one in the visible list.
|
|
|
|
|
* Similar to outliner, do not change active element when selecting elements in range. */
|
|
|
|
|
if ((fcu->flag & FCURVE_SELECTED) && (selectmode != SELECT_EXTEND_RANGE)) {
|
|
|
|
|
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3422,14 +3577,19 @@ static int click_select_channel_gplayer(bContext *C,
|
|
|
|
|
/* invert selection status of this layer only */
|
|
|
|
|
gpl->flag ^= GP_LAYER_SELECT;
|
|
|
|
|
}
|
|
|
|
|
else if (selectmode == SELECT_EXTEND_RANGE) {
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
|
|
|
|
|
animchannel_select_range(ac, ale);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* select layer by itself */
|
|
|
|
|
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
|
|
|
|
gpl->flag |= GP_LAYER_SELECT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* change active layer, if this is selected (since we must always have an active layer) */
|
|
|
|
|
if (gpl->flag & GP_LAYER_SELECT) {
|
|
|
|
|
/* change active layer, if this is selected (since we must always have an active layer).
|
|
|
|
|
* Similar to outliner, do not change active element when selecting elements in range. */
|
|
|
|
|
if ((gpl->flag & GP_LAYER_SELECT) && (selectmode != SELECT_EXTEND_RANGE)) {
|
|
|
|
|
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
|
|
|
|
|
/* update other layer status */
|
|
|
|
|
BKE_gpencil_layer_active_set(gpd, gpl);
|
|
|
|
@ -3478,7 +3638,7 @@ static int click_select_channel_masklayer(bAnimContext *ac,
|
|
|
|
|
static int mouse_anim_channels(bContext *C,
|
|
|
|
|
bAnimContext *ac,
|
|
|
|
|
const int channel_index,
|
|
|
|
|
const short /* eEditKeyframes_Select or -1 */ selectmode)
|
|
|
|
|
short /* eEditKeyframes_Select or -1 */ selectmode)
|
|
|
|
|
{
|
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
|
bAnimListElem *ale;
|
|
|
|
@ -3516,6 +3676,11 @@ static int mouse_anim_channels(bContext *C,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Change selection mode to single when no active element is found. */
|
|
|
|
|
if ((selectmode == SELECT_EXTEND_RANGE) && !animchannel_has_active_of_type(ac, ale->type)) {
|
|
|
|
|
selectmode = SELECT_INVERT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* action to take depends on what channel we've got */
|
|
|
|
|
/* WARNING: must keep this in sync with the equivalent function in nla_channels.c */
|
|
|
|
|
switch (ale->type) {
|
|
|
|
@ -3619,6 +3784,9 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
|
|
|
|
|
if (RNA_boolean_get(op->ptr, "extend")) {
|
|
|
|
|
selectmode = SELECT_INVERT;
|
|
|
|
|
}
|
|
|
|
|
else if (RNA_boolean_get(op->ptr, "extend_range")) {
|
|
|
|
|
selectmode = SELECT_EXTEND_RANGE;
|
|
|
|
|
}
|
|
|
|
|
else if (RNA_boolean_get(op->ptr, "children_only")) {
|
|
|
|
|
/* this is a bit of a special case for ActionGroups only...
|
|
|
|
|
* should it be removed or extended to all instead? */
|
|
|
|
@ -3672,6 +3840,13 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
|
|
|
|
|
prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", "");
|
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|
|
|
|
|
|
prop = RNA_def_boolean(ot->srna,
|
|
|
|
|
"extend_range",
|
|
|
|
|
false,
|
|
|
|
|
"Extend Range",
|
|
|
|
|
"Selection of active channel to clicked channel");
|
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|
|
|
|
|
|
/* Key-map: Enable with `Ctrl-Shift`. */
|
|
|
|
|
prop = RNA_def_boolean(ot->srna, "children_only", false, "Select Children Only", "");
|
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|