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:
parent
83c8f996f1
commit
994da7077d
Notes:
blender-bot
2023-02-21 17:59:30 +01:00
Referenced by issue #95802, Library Override - Outliner UI/UX
|
@ -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, ®ion->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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue