ID Static Override: add basic generic UI tools to control override of properties.
This commit is contained in:
parent
e36b5f004d
commit
0007873645
|
@ -6759,6 +6759,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
|
|||
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
|
||||
bool is_array, is_array_component;
|
||||
uiStringInfo label = {BUT_GET_LABEL, NULL};
|
||||
wmOperatorType *ot;
|
||||
PointerRNA op_ptr;
|
||||
|
||||
/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
|
||||
/* return 0;*/
|
||||
|
@ -6785,11 +6787,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
|
|||
const PropertySubType subtype = RNA_property_subtype(prop);
|
||||
bool is_anim = RNA_property_animateable(ptr, prop);
|
||||
bool is_editable = RNA_property_editable(ptr, prop);
|
||||
bool is_overridable;
|
||||
/*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */
|
||||
bool is_set = RNA_property_is_set(ptr, prop);
|
||||
|
||||
/* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */
|
||||
uiLayoutSetContextFromBut(layout, but);
|
||||
RNA_property_override_status(ptr, prop, -1, &is_overridable, NULL, NULL, NULL);
|
||||
|
||||
/* second slower test, saved people finding keyframe items in menus when its not possible */
|
||||
if (is_anim)
|
||||
|
@ -6918,11 +6920,57 @@ static bool ui_but_menu(bContext *C, uiBut *but)
|
|||
ICON_NONE, "ANIM_OT_keyingset_button_remove");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_overridable) {
|
||||
/* Override Operators */
|
||||
uiItemS(layout);
|
||||
|
||||
if (but->flag & UI_BUT_OVERRIDEN) {
|
||||
if (is_array_component) {
|
||||
ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
|
||||
uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", true);
|
||||
uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", false);
|
||||
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
|
||||
ICON_X, "UI_OT_override_remove_button", "all", true);
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
|
||||
ICON_X, "UI_OT_override_remove_button", "all", false);
|
||||
}
|
||||
else {
|
||||
uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", false);
|
||||
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
|
||||
ICON_X, "UI_OT_override_remove_button", "all", true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (is_array_component) {
|
||||
ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
|
||||
uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", true);
|
||||
uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", false);
|
||||
}
|
||||
else {
|
||||
uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE,
|
||||
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
|
||||
RNA_boolean_set(&op_ptr, "all", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
|
||||
/* Property Operators */
|
||||
|
||||
|
||||
/* Copy Property Value
|
||||
* Paste Property Value */
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "BKE_layer.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library_override.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_text.h" /* for UI_OT_reports_to_text */
|
||||
#include "BKE_report.h"
|
||||
|
@ -452,6 +453,215 @@ static void UI_OT_unuse_property_button(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Note that we use different values for UI/UX than 'real' override operations, user does not care
|
||||
* whether it's added or removed for the differential operation e.g. */
|
||||
enum {
|
||||
UIOverride_Type_NOOP = 0,
|
||||
UIOverride_Type_Replace = 1,
|
||||
UIOverride_Type_Difference = 2, /* Add/subtract */
|
||||
UIOverride_Type_Factor = 3, /* Multiply */
|
||||
/* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
|
||||
};
|
||||
|
||||
static EnumPropertyItem override_type_items[] = {
|
||||
{UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
|
||||
"'No-Operation', place holder preventing automatic override to ever affect the property"},
|
||||
{UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
|
||||
{UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
|
||||
{UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static int override_type_set_button_poll(bContext *C)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
int index;
|
||||
bool is_overridable;
|
||||
|
||||
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
|
||||
|
||||
RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL);
|
||||
|
||||
return (ptr.data && prop && is_overridable);
|
||||
}
|
||||
|
||||
static int override_type_set_button_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
int index;
|
||||
bool created;
|
||||
const bool all = RNA_boolean_get(op->ptr, "all");
|
||||
const int op_type = RNA_enum_get(op->ptr, "type");
|
||||
|
||||
short operation;
|
||||
|
||||
switch(op_type) {
|
||||
case UIOverride_Type_NOOP:
|
||||
operation = IDOVERRIDESTATIC_OP_NOOP;
|
||||
break;
|
||||
case UIOverride_Type_Replace:
|
||||
operation = IDOVERRIDESTATIC_OP_REPLACE;
|
||||
break;
|
||||
case UIOverride_Type_Difference:
|
||||
operation = IDOVERRIDESTATIC_OP_ADD; /* override code will automatically switch to subtract if needed. */
|
||||
break;
|
||||
case UIOverride_Type_Factor:
|
||||
operation = IDOVERRIDESTATIC_OP_MULTIPLY;
|
||||
break;
|
||||
default:
|
||||
operation = IDOVERRIDESTATIC_OP_REPLACE;
|
||||
BLI_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* try to reset the nominated setting to its default value */
|
||||
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
|
||||
|
||||
BLI_assert(ptr.id.data != NULL);
|
||||
|
||||
if (all) {
|
||||
index = -1;
|
||||
}
|
||||
|
||||
IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
|
||||
&ptr, prop, operation, index, true, NULL, &created);
|
||||
if (!created) {
|
||||
opop->operation = operation;
|
||||
}
|
||||
|
||||
return operator_button_property_finish(C, &ptr, prop);
|
||||
}
|
||||
|
||||
static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
|
||||
}
|
||||
|
||||
static void UI_OT_override_type_set_button(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Define Override Type";
|
||||
ot->idname = "UI_OT_override_type_set_button";
|
||||
ot->description = "Create an override operation, or set the type of an existing one";
|
||||
|
||||
/* callbacks */
|
||||
ot->poll = override_type_set_button_poll;
|
||||
ot->exec = override_type_set_button_exec;
|
||||
ot->invoke = override_type_set_button_invoke;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
|
||||
ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
|
||||
"Type", "Type of override operation");
|
||||
/* TODO: add itemf callback, not all aoptions are available for all data types... */
|
||||
}
|
||||
|
||||
|
||||
static int override_remove_button_poll(bContext *C)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
int index;
|
||||
bool is_overridden;
|
||||
|
||||
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
|
||||
|
||||
RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL);
|
||||
|
||||
return (ptr.data && ptr.id.data && prop && is_overridden);
|
||||
}
|
||||
|
||||
static int override_remove_button_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr, id_refptr, src;
|
||||
PropertyRNA *prop;
|
||||
int index;
|
||||
const bool all = RNA_boolean_get(op->ptr, "all");
|
||||
|
||||
/* try to reset the nominated setting to its default value */
|
||||
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
|
||||
|
||||
ID *id = ptr.id.data;
|
||||
IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
|
||||
BLI_assert(oprop != NULL);
|
||||
BLI_assert(id != NULL && id->override_static != NULL);
|
||||
|
||||
const bool is_template = (id->override_static->reference == NULL);
|
||||
|
||||
/* We need source (i.e. linked data) to restore values of deleted overrides...
|
||||
* If this is an override template, we obviously do not need to restore anything. */
|
||||
if (!is_template) {
|
||||
RNA_id_pointer_create(id->override_static->reference, &id_refptr);
|
||||
if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
|
||||
BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
|
||||
}
|
||||
}
|
||||
|
||||
if (!all && index != -1) {
|
||||
bool is_strict_find;
|
||||
/* Remove override operation for given item, add singular operations for the other items as needed. */
|
||||
IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
|
||||
oprop, NULL, NULL, index, index, false, &is_strict_find);
|
||||
BLI_assert(opop != NULL);
|
||||
if (!is_strict_find) {
|
||||
/* No specific override operation, we have to get generic one,
|
||||
* and create item-specific override operations for all but given index, before removing generic one. */
|
||||
for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
|
||||
if (idx != index) {
|
||||
BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
BKE_override_static_property_operation_delete(oprop, opop);
|
||||
if (!is_template) {
|
||||
RNA_property_copy(&ptr, &src, prop, index);
|
||||
}
|
||||
if (BLI_listbase_is_empty(&oprop->operations)) {
|
||||
BKE_override_static_property_delete(id->override_static, oprop);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Just remove whole generic override operation of this property. */
|
||||
BKE_override_static_property_delete(id->override_static, oprop);
|
||||
if (!is_template) {
|
||||
RNA_property_copy(&ptr, &src, prop, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return operator_button_property_finish(C, &ptr, prop);
|
||||
}
|
||||
|
||||
static void UI_OT_override_remove_button(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Remove Override";
|
||||
ot->idname = "UI_OT_override_remove_button";
|
||||
ot->description = "Remove an override operation";
|
||||
|
||||
/* callbacks */
|
||||
ot->poll = override_remove_button_poll;
|
||||
ot->exec = override_remove_button_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Copy To Selected Operator ------------------------ */
|
||||
|
||||
bool UI_context_copy_to_selected_list(
|
||||
|
@ -1243,6 +1453,8 @@ void ED_operatortypes_ui(void)
|
|||
WM_operatortype_append(UI_OT_unset_property_button);
|
||||
WM_operatortype_append(UI_OT_use_property_button);
|
||||
WM_operatortype_append(UI_OT_unuse_property_button);
|
||||
WM_operatortype_append(UI_OT_override_type_set_button);
|
||||
WM_operatortype_append(UI_OT_override_remove_button);
|
||||
WM_operatortype_append(UI_OT_copy_to_selected_button);
|
||||
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
|
||||
WM_operatortype_append(UI_OT_drop_color);
|
||||
|
|
Loading…
Reference in New Issue