Cleanup: Simplify outliner context menu building queries

- Remove unnecessary calls to `get_element_operation_type()` (result
  wasn't used).
- Remove branches/checks for cases that couldn't possibly happen.
  (assert instead).
- Ensure all return arguments are set so caller can't make the mistake
  of forgetting that.
- Early exit instead of big `if` block.
- Use `const`.
This commit is contained in:
Julian Eisel 2022-09-08 16:20:53 +02:00
parent 406243c2fd
commit 8f6a38ed7e
Notes: blender-bot 2023-02-14 01:11:05 +01:00
Referenced by issue #101007, Outliner: New context menu building design
1 changed files with 84 additions and 107 deletions

View File

@ -104,97 +104,96 @@ using blender::Vector;
* \{ */
static void get_element_operation_type(
TreeElement *te, int *scenelevel, int *objectlevel, int *idlevel, int *datalevel)
const TreeElement *te, int *scenelevel, int *objectlevel, int *idlevel, int *datalevel)
{
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
/* Layer collection points to collection ID. */
if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0) {
*datalevel = tselem->type;
}
else if (*datalevel != tselem->type) {
*datalevel = -1;
}
}
else {
const int idcode = (int)GS(tselem->id->name);
bool is_standard_id = false;
switch ((ID_Type)idcode) {
case ID_SCE:
*scenelevel = 1;
break;
case ID_OB:
*objectlevel = 1;
break;
*scenelevel = *objectlevel = *idlevel = *datalevel = 0;
case ID_ME:
case ID_CU_LEGACY:
case ID_MB:
case ID_LT:
case ID_LA:
case ID_AR:
case ID_CA:
case ID_SPK:
case ID_MA:
case ID_TE:
case ID_IP:
case ID_IM:
case ID_SO:
case ID_KE:
case ID_WO:
case ID_AC:
case ID_TXT:
case ID_GR:
case ID_LS:
case ID_LI:
case ID_VF:
case ID_NT:
case ID_BR:
case ID_PA:
case ID_GD:
case ID_MC:
case ID_MSK:
case ID_PAL:
case ID_PC:
case ID_CF:
case ID_WS:
case ID_LP:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_SIM:
is_standard_id = true;
break;
case ID_WM:
case ID_SCR:
/* Those are ignored here. */
/* NOTE: while Screens should be manageable here, deleting a screen used by a workspace
* will cause crashes when trying to use that workspace, so for now let's play minimal,
* safe change. */
break;
}
if (idcode == ID_NLA) {
/* Fake one, not an actual ID type... */
const TreeStoreElem *tselem = TREESTORE(te);
if ((tselem->flag & TSE_SELECTED) == 0) {
return;
}
/* Layer collection points to collection ID. */
if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
*datalevel = tselem->type;
}
else {
const int idcode = (int)GS(tselem->id->name);
bool is_standard_id = false;
switch ((ID_Type)idcode) {
case ID_SCE:
*scenelevel = 1;
break;
case ID_OB:
*objectlevel = 1;
break;
case ID_ME:
case ID_CU_LEGACY:
case ID_MB:
case ID_LT:
case ID_LA:
case ID_AR:
case ID_CA:
case ID_SPK:
case ID_MA:
case ID_TE:
case ID_IP:
case ID_IM:
case ID_SO:
case ID_KE:
case ID_WO:
case ID_AC:
case ID_TXT:
case ID_GR:
case ID_LS:
case ID_LI:
case ID_VF:
case ID_NT:
case ID_BR:
case ID_PA:
case ID_GD:
case ID_MC:
case ID_MSK:
case ID_PAL:
case ID_PC:
case ID_CF:
case ID_WS:
case ID_LP:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_SIM:
is_standard_id = true;
}
break;
case ID_WM:
case ID_SCR:
/* Those are ignored here. */
/* NOTE: while Screens should be manageable here, deleting a screen used by a workspace
* will cause crashes when trying to use that workspace, so for now let's play minimal,
* safe change. */
break;
}
if (idcode == ID_NLA) {
/* Fake one, not an actual ID type... */
is_standard_id = true;
}
if (is_standard_id) {
if (*idlevel == 0) {
*idlevel = idcode;
}
else if (*idlevel != idcode) {
*idlevel = -1;
}
if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
*datalevel = 0;
}
}
if (is_standard_id) {
*idlevel = idcode;
}
}
/* Return values are exclusive, only one may be non-null. */
BLI_assert(((*scenelevel != 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel == 0)) ||
((*scenelevel == 0) && (*objectlevel != 0) && (*idlevel == 0) && (*datalevel == 0)) ||
((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel != 0) && (*datalevel == 0)) ||
((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel != 0)) ||
/* All null. */
((*scenelevel == 0) && (*objectlevel == 0) && (*idlevel == 0) && (*datalevel == 0)));
}
static TreeElement *get_target_element(SpaceOutliner *space_outliner)
static TreeElement *get_target_element(const SpaceOutliner *space_outliner)
{
TreeElement *te = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE);
@ -1699,16 +1698,12 @@ static int outliner_liboverride_operation_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
/* check for invalid states */
if (space_outliner == nullptr) {
return OPERATOR_CANCELLED;
}
TreeElement *te = get_target_element(space_outliner);
get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel);
const eOutlinerLibOpSelectionSet selection_set = static_cast<eOutlinerLibOpSelectionSet>(
RNA_enum_get(op->ptr, "selection_set"));
const eOutlinerLibOverrideOpTypes event = static_cast<eOutlinerLibOverrideOpTypes>(
@ -2806,16 +2801,12 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
/* check for invalid states */
if (space_outliner == nullptr) {
return OPERATOR_CANCELLED;
}
TreeElement *te = get_target_element(space_outliner);
get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel);
eOutlinerLibOpTypes event = (eOutlinerLibOpTypes)RNA_enum_get(op->ptr, "type");
switch (event) {
case OL_LIB_DELETE: {
@ -3338,7 +3329,6 @@ static int outliner_operator_menu(bContext *C, const char *opname)
}
static int do_outliner_operation_event(bContext *C,
ReportList *reports,
ARegion *region,
SpaceOutliner *space_outliner,
TreeElement *te)
@ -3361,10 +3351,6 @@ static int do_outliner_operation_event(bContext *C,
get_element_operation_type(te, &scenelevel, &objectlevel, &idlevel, &datalevel);
if (scenelevel) {
if (objectlevel || datalevel || idlevel) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
return outliner_operator_menu(C, "OUTLINER_OT_scene_operation");
}
if (objectlevel) {
@ -3372,11 +3358,6 @@ static int do_outliner_operation_event(bContext *C,
return OPERATOR_FINISHED;
}
if (idlevel) {
if (idlevel == -1 || datalevel) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
switch (idlevel) {
case ID_GR:
WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
@ -3391,10 +3372,6 @@ static int do_outliner_operation_event(bContext *C,
}
}
else if (datalevel) {
if (datalevel == -1) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
if (datalevel == TSE_ANIM_DATA) {
return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation");
}
@ -3426,7 +3403,7 @@ static int do_outliner_operation_event(bContext *C,
return OPERATOR_CANCELLED;
}
static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event)
static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
@ -3447,7 +3424,7 @@ static int outliner_operation(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
return do_outliner_operation_event(C, op->reports, region, space_outliner, hovered_te);
return do_outliner_operation_event(C, region, space_outliner, hovered_te);
}
void OUTLINER_OT_operation(wmOperatorType *ot)