[Bf-blender-cvs] [e79d9048f34] id_override_static: ID Static Override: add basic generic UI tools to control override of properties.

Bastien Montagne noreply at git.blender.org
Wed Nov 29 17:45:41 CET 2017


Commit: e79d9048f34b0b213780db5dadc472d4d04a8b56
Author: Bastien Montagne
Date:   Wed Nov 29 17:03:52 2017 +0100
Branches: id_override_static
https://developer.blender.org/rBe79d9048f34b0b213780db5dadc472d4d04a8b56

ID Static Override: add basic generic UI tools to control override of properties.

===================================================================

M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_ops.c

===================================================================

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 2e9dae36d96..a4ce0e2f4a8 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -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 */
 		
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 5913f1c48f5..1866cebcbb8 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -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, 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list