Fix T41507: Empty prevents image deletion
Also allow assigning `Object.data = None` from Python
This commit is contained in:
@@ -42,7 +42,7 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
|
||||
layout.prop(ob, "empty_draw_type", text="Display")
|
||||
|
||||
if ob.empty_draw_type == 'IMAGE':
|
||||
layout.template_ID(ob, "data", open="image.open")
|
||||
layout.template_ID(ob, "data", open="image.open", unlink="object.unlink_data")
|
||||
layout.template_image(ob, "data", ob.image_user, compact=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
@@ -576,24 +576,33 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
|
||||
|
||||
/* delete button */
|
||||
/* don't use RNA_property_is_unlink here */
|
||||
if (id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
|
||||
if (id && (flag & UI_ID_DELETE)) {
|
||||
/* allow unlink if 'unlinkop' is passed, even when 'PROP_NEVER_UNLINK' is set */
|
||||
but = NULL;
|
||||
|
||||
if (unlinkop) {
|
||||
but = uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
|
||||
/* so we can access the template from operators, font unlinking needs this */
|
||||
uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
|
||||
}
|
||||
else {
|
||||
but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
|
||||
TIP_("Unlink datablock "
|
||||
"(Shift + Click to set users to zero, data will then not be saved)"));
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
|
||||
if ((RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
|
||||
but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
|
||||
TIP_("Unlink datablock "
|
||||
"(Shift + Click to set users to zero, data will then not be saved)"));
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
|
||||
|
||||
if (RNA_property_flag(template->prop) & PROP_NEVER_NULL)
|
||||
uiButSetFlag(but, UI_BUT_DISABLED);
|
||||
if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) {
|
||||
uiButSetFlag(but, UI_BUT_DISABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((idfrom && idfrom->lib) || !editable)
|
||||
uiButSetFlag(but, UI_BUT_DISABLED);
|
||||
if (but) {
|
||||
if ((idfrom && idfrom->lib) || !editable) {
|
||||
uiButSetFlag(but, UI_BUT_DISABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (idcode == ID_TE)
|
||||
|
||||
@@ -72,6 +72,7 @@ void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
|
||||
|
||||
/* object_edit.c */
|
||||
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
|
||||
|
||||
@@ -243,6 +243,7 @@ void ED_operatortypes_object(void)
|
||||
WM_operatortype_append(OBJECT_OT_bake_image);
|
||||
WM_operatortype_append(OBJECT_OT_bake);
|
||||
WM_operatortype_append(OBJECT_OT_drop_named_material);
|
||||
WM_operatortype_append(OBJECT_OT_unlink_data);
|
||||
WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
|
||||
|
||||
WM_operatortype_append(OBJECT_OT_lod_add);
|
||||
|
||||
@@ -2399,3 +2399,55 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
|
||||
/* properties */
|
||||
RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
|
||||
}
|
||||
|
||||
static int object_unlink_data_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ID *id;
|
||||
PropertyPointerRNA pprop;
|
||||
|
||||
uiIDContextProperty(C, &pprop.ptr, &pprop.prop);
|
||||
|
||||
if (pprop.prop == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
id = pprop.ptr.id.data;
|
||||
|
||||
if (GS(id->name) == ID_OB) {
|
||||
Object *ob = (Object *)id;
|
||||
if (ob->data) {
|
||||
ID *id_data = ob->data;
|
||||
|
||||
if (GS(id_data->name) == ID_IM) {
|
||||
id_us_min(id_data);
|
||||
ob->data = NULL;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RNA_property_update(C, &pprop.ptr, pprop.prop);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Only for empty-image objects, this operator is needed
|
||||
*/
|
||||
void OBJECT_OT_unlink_data(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Unlink";
|
||||
ot->idname = "OBJECT_OT_unlink_data";
|
||||
ot->description = "";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = object_unlink_data_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ void IMAGE_OT_view_ndof(struct wmOperatorType *ot);
|
||||
|
||||
void IMAGE_OT_new(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_open(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_unlink(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_match_movie_length(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_replace(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_reload(struct wmOperatorType *ot);
|
||||
|
||||
@@ -370,8 +370,14 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
|
||||
Object *ob = (Object *)ptr->data;
|
||||
ID *id = value.data;
|
||||
|
||||
if (id == NULL || ob->mode & OB_MODE_EDIT)
|
||||
if (ob->mode & OB_MODE_EDIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* assigning NULL only for empties */
|
||||
if ((id == NULL) && (ob->type != OB_EMPTY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ob->type == OB_EMPTY) {
|
||||
if (ob->data) {
|
||||
@@ -379,7 +385,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
|
||||
ob->data = NULL;
|
||||
}
|
||||
|
||||
if (id && GS(id->name) == ID_IM) {
|
||||
if (!id || GS(id->name) == ID_IM) {
|
||||
id_us_plus(id);
|
||||
ob->data = id;
|
||||
}
|
||||
@@ -391,11 +397,10 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
|
||||
if (ob->data) {
|
||||
id_us_min((ID *)ob->data);
|
||||
}
|
||||
if (id) {
|
||||
/* no need to type-check here ID. this is done in the _typef() function */
|
||||
BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
|
||||
id_us_plus(id);
|
||||
}
|
||||
|
||||
/* no need to type-check here ID. this is done in the _typef() function */
|
||||
BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
|
||||
id_us_plus(id);
|
||||
|
||||
ob->data = id;
|
||||
test_object_materials(G.main, id);
|
||||
|
||||
Reference in New Issue
Block a user