Outliner: Add icon column to toggle if library overrides are editable

Adds a column to the right in the Library Overrides Hierarchies view
mode to toggle editability of library overrides.

Note that making a library override non-editable currently involves
clearing all overridden properties. This is an arguable design choice,
we should probably at least warn the user before doing this.

Part of T95802.

Reviewed by: Bastien Montagne

Differential Revision: https://developer.blender.org/D14653
This commit is contained in:
Julian Eisel 2022-04-26 22:30:33 +02:00
parent 83c8f996f1
commit 994da7077d
Notes: blender-bot 2023-02-21 17:59:30 +01:00
Referenced by issue #95802, Library Override - Outliner UI/UX
4 changed files with 139 additions and 15 deletions

View File

@ -34,6 +34,7 @@
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@ -66,6 +67,7 @@
#include "outliner_intern.hh"
#include "tree/tree_display.hh"
#include "tree/tree_element.hh"
#include "tree/tree_element_id.hh"
#include "tree/tree_element_overrides.hh"
#include "tree/tree_element_rna.hh"
@ -1835,6 +1837,69 @@ static void outliner_draw_overrides_rna_buts(uiBlock *block,
}
}
static bool outliner_but_identity_cmp_context_id_fn(const uiBut *a, const uiBut *b)
{
const PointerRNA *idptr_a = UI_but_context_ptr_get(a, "id", &RNA_ID);
const PointerRNA *idptr_b = UI_but_context_ptr_get(b, "id", &RNA_ID);
if (!idptr_a || !idptr_b) {
return false;
}
const ID *id_a = (const ID *)idptr_a->data;
const ID *id_b = (const ID *)idptr_b->data;
/* Using session UUID to compare is safer than using the pointer. */
return id_a->session_uuid == id_b->session_uuid;
}
static void outliner_draw_overrides_restrictbuts(Main *bmain,
uiBlock *block,
const ARegion *region,
const SpaceOutliner *space_outliner,
const ListBase *lb,
const int x)
{
LISTBASE_FOREACH (const TreeElement *, te, lb) {
const TreeStoreElem *tselem = TREESTORE(te);
if (TSELEM_OPEN(tselem, space_outliner)) {
outliner_draw_overrides_restrictbuts(bmain, block, region, space_outliner, &te->subtree, x);
}
if (!outliner_is_element_in_view(te, &region->v2d)) {
continue;
}
TreeElementID *te_id = tree_element_cast<TreeElementID>(te);
if (!te_id) {
continue;
}
ID &id = te_id->get_ID();
BLI_assert(ID_IS_OVERRIDE_LIBRARY(&id));
if (ID_IS_LINKED(&id)) {
continue;
}
const bool is_system_override = BKE_lib_override_library_is_system_defined(bmain, &id);
const BIFIconID icon = is_system_override ? ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE :
ICON_LIBRARY_DATA_OVERRIDE;
uiBut *but = uiDefIconButO(block,
UI_BTYPE_BUT,
"ED_OT_lib_id_override_editable_toggle",
WM_OP_EXEC_DEFAULT,
icon,
x,
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
"");
PointerRNA idptr;
RNA_id_pointer_create(&id, &idptr);
UI_but_context_ptr_set(block, but, "id", &idptr);
UI_but_func_identity_compare_set(but, outliner_but_identity_cmp_context_id_fn);
UI_but_flag_enable(but, UI_BUT_DRAG_LOCK);
}
}
static bool outliner_draw_overrides_warning_buts(uiBlock *block,
ARegion *region,
SpaceOutliner *space_outliner,
@ -3899,12 +3964,6 @@ void draw_outliner(const bContext *C)
/* Default to no emboss for outliner UI. */
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
/* Draw overrides status columns. */
outliner_draw_overrides_warning_buts(
block, region, space_outliner, &space_outliner->tree, true);
}
if (space_outliner->outlinevis == SO_DATA_API) {
int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
/* draw rna buttons */
@ -3919,14 +3978,23 @@ void draw_outliner(const bContext *C)
/* draw user toggle columns */
outliner_draw_userbuts(block, region, space_outliner, &space_outliner->tree);
}
else if ((space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) &&
(space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES)) {
UI_block_emboss_set(block, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE);
else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
/* Draw overrides status columns. */
outliner_draw_overrides_warning_buts(
block, region, space_outliner, &space_outliner->tree, true);
const int x = region->v2d.cur.xmax - right_column_width;
outliner_draw_separator(region, x);
outliner_draw_overrides_rna_buts(block, region, space_outliner, &space_outliner->tree, x);
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
if (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES) {
UI_block_emboss_set(block, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE);
outliner_draw_overrides_rna_buts(block, region, space_outliner, &space_outliner->tree, x);
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
}
else if (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_HIERARCHIES) {
outliner_draw_overrides_restrictbuts(
mainvar, block, region, space_outliner, &space_outliner->tree, x);
}
}
else if (right_column_width > 0.0f) {
/* draw restriction columns */

View File

@ -324,10 +324,14 @@ float outliner_right_columns_width(const SpaceOutliner *space_outliner)
case SO_LIBRARIES:
return 0.0f;
case SO_OVERRIDES_LIBRARY:
if (space_outliner->lib_override_view_mode != SO_LIB_OVERRIDE_VIEW_PROPERTIES) {
return 0.0f;
switch ((eSpaceOutliner_LibOverrideViewMode)space_outliner->lib_override_view_mode) {
case SO_LIB_OVERRIDE_VIEW_PROPERTIES:
num_columns = OL_RNA_COL_SIZEX / UI_UNIT_X;
break;
case SO_LIB_OVERRIDE_VIEW_HIERARCHIES:
num_columns = 1;
break;
}
num_columns = OL_RNA_COL_SIZEX / UI_UNIT_X;
break;
case SO_ID_ORPHANS:
num_columns = 3;

View File

@ -18,6 +18,8 @@ set(INC
../../../../intern/clog
../../../../intern/glew-mx
../../../../intern/guardedalloc
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
)
@ -110,3 +112,6 @@ if(WITH_PYTHON)
endif()
blender_add_lib(bf_editor_util "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.h
add_dependencies(bf_editor_util bf_rna)

View File

@ -17,6 +17,7 @@
#include "BKE_context.h"
#include "BKE_icons.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_report.h"
@ -28,6 +29,7 @@
#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_prototypes.h"
#include "UI_interface.h"
@ -294,6 +296,50 @@ static void ED_OT_lib_id_unlink(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
static bool lib_id_override_editable_toggle_poll(bContext *C)
{
const PointerRNA id_ptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
const ID *id = static_cast<ID *>(id_ptr.data);
return id && ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id);
}
static int lib_id_override_editable_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
const PointerRNA id_ptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
ID *id = static_cast<ID *>(id_ptr.data);
const bool is_system_override = BKE_lib_override_library_is_system_defined(bmain, id);
if (is_system_override) {
/* A system override is not editable. Make it an editable (non-system-defined) one. */
id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
}
else {
/* Reset override, which makes it non-editable (i.e. a system define override). */
BKE_lib_override_library_id_reset(bmain, id, true);
}
WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, nullptr);
return OPERATOR_FINISHED;
}
static void ED_OT_lib_id_override_editable_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Library Override Editable";
ot->description = "Set if this library override data-block can be edited";
ot->idname = "ED_OT_lib_id_override_editable_toggle";
/* api callbacks */
ot->poll = lib_id_override_editable_toggle_poll;
ot->exec = lib_id_override_editable_toggle_exec;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -331,6 +377,7 @@ void ED_operatortypes_edutils()
WM_operatortype_append(ED_OT_lib_id_fake_user_toggle);
WM_operatortype_append(ED_OT_lib_id_unlink);
WM_operatortype_append(ED_OT_lib_id_override_editable_toggle);
WM_operatortype_append(ED_OT_flush_edits);